在游戏中禁用快捷键
本文介绍如何在 Microsoft Windows 中暂时禁用键盘快捷方式,以防止中断全屏游戏的游戏玩法。 SHIFT 键和 Ctrl 键通常用作游戏中的触发或运行按钮。 如果用户不小心按下位于这些键) 附近的 Windows 键 (,他们可能会导致自己突然跳出应用程序,从而破坏游戏体验。 只需将 SHIFT 键用作游戏按钮,就会无意中执行 StickyKeys 快捷方式,该快捷方式可能会显示警告对话框。 若要避免这些问题,应在全屏模式下运行时禁用这些键,并在以窗口模式运行时启用这些键回到其默认处理程序,或者退出应用程序。
本文介绍如何执行以下操作:
使用键盘挂钩禁用 Windows 键
使用低级键盘挂钩来筛选出 正在处理的 Windows 键。 即使用户最小化窗口或切换到另一个应用程序,示例 1 中显示的低级别键盘挂钩仍有效。 这意味着,你必须小心,确保在停用应用程序时不会禁用 Windows 密钥。 示例 1 中的代码通过处理WM_ACTIVATEAPP消息来执行此操作。
注意
此方法适用于 Windows 2000 及更高版本的 Windows。 此方法也适用于最低特权用户帐户 (也称为标准用户帐户) 。
此方法由 DXUT 使用,并在以下代码示例中进行了说明。
示例 1。 使用低级键盘挂钩禁用 Windows 键
HHOOK g_hKeyboardHook = nullptr;
bool g_bWindowActive = false;
bool g_bFullscreen;
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
// Initialization
g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(nullptr), 0 );
//
// main application code here
//
// Cleanup before shutdown
UnhookWindowsHookEx( g_hKeyboardHook );
g_hKeyboardHook = nullptr;
return 0;
}
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
if (nCode < 0 || nCode != HC_ACTION ) // do not process message
return CallNextHookEx( g_hKeyboardHook, nCode, wParam, lParam);
bool bEatKeystroke = false;
auto p = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
switch (wParam)
{
case WM_KEYDOWN:
case WM_KEYUP:
{
bEatKeystroke = (g_bFullscreen && g_bWindowActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)));
// Note that this will not block the Xbox Game Bar hotkeys (Win+G, Win+Alt+R, etc.)
break;
}
}
if( bEatKeystroke )
return 1;
else
return CallNextHookEx( g_hKeyboardHook, nCode, wParam, lParam );
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_ACTIVATEAPP:
// g_bWindowActive is used to control if the Windows key is filtered by the keyboard hook or not.
if( wParam )
g_bWindowActive = true;
else
g_bWindowActive = false;
break;
case WM_SYSKEYDOWN:
if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)
{
// Implement the classic ALT+ENTER fullscreen toggle
...
// g_bFullscreen is used to control if the Windows key is filtered by the keyboard hook or not.
g_bFullscreen = !g_bFullscreen;
// Remember to use DXGI_MWA_NO_ALT_ENTER when you call the DXGI method MakeWindowAssociation
// so you control the fullscreen toggling in your application.
}
break;
}
}
禁用辅助功能快捷键
Windows 包括诸如 StickyKeys、FilterKeys 和 ToggleKeys 等辅助功能, (请参阅 Windows 辅助功能) 。 其中每个都有不同的用途:例如,StickyKeys 专为难以同时按住两个或多个键的用户而设计。 其中每个辅助功能还具有一个键盘快捷方式,允许打开或关闭该功能。 例如,通过按 SHIFT 键五次触发 StickyKeys 快捷方式。 如果游戏中还使用了 SHIFT 键,则用户在玩游戏期间可能会意外触发此快捷方式。 触发快捷方式时,Windows (默认情况下) 对话框中显示警告,这将导致 Windows 最小化在全屏模式下运行的游戏。 当然,这会对游戏发挥产生巨大影响。
某些客户需要辅助功能,并且本身不会干扰全屏游戏;因此,不应更改辅助功能设置。 但是,由于辅助功能快捷方式在意外触发时可能会中断游戏玩法,因此仅当未通过调用 SystemParametersInfo 启用该功能时,才应关闭辅助功能快捷方式。
即使应用程序退出, SystemParametersInfo 关闭的辅助功能快捷方式也会保持关闭状态。 这意味着,在退出应用程序之前,必须还原设置。 由于应用程序可能无法正确退出,因此应将这些设置写入永久性存储,以便在应用程序再次运行时还原这些设置。 如果发生崩溃,还可以使用异常处理程序还原这些设置。
关闭这些快捷方式
- 在禁用当前辅助功能设置之前捕获它们。
- 如果禁用辅助功能,则当应用程序进入全屏模式时禁用辅助功能快捷方式。
- 在应用程序进入窗口模式或退出时还原辅助功能设置。
此方法在 DXUT 中使用,并在以下代码示例中进行了说明。
注意
此方法在标准用户帐户上运行时有效。
示例 2。 禁用辅助功能快捷键
STICKYKEYS g_StartupStickyKeys = {sizeof(STICKYKEYS), 0};
TOGGLEKEYS g_StartupToggleKeys = {sizeof(TOGGLEKEYS), 0};
FILTERKEYS g_StartupFilterKeys = {sizeof(FILTERKEYS), 0};
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
// Save the current sticky/toggle/filter key settings so they can be restored them later
SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &g_StartupStickyKeys, 0);
SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_StartupToggleKeys, 0);
SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &g_StartupFilterKeys, 0);
...
// Disable when full screen
AllowAccessibilityShortcutKeys( false );
...
// Restore back when going to windowed or shutting down
AllowAccessibilityShortcutKeys( true );
}
void AllowAccessibilityShortcutKeys( bool bAllowKeys )
{
if( bAllowKeys )
{
// Restore StickyKeys/etc to original state and enable Windows key
STICKYKEYS sk = g_StartupStickyKeys;
TOGGLEKEYS tk = g_StartupToggleKeys;
FILTERKEYS fk = g_StartupFilterKeys;
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &g_StartupStickyKeys, 0);
SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_StartupToggleKeys, 0);
SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &g_StartupFilterKeys, 0);
}
else
{
// Disable StickyKeys/etc shortcuts but if the accessibility feature is on,
// then leave the settings alone as its probably being usefully used
STICKYKEYS skOff = g_StartupStickyKeys;
if( (skOff.dwFlags & SKF_STICKYKEYSON) == 0 )
{
// Disable the hotkey and the confirmation
skOff.dwFlags &= ~SKF_HOTKEYACTIVE;
skOff.dwFlags &= ~SKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &skOff, 0);
}
TOGGLEKEYS tkOff = g_StartupToggleKeys;
if( (tkOff.dwFlags & TKF_TOGGLEKEYSON) == 0 )
{
// Disable the hotkey and the confirmation
tkOff.dwFlags &= ~TKF_HOTKEYACTIVE;
tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tkOff, 0);
}
FILTERKEYS fkOff = g_StartupFilterKeys;
if( (fkOff.dwFlags & FKF_FILTERKEYSON) == 0 )
{
// Disable the hotkey and the confirmation
fkOff.dwFlags &= ~FKF_HOTKEYACTIVE;
fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &fkOff, 0);
}
}
}