mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-02-01 21:33:47 +00:00
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
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user