diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp index c7cc3841..67a18d48 100644 --- a/HookFilter/HookFilter.cpp +++ b/HookFilter/HookFilter.cpp @@ -2,40 +2,65 @@ // https://stackoverflow.com/questions/2490577/suppress-task-switch-keys-winkey-alt-tab-alt-esc-ctrl-esc-using-low-level-k +static HWND g_hFrameWindow = (HWND)0; + // NB. __stdcall (or WINAPI) and extern "C": // . symbol is decorated as _@bytes // . so use the #pragma to create an undecorated alias for our symbol extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc( _In_ int nCode, _In_ WPARAM wParam, - _In_ LPARAM lParam -) + _In_ LPARAM lParam) { #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) - if (nCode >= 0) + if (nCode == HC_ACTION) { bool suppress = false; PKBDLLHOOKSTRUCT pKbdLlHookStruct = (PKBDLLHOOKSTRUCT) lParam; + UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN; + LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state - // Suppress alt-tab. - if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + // Note about PostMessage() and use of VkKeyScan(): + // . Convert the ascii code to virtual key code, so that the message pump can do TranslateMessage() + // . NB. From MSDN for "WM_KEYDOWN" && "WM_KEYUP" : "Applications must pass wParam to TranslateMessage without altering it at all." + + // Suppress alt-tab + if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + { + PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x09)), newlParam); suppress = true; + } - // Suppress alt-escape. - if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + // Suppress alt-escape + if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + { + PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x1B)), newlParam); suppress = true; + } - // Suppress ctrl-escape. + // Suppress alt-space + if (pKbdLlHookStruct->vkCode == VK_SPACE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + { + PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x20)), newlParam); + suppress = true; + } + + // Suppress ctrl-escape bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0; if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown) suppress = true; - // Suppress keys by returning 1. + // Suppress keys by returning 1 if (suppress) return 1; } return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam); } + +extern "C" __declspec(dllexport) void __cdecl RegisterHWND(HWND hWnd) +{ + g_hFrameWindow = hWnd; +} diff --git a/HookFilter/HookFilter.vcproj b/HookFilter/HookFilter.vcproj index df4e8951..61bb8edb 100644 --- a/HookFilter/HookFilter.vcproj +++ b/HookFilter/HookFilter.vcproj @@ -2,7 +2,7 @@ = VK_F1) && (wparam <= VK_F8) && (buttondown == -1)) @@ -1399,6 +1400,8 @@ LRESULT CALLBACK FrameWndProc ( break; case WM_KEYUP: + KeybSpecialKeyup(wparam); + // Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8 if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1)) { diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp index 53a91cfb..3261f52e 100644 --- a/source/Keyboard.cpp +++ b/source/Keyboard.cpp @@ -389,6 +389,58 @@ static char ClipboardCurrChar(bool bIncPtr) //=========================================================================== +// For AKD (Any Key Down), need special handling for the hooked key combos(*), as GetKeyState() doesn't detect the keys as being down. +// (*) ALT+TAB, ALT+ESCAPE, ALT+SPACE + +static enum {AKD_TAB=0, AKD_ESCAPE, AKD_SPACE}; +static bool g_specialAKD[3] = {false,false,false}; + +void KeybSpecialKeydown(DWORD wparam) +{ + switch (wparam) + { + case VK_TAB: + g_specialAKD[AKD_TAB] = true; + break; + case VK_ESCAPE: + g_specialAKD[AKD_ESCAPE] = true; + break; + case VK_SPACE: + g_specialAKD[AKD_SPACE] = true; + break; + }; +} + +void KeybSpecialKeyup(DWORD wparam) +{ + switch (wparam) + { + case VK_TAB: + g_specialAKD[AKD_TAB] = false; + break; + case VK_ESCAPE: + g_specialAKD[AKD_ESCAPE] = false; + break; + case VK_SPACE: + g_specialAKD[AKD_SPACE] = false; + break; + }; +} + +static bool IsSpecialAKD(int lastvirtkey) +{ + if (VK_TAB == lastvirtkey) + return g_specialAKD[AKD_TAB]; + else if (VK_ESCAPE == lastvirtkey) + return g_specialAKD[AKD_ESCAPE]; + else if (VK_SPACE == lastvirtkey) + return g_specialAKD[AKD_SPACE]; + + return false; +} + +//=========================================================================== + BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG) { LogFileTimeUntilFirstKeyRead(); @@ -428,6 +480,9 @@ BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG) keywaiting = 0; + if (IsSpecialAKD(lastvirtkey)) + return keycode | 0x80; + return keycode | ((GetKeyState(lastvirtkey) < 0) ? 0x80 : 0); } diff --git a/source/Keyboard.h b/source/Keyboard.h index dfe9c20c..de3bcb31 100644 --- a/source/Keyboard.h +++ b/source/Keyboard.h @@ -14,6 +14,8 @@ BYTE KeybGetKeycode (); void KeybQueueKeypress (int,BOOL); void KeybToggleCapsLock (); void KeybToggleP8ACapsLock (); +void KeybSpecialKeydown(DWORD wparam); +void KeybSpecialKeyup(DWORD wparam); void KeybSetSnapshot_v1(const BYTE LastKey); void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);