Поделиться через


Отключение сочетаний клавиш в играх

В этой статье описывается, как временно отключить сочетания клавиш в 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, например, предназначен для людей, которые испытывают трудности с удержанием двух или более ключей одновременно. Каждая из этих функций специальных возможностей также имеет сочетание клавиш, позволяющее включить или отключить функцию. Например, сочетание клавиш StickyKeys активируется путем пятикратного нажатия клавиши SHIFT. Если также используется клавиша SHIFT в игре, пользователь может случайно активировать это сочетание клавиш в процессе игры. При активации ярлыка Windows (по умолчанию) представляет предупреждение в диалоговом окне, что приведет к минимизации игры в полноэкранном режиме. Это, конечно, может иметь резкое влияние на игру.

Функции специальных возможностей необходимы для некоторых клиентов и не вмешиваются в полноэкранные игры; Поэтому не следует изменять параметры специальных возможностей. Тем не менее, поскольку сочетания клавиш для специальных возможностей могут нарушить игру при случайном срабатывании, следует отключить ярлык специальных возможностей только в том случае, если эта функция не включена путем вызова SystemParametersInfo.

Отключенный SystemParametersInfo ярлык специальных возможностей остается отключенным даже после закрытия приложения. Это означает, что перед выходом из приложения необходимо восстановить параметры. Так как приложению не удается завершить работу правильно, эти параметры следует записать в постоянное хранилище, чтобы их можно было восстановить при повторном запуске приложения. Вы также можете использовать обработчик исключений для восстановления этих параметров, если происходит сбой.

Отключите эти сочетания клавиш

  1. Зафиксировать текущие параметры специальных возможностей перед их отключением.
  2. Отключите ярлык специальных возможностей при переходе приложения в полноэкранный режим, если функция специальных возможностей отключена.
  3. Восстановите параметры специальных возможностей при переходе приложения в оконный режим или при выходе.

Этот метод используется в 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);
        }
    }
}