例如,使用winamp(至少在Windows上),您可以在后台以winamp播放全屏游戏,并使用媒体按钮*控制声音。Winamp不需要聚焦,可以使游戏继续全屏显示。
我更喜欢用Java编写此代码,但这可能行不通(在Java afaik中很难捕获没有重点的击键),因此任何C#解决方案也都可以。
因此,基本问题是:如何在没有重点的情况下捕获击键?
*)我相信“后退/前进/停止/邮件/搜索/收藏夹/网站/主页”按钮称为媒体按钮,但欢迎使用更好的名称:)。
低级Windows挂钩是一种实现方法。这是一篇文章,这里是来自MSDN的更多信息。
这是该代码的局部视图:
private IntPtr LowLevelKeyboardHook(int nCode, WindowsMessages wParam, [In] KBDLLHOOKSTRUCT lParam) { bool callNext = true; bool isKeyDown = (wParam == WindowsMessages.KEYDOWN || wParam == WindowsMessages.SYSKEYDOWN); bool isKeyUp = (wParam == WindowsMessages.KEYUP || wParam == WindowsMessages.SYSKEYUP); if ((nCode >= 0) && (isKeyDown || isKeyUp)) { // the virtual key codes and the winforms Keys have the same enumeration // so we can freely cast back and forth between them Keys key = (Keys)lParam.vkCode; // Do your other processing here... } // if any handler returned false, trap the message return (callNext) ? User32.CallNextHookEx(_mainHook, nCode, wParam, lParam) : _nullNext; } /// <summary> /// Registers the user's LowLevelKeyboardProc with the system in order to /// intercept any keyboard events before processed in the regular fashion. /// This can be used to log all keyboard events or ignore them. /// </summary> /// <param name="hook">Callback function to call whenever a keyboard event occurs.</param> /// <returns>The IntPtr assigned by the Windows's sytem that defines the callback.</returns> private IntPtr RegisterLowLevelHook(LowLevelKeyboardProc hook) { IntPtr handle = IntPtr.Zero; using (Process currentProcess = Process.GetCurrentProcess()) using (ProcessModule currentModule = currentProcess.MainModule) { IntPtr module = Kernel32.GetModuleHandle(currentModule.ModuleName); handle = User32.SetWindowsHookEx(HookType.KEYBOARD_LL, hook, module, 0); } return handle; } /// <summary> /// Unregisters a previously registered callback from the low-level chain. /// </summary> /// <param name="hook">IntPtr previously assigned to the low-level chain. /// Users should have stored the value given by /// <see cref="Drs.Interop.Win32.LowLevelKeyboard.RegisterLowLevelHook"/>, /// and use that value as the parameter into this function.</param> /// <returns>True if the hook was removed, false otherwise.</returns> private bool UnregisterLowLevelHook(IntPtr hook) { return User32.UnhookWindowsHookEx(hook); }
只需实现所需的所有P / Invoke声明,它就可以工作。我在应用程序中使用了这种方法,并且效果很好。