SysKey hook filter:
. Also suppress ALT+SPACE . PostMessage to AppleWin message-pump for WM_KEYDOWN, WM_KEYUP for these special key combos . Add special any-key-down (AKD) handling for these special key combos
This commit is contained in:
parent
19b90800cf
commit
6b53adde55
6 changed files with 147 additions and 52 deletions
|
@ -2,40 +2,65 @@
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/2490577/suppress-task-switch-keys-winkey-alt-tab-alt-esc-ctrl-esc-using-low-level-k
|
// 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":
|
// NB. __stdcall (or WINAPI) and extern "C":
|
||||||
// . symbol is decorated as _<symbol>@bytes
|
// . symbol is decorated as _<symbol>@bytes
|
||||||
// . so use the #pragma to create an undecorated alias for our symbol
|
// . so use the #pragma to create an undecorated alias for our symbol
|
||||||
extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
|
extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
|
||||||
_In_ int nCode,
|
_In_ int nCode,
|
||||||
_In_ WPARAM wParam,
|
_In_ WPARAM wParam,
|
||||||
_In_ LPARAM lParam
|
_In_ LPARAM lParam)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
#pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
|
#pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
|
||||||
|
|
||||||
if (nCode >= 0)
|
if (nCode == HC_ACTION)
|
||||||
{
|
{
|
||||||
bool suppress = false;
|
bool suppress = false;
|
||||||
|
|
||||||
PKBDLLHOOKSTRUCT pKbdLlHookStruct = (PKBDLLHOOKSTRUCT) lParam;
|
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.
|
// Note about PostMessage() and use of VkKeyScan():
|
||||||
if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
|
// . 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 = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Suppress alt-escape.
|
// Suppress alt-escape
|
||||||
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
|
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
|
||||||
|
{
|
||||||
|
PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x1B)), newlParam);
|
||||||
suppress = true;
|
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;
|
bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||||
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown)
|
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown)
|
||||||
suppress = true;
|
suppress = true;
|
||||||
|
|
||||||
// Suppress keys by returning 1.
|
// Suppress keys by returning 1
|
||||||
if (suppress)
|
if (suppress)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam);
|
return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) void __cdecl RegisterHWND(HWND hWnd)
|
||||||
|
{
|
||||||
|
g_hFrameWindow = hWnd;
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9.00"
|
||||||
Name="AppleWinHookFilter"
|
Name="HookFilter"
|
||||||
ProjectGUID="{AA5854AD-2BC7-4EFD-9790-349ADB35E35A}"
|
ProjectGUID="{AA5854AD-2BC7-4EFD-9790-349ADB35E35A}"
|
||||||
RootNamespace="HookFilter"
|
RootNamespace="HookFilter"
|
||||||
Keyword="Win32Proj"
|
Keyword="Win32Proj"
|
||||||
|
|
|
@ -821,7 +821,7 @@ void RegisterExtensions(void)
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
// NB. On a restart, it's OK to call RegisterHotKey() again since the old g_hFrameWindow has been destroyed
|
// NB. On a restart, it's OK to call RegisterHotKey() again since the old g_hFrameWindow has been destroyed
|
||||||
static void AppleWin_RegisterHotKeys(void)
|
static void RegisterHotKeys(void)
|
||||||
{
|
{
|
||||||
BOOL bStatus[3] = {0,0,0};
|
BOOL bStatus[3] = {0,0,0};
|
||||||
|
|
||||||
|
@ -865,6 +865,49 @@ static void AppleWin_RegisterHotKeys(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static HINSTANCE g_hinstDLL = 0;
|
||||||
|
static HHOOK g_hhook = 0;
|
||||||
|
|
||||||
|
// Pre: g_hFrameWindow must be valid
|
||||||
|
void HookFilterForKeyboard()
|
||||||
|
{
|
||||||
|
g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
|
||||||
|
|
||||||
|
_ASSERT(g_hFrameWindow);
|
||||||
|
|
||||||
|
typedef void (*RegisterHWNDProc)(HWND);
|
||||||
|
RegisterHWNDProc RegisterHWND = (RegisterHWNDProc) GetProcAddress(g_hinstDLL, "RegisterHWND");
|
||||||
|
if (RegisterHWND)
|
||||||
|
RegisterHWND(g_hFrameWindow);
|
||||||
|
|
||||||
|
HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
|
||||||
|
|
||||||
|
g_hhook = SetWindowsHookEx(
|
||||||
|
WH_KEYBOARD_LL,
|
||||||
|
hkprcLowLevelKeyboardProc,
|
||||||
|
g_hinstDLL,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (g_hhook == 0 || g_hFrameWindow == 0)
|
||||||
|
{
|
||||||
|
std::string msg("Failed to install hook filter for system keys");
|
||||||
|
|
||||||
|
DWORD dwErr = GetLastError();
|
||||||
|
MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
|
||||||
|
|
||||||
|
msg += "\n";
|
||||||
|
LogFileOutput(msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnhookFilterForKeyboard()
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(g_hhook);
|
||||||
|
FreeLibrary(g_hinstDLL);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
LPSTR GetCurrArg(LPSTR lpCmdLine)
|
LPSTR GetCurrArg(LPSTR lpCmdLine)
|
||||||
|
@ -1012,40 +1055,6 @@ static void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBo
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static HINSTANCE g_hinstDLL = 0;
|
|
||||||
static HHOOK g_hhook = 0;
|
|
||||||
|
|
||||||
void HookFilterForKeyboard()
|
|
||||||
{
|
|
||||||
g_hinstDLL = LoadLibrary(TEXT("AppleWinHookFilter.dll"));
|
|
||||||
HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
|
|
||||||
|
|
||||||
g_hhook = SetWindowsHookEx(
|
|
||||||
WH_KEYBOARD_LL,
|
|
||||||
hkprcLowLevelKeyboardProc,
|
|
||||||
g_hinstDLL,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (g_hhook == NULL)
|
|
||||||
{
|
|
||||||
std::string msg("Failed to install hook filter for system keys");
|
|
||||||
|
|
||||||
DWORD dwErr = GetLastError();
|
|
||||||
MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK); // NB. g_hFrameWindow is not yet valid
|
|
||||||
|
|
||||||
msg += "\n";
|
|
||||||
LogFileOutput(msg.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnhookFilterForKeyboard()
|
|
||||||
{
|
|
||||||
UnhookWindowsHookEx(g_hhook);
|
|
||||||
FreeLibrary(g_hinstDLL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||||
{
|
{
|
||||||
bool bShutdown = false;
|
bool bShutdown = false;
|
||||||
|
@ -1344,8 +1353,6 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||||
DiskInitialize();
|
DiskInitialize();
|
||||||
LogFileOutput("Init: DiskInitialize()\n");
|
LogFileOutput("Init: DiskInitialize()\n");
|
||||||
|
|
||||||
HookFilterForKeyboard();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -1398,10 +1405,13 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||||
RegSaveString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, VERSIONSTRING); // Only save version after user accepts license
|
RegSaveString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, VERSIONSTRING); // Only save version after user accepts license
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintScrn support
|
|
||||||
if (g_bCapturePrintScreenKey)
|
if (g_bCapturePrintScreenKey)
|
||||||
AppleWin_RegisterHotKeys(); // needs valid g_hFrameWindow
|
{
|
||||||
LogFileOutput("Main: AppleWin_RegisterHotKeys()\n");
|
RegisterHotKeys(); // needs valid g_hFrameWindow
|
||||||
|
LogFileOutput("Main: RegisterHotKeys()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
HookFilterForKeyboard(); // needs valid g_hFrameWindow (for message pump)
|
||||||
|
|
||||||
// Need to test if it's safe to call ResetMachineState(). In the meantime, just call DiskReset():
|
// Need to test if it's safe to call ResetMachineState(). In the meantime, just call DiskReset():
|
||||||
DiskReset(); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
|
DiskReset(); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
|
||||||
|
@ -1508,11 +1518,11 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||||
|
|
||||||
DSUninit();
|
DSUninit();
|
||||||
LogFileOutput("Main: DSUninit()\n");
|
LogFileOutput("Main: DSUninit()\n");
|
||||||
|
|
||||||
|
UnhookFilterForKeyboard();
|
||||||
}
|
}
|
||||||
while (g_bRestart);
|
while (g_bRestart);
|
||||||
|
|
||||||
UnhookFilterForKeyboard();
|
|
||||||
|
|
||||||
if (bChangedDisplayResolution)
|
if (bChangedDisplayResolution)
|
||||||
ChangeDisplaySettings(NULL, 0); // restore default
|
ChangeDisplaySettings(NULL, 0); // restore default
|
||||||
|
|
||||||
|
|
|
@ -1260,6 +1260,7 @@ LRESULT CALLBACK FrameWndProc (
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
KeybUpdateCtrlShiftStatus();
|
KeybUpdateCtrlShiftStatus();
|
||||||
|
KeybSpecialKeydown(wparam);
|
||||||
|
|
||||||
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
|
// 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 == -1))
|
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == -1))
|
||||||
|
@ -1399,6 +1400,8 @@ LRESULT CALLBACK FrameWndProc (
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_KEYUP:
|
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
|
// 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))
|
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
|
||||||
{
|
{
|
||||||
LogFileTimeUntilFirstKeyRead();
|
LogFileTimeUntilFirstKeyRead();
|
||||||
|
@ -428,6 +480,9 @@ BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
|
||||||
|
|
||||||
keywaiting = 0;
|
keywaiting = 0;
|
||||||
|
|
||||||
|
if (IsSpecialAKD(lastvirtkey))
|
||||||
|
return keycode | 0x80;
|
||||||
|
|
||||||
return keycode | ((GetKeyState(lastvirtkey) < 0) ? 0x80 : 0);
|
return keycode | ((GetKeyState(lastvirtkey) < 0) ? 0x80 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ BYTE KeybGetKeycode ();
|
||||||
void KeybQueueKeypress (int,BOOL);
|
void KeybQueueKeypress (int,BOOL);
|
||||||
void KeybToggleCapsLock ();
|
void KeybToggleCapsLock ();
|
||||||
void KeybToggleP8ACapsLock ();
|
void KeybToggleP8ACapsLock ();
|
||||||
|
void KeybSpecialKeydown(DWORD wparam);
|
||||||
|
void KeybSpecialKeyup(DWORD wparam);
|
||||||
void KeybSetSnapshot_v1(const BYTE LastKey);
|
void KeybSetSnapshot_v1(const BYTE LastKey);
|
||||||
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||||
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||||
|
|
Loading…
Add table
Reference in a new issue