Disabling Shortcut Keys in Full Screen mode

简介:
昨天和两个同学一起玩魔兽3C的时候,由于很长时间我都是躲在练功房里砍木头人升级,而这种体力活不需要我监视英雄的举动,所以我就不断地切出游戏去上网,这种行为弄得两个哥们十分郁闷。呵呵,谁让我是主机呢,于是就不断地出现掉线的情况。
过后我就在想,那么如何在游戏中限制用户这种动作呢,使得他无法利用’ WIN功能键”不断地切进切出。
      下面就是我给出的一个解决方案,原理是:利用一个底层的键盘钩子函数对待处理的键盘消息进行过滤。这个钩子即使在用户对窗口最小化或切换到另一个应用程序也是有效的。
// demo0.cpp : Defines the entry point for the application.
//******************************
//Author:phinecos
//Date:2008-4-17
//*******************************

#include "stdafx.h"
#include "demo0.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
HWND hWnd = NULL; //窗口句柄
HHOOK g_hKeyboardHook;


TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
BOOL isFullScreen = TRUE;//是否全屏
BOOL isActive=TRUE;        // Window Active Flag Set To TRUE By Default

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);


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;
    KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
    switch (wParam) 
    {
    case WM_KEYDOWN:  
    case WM_KEYUP:    
        {
            bEatKeystroke = (isFullScreen && isActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)));
            break;
        }
    }

    if( bEatKeystroke )
        return 1;
    else
        return CallNextHookEx( g_hKeyboardHook, nCode, wParam, lParam );
}



int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO: Place code here.
    MSG msg;
    g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL,  LowLevelKeyboardProc, GetModuleHandle(NULL), 0 ); //设置钩子

    if (MessageBox(NULL,L"是否以全屏模式运行?", L"信息?",MB_YESNO|MB_ICONQUESTION)==IDNO)
    {
        isFullScreen = FALSE;                            // Windowed Mode
    }
    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_DEMO0, szWindowClass, MAX_LOADSTRING);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    UnhookWindowsHookEx( g_hKeyboardHook ); //卸载钩子
    return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DEMO0));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = 0;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

VOID KillWindow(VOID)                                // Properly Kill The Window
{
    if (isFullScreen)                                        // Are We In Fullscreen Mode?
    {
        ChangeDisplaySettings(NULL,0);                    // If So Switch Back To The Desktop
        ShowCursor(TRUE);                                // Show Mouse Pointer
    }
    if (hWnd && !DestroyWindow(hWnd))                    // Are We Able To Destroy The Window?
    {
        MessageBox(NULL,L"Could Not Release hWnd.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hWnd=NULL;                                        // Set hWnd To NULL
    }
    if (!UnregisterClass(szWindowClass,hInst))            // Are We Able To Unregister Class
    {
        MessageBox(NULL,L"Could Not Unregister Class.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hInst=NULL;                                    // Set hInstance To NULL
    }
}


BOOL MyCreateWindow(TCHAR* title, int width, int height, int bits, BOOL fullscreenflag)
{
    DWORD        dwExStyle;                // Window Extended Style
    DWORD        dwStyle;                // Window Style
    RECT        WindowRect;                // Grabs Rectangle Upper Left / Lower Right Values
    WindowRect.left=(long)0;            // Set Left Value To 0
    WindowRect.right=(long)width;        // Set Right Value To Requested Width
    WindowRect.top=(long)0;                // Set Top Value To 0
    WindowRect.bottom=(long)height;        // Set Bottom Value To Requested Height

    isFullScreen = fullscreenflag;            // Set The Global Fullscreen Flag
    if (isFullScreen)                                                // Attempt Fullscreen Mode?
    {
        DEVMODE dmScreenSettings;                                // Device Mode
        memset(&dmScreenSettings,0,sizeof(dmScreenSettings));    // Makes Sure Memory's Cleared
        dmScreenSettings.dmSize=sizeof(dmScreenSettings);        // Size Of The Devmode Structure
        dmScreenSettings.dmPelsWidth    = width;                // Selected Screen Width
        dmScreenSettings.dmPelsHeight    = height;                // Selected Screen Height
        dmScreenSettings.dmBitsPerPel    = bits;                    // Selected Bits Per Pixel
        dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

        // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
        if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
        {
            // If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
            if (MessageBox(NULL,L"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?",L"Infomation",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
            {
                isFullScreen = FALSE;        // Windowed Mode Selected.  Fullscreen = FALSE
            }
            else
            {
                // Pop Up A Message Box Letting User Know The Program Is Closing.
                MessageBox(NULL,L"Program Will Now Close.",L"ERROR",MB_OK|MB_ICONSTOP);
                return FALSE;                                    // Return FALSE
            }
        }
    }

    if (isFullScreen)                                                // Are We Still In Fullscreen Mode?
    {
        dwExStyle=WS_EX_APPWINDOW;                                // Window Extended Style
        dwStyle=WS_POPUP;                                        // Windows Style
        ShowCursor(FALSE);                                        // Hide Mouse Pointer
    }
    else
    {
        dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;            // Window Extended Style
        dwStyle=WS_OVERLAPPEDWINDOW;                            // Windows Style
    }

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);        // Adjust Window To True Requested Size

    // Create The Window
    if (!(hWnd=CreateWindowEx(    dwExStyle,                            // Extended Style For The Window
        szWindowClass,                            // Class Name
        title,                                // Window Title
        dwStyle |                            // Defined Window Style
        WS_CLIPSIBLINGS |                    // Required Window Style
        WS_CLIPCHILDREN,                    // Required Window Style
        0, 0,                                // Window Position
        WindowRect.right-WindowRect.left,    // Calculate Window Width
        WindowRect.bottom-WindowRect.top,    // Calculate Window Height
        NULL,                                // No Parent Window
        NULL,                                // No Menu
        hInst,                            // Instance
        NULL)))                                // Dont Pass Anything To WM_CREATE
    {
        KillWindow();                                // Reset The Display
        MessageBox(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                                // Return FALSE
    }
    ShowWindow(hWnd,SW_SHOW);                        // Show The Window
    SetForegroundWindow(hWnd);                        // Slightly Higher Priority
    SetFocus(hWnd);                                    // Sets Keyboard Focus To The Window

    return TRUE;                                    // Success
}
//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    MyRegisterClass(hInstance);
   hInst = hInstance; // Store instance handle in our global variable
    MyCreateWindow(szTitle,640,480,16,isFullScreen);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_ACTIVATEAPP:
        // g_bWindowActive is used to control if the Windows key is filtered by the keyboard hook or not.
        if( wParam == TRUE )
            isActive  = TRUE;           
        else 
            isActive  = FALSE;           
        break;

    case WM_KEYDOWN:
        {
            if (wParam==VK_ESCAPE)
            {//退出
                KillWindow();                        // Kill Our Current Window
            }
        }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


参考资料:
1,  Disabling Shortcut Keys in Games
2,  Nehe OpenGL tutorial



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/04/17/1157739.html,如需转载请自行联系原作者
目录
相关文章
问题 There is no screen to be resumed matching
问题 There is no screen to be resumed matching
145 0
|
7月前
|
Android开发
Can t process attribute android:fillColor=@color/camera_progress_delete: references to other resou
Can t process attribute android:fillColor=@color/camera_progress_delete: references to other resou
48 1
|
7月前
|
Ubuntu iOS开发 MacOS
Could not enumerate video devices (or none found).解决办法
Could not enumerate video devices (or none found).解决办法
110 0
flag_in_your_hand
flag_in_your_hand
50 0
|
JSON 数据格式
成功解决 global init errTypeError:Right-hand side of 'instanceof' is not callable
成功解决 global init errTypeError:Right-hand side of 'instanceof' is not callable
|
TensorFlow 算法框架/工具 Python
成功解决File "frozen importlib._bootstrap", line 219, in _call_with_frames_removed ImportError: DLL lo
成功解决File "frozen importlib._bootstrap", line 219, in _call_with_frames_removed ImportError: DLL lo
成功解决File "frozen importlib._bootstrap", line 219, in _call_with_frames_removed ImportError: DLL lo
成功解决:Could not initialize SDL - No available video device (Did you set the DISPLAY variable?)
成功解决:Could not initialize SDL - No available video device (Did you set the DISPLAY variable?)
667 0
|
Java 应用服务中间件 Python
Refused to display 'xxx' in a frame ,because it set 'X-Frame-Options' to 'deny'.
我本是在DJANGO页面的iframe里嵌入springboot的页面。 当报了这个错误之后,我花了时间在nginx和django上, 后来才改变解决思路,从springboot出发,解决问题。
5890 0
goods_type和disable_pay_channels和enable_pay_channels区别
说明:   为防止用户使用花呗分期套现,需要禁止使用花呗分期。如果商家在虚拟商品交易中使用花呗分期支付,一经发现关闭花呗分期权限。禁用花呗分期方法   注意:goods_type如果传值为0,信用卡渠道也是不可以使用的。
1213 12