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)
if (wParam == (IntPtr)WM_KEYDOWN) { return (IntPtr)1; }
and the otherreturn (IntPtr)1;
in theif (keyInfo.VkCode == VK_LWIN)
block, and that worked too, though I think your code is simpler and cleaner. I've been stuck for 9 months on this, so my heartfelt thanks for taking the time to look into this! (And the solution was simple, obviously...) – Hyperborean