我正在开发一个基于 WPF 的小型程序,用于通过使用挂钩实现的系统范围的热键启动应用程序。我在 C# 和 Visual Studio 2010 中实现它。
当我检测到特定的按键时,我使用 Process.Start(...) 来运行应用程序。这在 Visual Studio 处于活动状态时工作正常,正如我所料,将新应用程序放置在具有输入焦点的前台。如果我的启动器在后台(在另一个活动程序之后),它仍然会检测到密钥并正确启动应用程序,在其他所有内容之前。
问题是,当我在没有激活 Visual Studio 的情况下运行启动器时,并且我的启动器应用程序不在前面时,它也不会启动应用程序。它们出现在启动器前面,但在活动应用程序后面。
我可以看到其他软件,如 AutoHotkey,能够通过这种行为进行热键启动,但我看不出我做错了什么。
更新:刚刚想出了一个在我的开发环境中有效的解决方案。我首先使用启动器主窗口句柄通过 Windows API RegisterHotKey 注册一个全局热键。密钥可以是任何密钥,但应该是通常在物理上不存在的密钥,在我的情况下为 F24。然后,每当我通过应该启动应用程序的挂钩检测到按键时,我首先调用 keybd_event 来“伪造”热键的按键。
对于 WPF 使用:
keybd_event((byte)KeyInterop.VirtualKeyFromKey(Key.F24),0,KEYEVENTF_KEYUP,0);
对于 WinForms 使用:
keybd_event((byte)Keys.F24,0,KEYEVENTF_KEYUP,0);
这将为启动器带来足够的关注,以便 Process.Start(...) 使执行的程序位于前面。它不会将启动器窗口置于前面,也不会使启动器接受输入。
如果在 keybd_event() 之后在主窗口上调用 Activate(),这会将主窗口置于前面并允许键盘输入,就像用户切换了任务一样。