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:
tomcw 2018-05-28 17:27:38 +01:00
parent 19b90800cf
commit 6b53adde55
6 changed files with 147 additions and 52 deletions

View File

@ -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 _<symbol>@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;
}

View File

@ -2,7 +2,7 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="AppleWinHookFilter"
Name="HookFilter"
ProjectGUID="{AA5854AD-2BC7-4EFD-9790-349ADB35E35A}"
RootNamespace="HookFilter"
Keyword="Win32Proj"

View File

@ -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
static void AppleWin_RegisterHotKeys(void)
static void RegisterHotKeys(void)
{
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)
@ -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)
{
bool bShutdown = false;
@ -1344,8 +1353,6 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
DiskInitialize();
LogFileOutput("Init: DiskInitialize()\n");
HookFilterForKeyboard();
//
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
}
// PrintScrn support
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():
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();
LogFileOutput("Main: DSUninit()\n");
UnhookFilterForKeyboard();
}
while (g_bRestart);
UnhookFilterForKeyboard();
if (bChangedDisplayResolution)
ChangeDisplaySettings(NULL, 0); // restore default

View File

@ -1260,6 +1260,7 @@ LRESULT CALLBACK FrameWndProc (
case WM_KEYDOWN:
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
if ((wparam >= 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))
{

View File

@ -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);
}

View File

@ -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);