ゲームでショートカット キーを無効にする
この記事では、全画面表示ゲームのゲーム の中断を防ぐために、Microsoft Windows でキーボード ショートカットを一時的に無効にする方法について説明します。 Shift キーと Ctrl キーは、多くの場合、ゲームで起動または実行ボタンとして使用されます。 ユーザーが誤って (これらのキーの近くにある) Windows キーを押すと、アプリケーションから突然飛び出し、ゲームエクスペリエンスが損なわれる可能性があります。 Shift キーをゲーム ボタンとして使用するだけで、誤って StickyKeys ショートカットが実行され、警告ダイアログが表示されることがあります。 これらの問題を回避するには、全画面表示モードで実行するときにこれらのキーを無効にし、ウィンドウ モードで実行するときにキーを既定のハンドラーに戻すか、アプリケーションを終了する必要があります。
この記事では、次の操作を行う方法について説明します。
キーボード フックを使用して Windows キーを無効にする
Windows キーの処理を除外するには、低レベルのキーボード フックを使用します。 例 1 に示す低レベルのキーボード フックは、ユーザーがウィンドウを最小化したり、別のアプリケーションに切り替えたりしても有効です。 つまり、アプリケーションを非アクティブ化するときに Windows キーが無効にならないように注意する必要があります。 例 1 のコードでは、WM_ACTIVATEAPP メッセージを処理してこれを行います。
Note
このメソッドは、Windows 2000 以降のバージョンの Windows で動作します。 この方法は、最小限の特権を持つユーザー アカウント (Standard ユーザー アカウントとも呼ばれます) でも機能します。
このメソッドは 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 は、2 つ以上のキーを同時に押し続けるのが困難なユーザー向けに設計されています。 これらの各アクセシビリティ機能には、機能のオンとオフを切り替えるキーボード ショートカットもあります。 たとえば、 Shift キーを 5 回押すと、StickyKeys ショートカットがトリガーされます。 Shift キーがゲームでも使用されている場合、ユーザーはゲームのプレイ中に誤ってこのショートカットをトリガーする可能性があります。 ショートカットがトリガーされると、Windows (既定) はダイアログ ボックスに警告を表示します。これにより、Windows は全画面表示モードで実行されているゲームを最小限に抑えます。 これはもちろん、ゲームプレイに大きな影響を与える可能性があります。
アクセシビリティ機能は、一部のお客様に必要であり、それ自体が全画面表示ゲームに干渉することはありません。そのため、アクセシビリティ設定を変更しないでください。 ただし、アクセシビリティ機能のショートカットは、誤ってトリガーされた場合にゲームプレイを中断する可能性があるため、 SystemParametersInfo を呼び出して、その機能が有効になっていない場合にのみ、アクセシビリティ ショートカットをオフにする必要があります。
SystemParametersInfo によってオフになっているアクセシビリティ ショートカットは、アプリケーションが終了した後でもオフのままです。 つまり、アプリケーションを終了する前に設定を復元する必要があります。 アプリケーションが正しく終了しない可能性があるため、アプリケーションを再度実行したときに復元できるように、これらの設定を永続ストレージに書き込む必要があります。 クラッシュが発生した場合は、例外ハンドラーを使用してこれらの設定を復元することもできます。
これらのショートカットをオフにするには
- 無効にする前に、現在のアクセシビリティ設定をキャプチャします。
- アクセシビリティ機能がオフの場合、アプリケーションが全画面表示モードになったときにアクセシビリティ ショートカットを無効にします。
- アプリケーションがウィンドウ モードになったり終了したりしたときに、アクセシビリティ設定を復元します。
このメソッドは DXUT で使用され、次のコード例に示されています。
Note
このメソッドは、Standard ユーザー アカウントで実行する場合に機能します。
例 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);
}
}
}