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


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

В этой статье описывается, как временно отключить сочетания клавиш в 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);
        }
    }
}