Compartir a través de


Deshabilitar teclas de método abreviado en juegos

En este artículo se describe cómo deshabilitar temporalmente los métodos abreviados de teclado en Microsoft Windows para evitar la interrupción del juego en juegos de pantalla completa. La tecla MAYÚS y la tecla CTRL se usan a menudo como botones de encendido o ejecución en juegos. Si los usuarios presionan accidentalmente la tecla De Windows (ubicada cerca de estas teclas), pueden provocar que de repente salgan de la aplicación, lo que arruina la experiencia del juego. Simplemente usando la tecla MAYÚS como un botón de juego puede ejecutar accidentalmente el acceso directo StickyKeys, que puede mostrar un cuadro de diálogo de advertencia. Para evitar estos problemas, debe deshabilitar estas claves al ejecutarse en modo de pantalla completa y volver a habilitar las teclas en sus controladores predeterminados al ejecutarse en modo de ventana o salir de la aplicación.

En este artículo se describe cómo hacer lo siguiente:

Deshabilitar la tecla de Windows con un enlace de teclado

Use un enlace de teclado de bajo nivel para filtrar la tecla de Windows de la que se va a procesar. El enlace de teclado de bajo nivel que se muestra en el ejemplo 1 permanece en vigor incluso si un usuario minimiza la ventana o cambia a otra aplicación. Esto significa que debe tener cuidado de asegurarse de que la clave de Windows no está deshabilitada cuando se desactiva la aplicación. El código del ejemplo 1 lo hace controlando el mensaje WM_ACTIVATEAPP.

Nota

Este método funciona en Windows 2000 y versiones posteriores de Windows. Este método también funciona con cuentas de usuario con privilegios mínimos (también conocidas como cuentas de usuario estándar).

 

DXUT usa este método y se muestra en el ejemplo de código siguiente.

Ejemplo 1. Usar un enlace de teclado de bajo nivel para deshabilitar la tecla De 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;
    }
}

Deshabilitar las teclas de método abreviado de accesibilidad

Windows incluye características de accesibilidad como StickyKeys, FilterKeys y ToggleKeys (consulta Accesibilidad de Windows). Cada uno de ellos sirve para un propósito diferente; StickyKeys, por ejemplo, está diseñado para personas que tienen dificultades para mantener dos o más teclas simultáneamente. Cada una de estas características de accesibilidad también tiene un método abreviado de teclado que permite activar o desactivar la característica. Por ejemplo, el acceso directo StickyKeys se desencadena presionando la tecla MAYÚS cinco veces. Si la tecla MAYÚS también se usa en el juego, el usuario podría desencadenar accidentalmente este acceso directo durante el juego. Cuando se desencadena el acceso directo, Windows (de forma predeterminada) presenta una advertencia en un cuadro de diálogo, lo que provocaría que Windows minimice la ejecución de un juego en modo de pantalla completa. Esto, por supuesto, puede tener un efecto drástico en el juego.

Las características de accesibilidad son necesarias para algunos clientes y no interfieren con juegos de pantalla completa; por lo tanto, no debe cambiar la configuración de accesibilidad. Sin embargo, dado que los accesos directos de las características de accesibilidad pueden interrumpir el juego si se desencadenan accidentalmente, debes desactivar un acceso directo de accesibilidad solo cuando esa característica no esté habilitada mediante una llamada a SystemParametersInfo.

Un acceso directo de accesibilidad desactivado por SystemParametersInfo permanece desactivado incluso después de que se haya cerrado la aplicación. Esto significa que debe restaurar la configuración antes de salir de la aplicación. Dado que es posible que la aplicación no se cierre correctamente, debe escribir esta configuración en el almacenamiento persistente para que se puedan restaurar cuando se vuelva a ejecutar la aplicación. También puede usar un controlador de excepciones para restaurar esta configuración si se produce un bloqueo.

Para desactivar estos accesos directos

  1. Capture la configuración de accesibilidad actual antes de deshabilitarla.
  2. Deshabilite el acceso directo de accesibilidad cuando la aplicación entre en modo de pantalla completa si la característica de accesibilidad está desactivada.
  3. Restaure la configuración de accesibilidad cuando la aplicación entre en modo de ventana o salga.

Este método se usa en DXUT y se muestra en el ejemplo de código siguiente.

Nota

Este método funciona cuando se ejecuta en cuentas de usuario estándar.

 

Ejemplo 2. Deshabilitación de las teclas de método abreviado de accesibilidad

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);
        }
    }
}