How to hook Win + Tab using LowLevelKeyboardHook

坚强是说给别人听的谎言 提交于 2019-12-10 02:21:31

问题


In a few words: blocking Win up after Win + Tab makes Windows think Win is still down, so then pressing S with the Win key up for example will open the search charm rather than just type "s"... until the user presses Win again. Not blocking it means the Windows Start menu will show up. I'm in a conundrum!


I have no trouble hooking into shortcuts using Alt + Tab using LowLevelKeyboardHook, or Win + Some Ubounded Key using RegisterHotKey. The problem happens only with the Win key using LowLevelKeyboardHook.

In the example below, I'm taking over the Win up event when the Win + Tab combination is detected. This results in making every following keystrokes behave as if the Win key was still down.

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode != HC_ACTION)
                return CallNextHookEx(_hookID, nCode, wParam, lParam);

            var keyInfo = (Kbdllhookstruct)Marshal.PtrToStructure(lParam, typeof(Kbdllhookstruct));

            if (keyInfo.VkCode == VK_LWIN)
            {
                if (wParam == (IntPtr)WM_KEYDOWN) {
                    _isWinDown = true;
                } else {
                    _isWinDown = false;

                    if (_isWinTabDetected) {
                        _isWinTabDetected = false;
                        return (IntPtr)1;
                    }
                }
            }
            else if (keyInfo.VkCode == VK_TAB && _isWinDown) {
                _isWinTabDetected = true;

                if (wParam == (IntPtr)WM_KEYDOWN) {
                    return (IntPtr)1;
                } else {
                    _isWinTabDetected = true;
                    Console.WriteLine("WIN + TAB Pressed");
                    return (IntPtr)1;
                }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }
}

You can find the complete code here (note that it should replace your Program.cs in an empty WinForms project to run): https://gist.github.com/christianrondeau/bdd03a3dc32a7a718d62 - press Win + Tab and the Form title should update each time the shortcut is pressed.

Note that the intent of hooking into this specific combination is to provide an Alt + Tab alternative without replacing Alt + Tab itself. An answer providing the ability to launching custom code using Win + Tab will also be accepted.

Here are my ideas, for which I could not find documentation. All would potentially answer my question successfully.

  • Tell Windows to "cancel" the Win up without actually triggering it
  • Prevent Windows from launching the Start menu once
  • Hook directly in the Windows' Win + event rather than manually hooking into the keystrokes (This would be by far my first choice if that exists)

回答1:


This appears to do exactly what you want (omit RWin if you wish).

Please be considerate and unregister this KB hook when your app loses focus!

    [DllImport("user32.dll")]
    static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode == HC_ACTION)
        {
            var keyInfo = (Kbdllhookstruct) Marshal.PtrToStructure(lParam, typeof (Kbdllhookstruct));
            if ((int) wParam == WM_KEYDOWN
                && keyInfo.VkCode == VK_TAB
                && (GetAsyncKeyState(Keys.LWin) < 0 || GetAsyncKeyState(Keys.RWin) < 0))
            {
                _mainForm.Text = "Win + Tab was pressed " + (++_winTabPressCounter) + " times";
                return (IntPtr) 1;
            }
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

I tried several things before discovering this technique. This post was the most helpful https://stackoverflow.com/a/317550/55721




回答2:


System need to know you release the Windows key. I check the difference between my own hook who doesn't have this problem and the only diffence between your and mine is this line :

if (_isWinTabDetected) {
    _isWinTabDetected = false;
     return (IntPtr)1; //THIS LINE 
}


来源:https://stackoverflow.com/questions/27181125/how-to-hook-win-tab-using-lowlevelkeyboardhook

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!