失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 设置全局键盘钩子和消息钩子

设置全局键盘钩子和消息钩子

时间:2024-02-05 15:35:47

相关推荐

设置全局键盘钩子和消息钩子

前几天因为工作需要用到钩子,而且是全局钩子,用来监视别人的程序键盘消息。需要注意几点

1.如果只需要监视自己的应用程序,在自己程序里设置钩子就行。

2.如果需要监视别人的应用程序,一定要做成DLL形式的全局钩子。

首先我是用VS新建一个DLL 工程。头文件如下

#ifndef __KEYHOOK_H_H#define __KEYHOOK_H_H#ifdef MY_HOOK_API#else#define MY_HOOK_API _declspec(dllimport)#endif#ifdef __cplusplusextern "C" {#endif MY_HOOK_API BOOL __stdcall Reg_raw_input(HWND hwnd);//注册输入信息,这个可以不要,因为自己工作的原因需要加上MY_HOOK_API BOOL __stdcall InstallHook();MY_HOOK_API BOOL __stdcall UnInstallHook();#ifdef __cplusplus}#endif #endif

.CPP文件

自己使用RegisterRawInputDevices这个函数时有一个小问题卡了很久,用这个RIDEV_INPUTSINK标志时(即窗口不在前台时也台捕捉输入源信息),微软文档明确说明不用指定hwndTarget,试了很多次也不成功。然后直接有DLL用FindWindows找自己需要的句柄传给hwndTarget,还是返回失败,只有设置RIM_INPUT才可以,最后偶尔把上层应用的主窗口GetSafeWind()返回的句柄给hwndTarget时才成功。

BOOL __stdcall Reg_raw_input(HWND hwnd){static bool bReg_raw_input = false;if(bReg_raw_input)return FALSE; RAWINPUTDEVICE dev;memset(&dev, 0, sizeof(dev));dev.usUsagePage = 1;dev.usUsage = 6;dev.dwFlags = RIDEV_INPUTSINK;//dev.dwFlags = RIDEV_INPUTSINK;//RIM_INPUT;//Shejn /7/17 16:34:31 adddev.hwndTarget = hwnd;BOOL bReg = RegisterRawInputDevices(&dev, 1, sizeof(dev));bReg_raw_input = true;return bReg;};BOOL __stdcall InstallHook(){BOOL bRet = 1;UProductCmd cmd;bNewKey = cmd.IsUseKeyNewMap();_hHook_msg1 = SetWindowsHookEx(WH_GETMESSAGE, msg_hook_Proc1,g_hInst, NULL);//GetCurrentThreadId());最后一个参数为0表明监视所有线程而不是本身if (_hHook_msg1 == NULL){bRet = 0;}g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL,//这里使用底层键盘钩子,在键盘动产生作用前就响应,而且底层钩子比消息钩子先响应LowLevelKeyboardProc,g_hInst,NULL);if (g_hHook == NULL){bRet = 0;}return bRet;//return g_hHook == NULL ? FALSE : TRUE;}BOOL __stdcall UnInstallHook(){UnhookWindowsHookEx(_hHook_msg1); return UnhookWindowsHookEx(g_hHook);}BOOL WINAPI DllMain(IN HINSTANCE hDllHandle,IN DWORD nReason,IN LPVOID Reserved){//g_hInst = hDllHandle;//return TRUE;switch (nReason){case DLL_PROCESS_ATTACH:g_hInst=HINSTANCE(hDllHandle);break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH://UnInstallHook();//这个要注释掉,后来发现如果监视的程序关掉,会直接调用这里,导致全局钩子失效,需要卸载钩子时在上层应用关闭时调用break;}return TRUE;}

下面这段代码注意,如果是回车和空格互换,比如VK_RETURN变成VK_SPACE,keybd_event(VK_SPACE, 0 0, 0);似乎还会键盘钩子捕获到VK_SPACE,为了保险起见,最好设置一个标志,如果是第二个keybd_event产生,则直接return CallNextHookEx(g_hHook, code, wParam, lParam); 这点还没确认,高手可以去确认下。

DWORD dwIndex = 0;BYTE g_bFreezeCAVK[2] = {VK_F2, VK_F8};LRESULT CALLBACK LowLevelKeyboardProc(int code,WPARAM wParam,LPARAM lParam){if(code == HC_ACTION){PKBDLLHOOKSTRUCT pStruct = (PKBDLLHOOKSTRUCT)lParam;switch (pStruct->vkCode){case VK_RETURN:dwIndex = 0;break;case VK_SPACE:dwIndex = 1;break; default:bWork = FALSE;return CallNextHookEx(g_hHook, code, wParam, lParam);}if (wParam == WM_KEYDOWN){keybd_event(g_bVK[dwIndex], MapVirtualKey(g_bVK[dwIndex], 0), 0, 0);return 1;//CallNextHookEx(g_hHook, code, wParam, lParam);//这里注意返回1是原按键无效,如果是CallNextHookEx则会断续传递还会产生原按键消息}}return CallNextHookEx(g_hHook, code, wParam, lParam);}

//消息钩子,这段代码可以忽略,根据自己的需要来LRESULT CALLBACK msg_hook_Proc1(int nCode, WPARAM wParam, LPARAM lParam){MSG* pMsg = (MSG*)lParam;if(nCode < 0)return CallNextHookEx(_hHook_msg1, nCode, wParam, lParam);if(pMsg->message == WM_INPUT){HRAWINPUT hInput = (HRAWINPUT)pMsg->lParam;CString strDev_name = get_dev_name(hInput);UProductCmd cmd;CString strMini_kbd_id = cmd.get_setting("keyboard", "MiniKeyboardID", "Vid_04d9&Pid_1603");strMini_kbd_id.MakeLower();strDev_name.MakeLower();int aTest = strDev_name.Find(strMini_kbd_id);if(strDev_name.Find(strMini_kbd_id) >= 0 && bNewKey)//cmd.IsUseKeyNewMap()){_bHid = true;}else{_bHid = false;}//bWork = TRUE;if (bWork){if(_bHid){if (bFreeze){keybd_event(g_bFreezeCAVK[dwIndex], MapVirtualKey(g_bFreezeCAVK[dwIndex], 0), 0, 0);}elsekeybd_event(g_bLiveCAVK[dwIndex], MapVirtualKey(g_bLiveCAVK[dwIndex], 0), 0, 0);//keybd_event(g_bCAVK[dwIndex], MapVirtualKey(g_bCAVK[dwIndex], 0), 0, 0);if (dwIndex == 0){bFreeze = !bFreeze;}}else{bKeep = TRUE;if (bNewKey){keybd_event(g_bNewVK[dwIndex], MapVirtualKey(g_bNewVK[dwIndex], 0), 0, 0);}else{keybd_event(g_bOldVK[dwIndex], MapVirtualKey(g_bOldVK[dwIndex], 0), 0, 0);}}}bWork = FALSE;}return CallNextHookEx(_hHook_msg1, nCode, wParam, lParam);}

如果觉得《设置全局键盘钩子和消息钩子》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。