Capturing keystrokes without focus

后端 未结 2 1102
伪装坚强ぢ
伪装坚强ぢ 2020-12-15 00:18

E.g. with winamp (on Windows at least), you can play a game fullscreen with winamp in the background, and use the media buttons* to control the sound. Winamp doesn\'t need t

2条回答
  •  醉话见心
    2020-12-15 00:50

    Low-Level windows hooks is one way to do it. Here is one article and here is a little more info from MSDN.

    This is a partial view of what that code can look like:

        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;
        }
    
    
        /// 
        /// 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.
        /// 
        /// Callback function to call whenever a keyboard event occurs.
        /// The IntPtr assigned by the Windows's sytem that defines the callback.
        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;
        }
    
        /// 
        /// Unregisters a previously registered callback from the low-level chain.
        /// 
        /// IntPtr previously assigned to the low-level chain.
        /// Users should have stored the value given by 
        /// ,
        /// and use that value as the parameter into this function.
        /// True if the hook was removed, false otherwise.
        private bool UnregisterLowLevelHook(IntPtr hook)
        {
            return User32.UnhookWindowsHookEx(hook);
        }
    

    Just implement all the P/Invoke declarations needed, and it should work. I use this approach in my application and it works fine.

提交回复
热议问题