在遊戲中停用快速鍵
本文說明如何在 Microsoft Windows 中暫時停用鍵盤快速鍵,以防止全螢幕遊戲的遊戲中斷。 SHIFT鍵和CTRL鍵通常用於遊戲中的引發或執行按鈕。 如果使用者不小心按下 Windows 鍵 (位於這些按鍵附近) ,他們可能會導致自己突然跳出應用程式,這會破壞遊戲體驗。 只要使用 SHIFT 鍵做為遊戲按鈕,就可以不小心執行可顯示警告對話方塊的 StickyKeys 快捷方式。 若要避免這些問題,您應該在全螢幕模式中執行時停用這些金鑰,並在視窗模式中執行或結束應用程式時,啟用金鑰回到其預設處理常式。
本文說明如何執行下列動作:
使用鍵盤勾點停用 Windows 鍵
使用低階鍵盤勾點來篩選出正在處理的 Windows 按鍵。 範例 1 所示的低階鍵盤勾點仍然有效,即使使用者最小化視窗或切換至另一個應用程式也一樣。 這表示您必須小心,以確保應用程式停用時不會停用 Windows 金鑰。 範例 1 中的程式碼會藉由處理WM_ACTI加值稅EAPP訊息來執行此動作。
注意
此方法適用于 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 是專為難以同時按住兩個或多個金鑰的人員所設計。 所有這些協助工具功能也有一個鍵盤快速鍵,可讓功能開啟或關閉。 例如,StickyKeys 快捷方式會按下 SHIFT 鍵五次來觸發。 如果遊戲也使用 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);
}
}
}