Closed xiaokaixuan closed 5 years ago
在 VC 中捕按键可以在 OnKeyDown 或 OnKeyUp 事件中进行捕获,不过这有很大的局限性,这里只能捕获用户按键。但在一些特殊的工程(项目)中往往需要捕获某些系统按键以完成特殊的功能,我们就不得不选择钩子了,一般情况下 大家都会选择 WH_KEYBOARD 这个钩子类型,但是在编写过程会发现这个钩子类型并不能捕获所有的系统按键,怎么办呢?那就得选择WH_KEYBOARD_LL (低级键盘钩子)了,使用它可以捕获全部的系统按键,一个不漏…… 在使用低级键盘钩子之前,先在 StdAfx.h 的第一行添加一条: #define _WIN32_WINNT 0x400 (这里假定你是用的 MFC 的 DLL),不然在编译的时候会提示说 WH_KEYBOARD_LL 没有定义。
网上还有另一种方法: 首先定义 #define WH_KEYBOARD_LL 13 然后 Winuser.h 中定义的 tagKBDLLHOOKSTRUCT 代码拷贝到工程中。 下面代码用以捕获系统按键:
/* 用户模块 return TRUE; --->丢弃该消息 */ LRESULT CALLBACK LowLevelKeyboardProc( int nCode, // hook code WPARAM wParam, // message identifier LPARAM lParam // message data ) { PKBDLLHOOKSTRUCT pm = NULL; if (nCode == HC_ACTION) { pm = (PKBDLLHOOKSTRUCT)lParam; switch(pm->vkCode) { //屏蔽 win 键 case VK_LWIN: case VK_RWIN: return 1; break; //屏蔽 alt+tab case VK_TAB: if(pm->flags & LLKHF_ALTDOWN) { return 1; } break; //屏蔽 esc alt+esc ctrl+esc case VK_ESCAPE: return 1; break; //屏蔽 ALT+F4 case VK_F4: if(pm->flags & LLKHF_ALTDOWN) { return 1; } break; //屏蔽 F1 case VK_F1: return 1; break; //屏蔽 CTRL+ALT+DEL case VK_DELETE: if(pm->flags & LLKHF_ALTDOWN) { if (GetKeyState(VK_CONTROL) < 0) { return 1; } } break; default: break; } } // if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN) // //如果按键为按下状态 // { // if (Key_Info->vkCode == VK_LWIN || Key_Info->vkCode == VK_RWIN) // //屏敝 WIN(左右) 键 // { // return TRUE; // } // if (Key_Info->vkCode == 0x4D && ((GetKeyState(VK_LWIN) & 0x8000) || // (GetKeyState(VK_RWIN) & 0x8000))) // //屏敝 WIN+D 组合键(左右) // { // return TRUE; // } // if (Key_Info->vkCode == 0x44 && ((GetKeyState(VK_LWIN) & 0x8000) || // (GetKeyState(VK_LWIN) & 0x8000))) // //屏敝 WIN+M 组合键(左右) // { // return TRUE; // } // if (Key_Info->vkCode == 0x1b && GetKeyState(VK_CONTROL) & 0x8000) // //屏敝 CTRL + ESC 组合键 // { // return TRUE; // } // if (Key_Info->vkCode == VK_TAB && Key_Info->flags & LLKHF_ALTDOWN) // //屏敝 ATL + TAB 组合键 // { // return TRUE; // } // if (Key_Info->vkCode == VK_ESCAPE && Key_Info->flags & LLKHF_ALTDOWN) // //屏敝 ATL + ESC 组合键 // { // return TRUE; // } // if (Key_Info->flags & LLKHF_ALTDOWN) // //屏敝 CTRL 键 // { // return TRUE; // } return CallNextHookEx(g_hhk, nCode, wParam, lParam); } BOOL CTestHookDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here g_hhk = SetWindowsHookEx(13, LowLevelKeyboardProc, GetModuleHandle(NULL), 0); return TRUE; // return TRUE unless you set the focus to a control }
注意 此钩子必须是系统级的钩子,也就是说在安装钩子的时候,ThreadID 的值必须为 0。 在这儿需要特别说明的是:if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN) ,如果不加这句,按键信息会被响应两次(KeyUP & KeyDown),开始我只写了 if (WM_KEYDOWN == wParam) ,在捕获 ALT+TAB 时就一直出错,找不到方向,后来才想到 ALT 键盘是系统键,所以必须得加上WM_SYSKEYDOWN,这样才能捕获 ALT+TAB !if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN)也可以写成if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam)如果要想屏敝 CTRL+ALT+DEL 键的话,也可能用相当的方法!不过可以用一种更简单的方法来屏敝 CTRL+ALT+DEL :屏敝这个组合键的其中任意一个按键便可达到相同的效果。
在 VC 中捕按键可以在 OnKeyDown 或 OnKeyUp 事件中进行捕获,不过这有很大的局限性,这里只能捕获用户按键。但在一些特殊的工程(项目)中往往需要捕获某些系统按键以完成特殊的功能,我们就不得不选择钩子了,一般情况下 大家都会选择 WH_KEYBOARD 这个钩子类型,但是在编写过程会发现这个钩子类型并不能捕获所有的系统按键,怎么办呢?那就得选择WH_KEYBOARD_LL (低级键盘钩子)了,使用它可以捕获全部的系统按键,一个不漏…… 在使用低级键盘钩子之前,先在 StdAfx.h 的第一行添加一条: #define _WIN32_WINNT 0x400 (这里假定你是用的 MFC 的 DLL),不然在编译的时候会提示说 WH_KEYBOARD_LL 没有定义。
网上还有另一种方法: 首先定义 #define WH_KEYBOARD_LL 13 然后 Winuser.h 中定义的 tagKBDLLHOOKSTRUCT 代码拷贝到工程中。 下面代码用以捕获系统按键:
注意 此钩子必须是系统级的钩子,也就是说在安装钩子的时候,ThreadID 的值必须为 0。 在这儿需要特别说明的是:if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN) ,如果不加这句,按键信息会被响应两次(KeyUP & KeyDown),开始我只写了 if (WM_KEYDOWN == wParam) ,在捕获 ALT+TAB 时就一直出错,找不到方向,后来才想到 ALT 键盘是系统键,所以必须得加上WM_SYSKEYDOWN,这样才能捕获 ALT+TAB !if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN)也可以写成if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam)如果要想屏敝 CTRL+ALT+DEL 键的话,也可能用相当的方法!不过可以用一种更简单的方法来屏敝 CTRL+ALT+DEL :屏敝这个组合键的其中任意一个按键便可达到相同的效果。