昨天和两个同学一起玩魔兽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,如需转载请自行联系原作者

Disabling Shortcut Keys in Full Screen mode相关推荐

  1. adobe captivate 5.5 中文教程

    adobe captivate 5.5 中文教程 目 录 adobe captivate 5.5 中文教程... 1 目 录... 1 第1节 Adobe Captivate 5.5更新的内容... ...

  2. Android 禁用电源键音量键与模拟

    /base/services/core/java/com/android/server/policy/PhoneWindowManager.java 模拟 在PhoneWindowManager中注册 ...

  3. windows调整窗口大小_175 Windows 7调整,提示和操作方法文章

    windows调整窗口大小 Windows 7 is being officially released on October 22nd, which also happens to be today ...

  4. SnagIt - 版本历史

    SnagIt - 版本历史 07 May, 2007: SnagIt v8.2.3 Updated SnagIt to run C# accessories. 01 March, 2007: Snag ...

  5. 【STM32】 keil软件工具--configuration详解(下)

    转载至:https://blog.csdn.net/ybhuangfugui/article/details/51501781 Ⅰ.写在前面 本文接着上一篇文章"Configuration( ...

  6. mac屏幕截图_如何在Mac上拍摄屏幕截图

    mac屏幕截图 On a Mac, you can take screenshots with a few quick keyboard shortcuts. But Mac OS X also in ...

  7. 用户帐户控制设置_创建快捷方式以避免用户帐户控制弹出式快捷方式

    用户帐户控制设置 There are numerous applications which, when launched, result in a UAC (User Account Control ...

  8. Keil(MDK-ARM-STM32)系列教程(六)Configuration(Ⅱ)

    Ⅰ.写在前面 本文接着上一篇文章"Configuration(Ⅰ)"进行讲述Configuration后面三项Shortcut Keys快捷键.Text Completion代码完 ...

  9. windows截图快捷键_使用快捷键打开并使用Windows截图工具

    windows截图快捷键 Snippingtool used used to take screenshot in windows operating systems. Snipping tool i ...

最新文章

  1. matplotlib可视化时间序列数据、并高亮时间序列中的指定区域(Highlight a Region of Time-Series Plot with Matplotlib)
  2. Luogu P2920 时间管理【二分答案】
  3. mysql的映射文件调用函数_MyBatis中调用存储过程和函数
  4. NumPy - ndarray
  5. eq linux_音乐家和音乐爱好者的开放硬件 | Linux 中国
  6. windbg 常用命令~*
  7. 卷积神经网络系列之softmax,softmax loss和cross entropy
  8. layui复选框:被js操作checked切换并显示状态(含案例、代码)
  9. BZOJ3884 上帝与集合的正确用法 【欧拉定理】
  10. sqlserver2014导出mysql_sql server2014如何备份数据库-sql server2014备份数据库教程 - 河东软件园...
  11. client_loop: send disconnect: Broken pipe_欧姆龙plc之间用 SEND 和 RCV 指令发送读取数据...
  12. ReDet A Rotation-equivariant Detector for Aerial Object Detection 论文学习
  13. 计算机微格教学心得体会,微格教学心得体会6篇_微格教学体会报告(2)
  14. box-shadow 设置单边、多边阴影
  15. 洛谷P2713 罗马游戏
  16. 如何正确选择云服务提供商?
  17. 结构光N步相移+多频外差法之解相位:三频四相
  18. 解决org.springframework.amqp.AmqpException: No method found for class [B
  19. 全国百强县排名完全名单——你老家上榜了吗?
  20. 关于SQLite数据库 字段 DateTime 类型

热门文章

  1. 使用hibernate可以优化的地方
  2. iOS中用到的唯一标示符
  3. 关于方法的重载和默认参数的一点小误区
  4. 实战Makefile
  5. [转载]Netvault:操作Informix APM将A机备份的数据恢复到B机
  6. 【转载】关于网页尺寸的设置
  7. ES6新特性_使用babel对ES6模块化代码转换_使用browserify对代码进行打包_实现es6兼容其他浏览器--JavaScript_ECMAScript_ES6-ES11新特性工作笔记045
  8. ES6新特性_ES6_Symbol的介绍与创建---JavaScript_ECMAScript_ES6-ES11新特性工作笔记015
  9. 使用svm 对参数寻优的时候出现错误
  10. 视讯稳定对接出现的问题