基于键盘钩子的dota改键(单线程+DLL)MFC实现(源码+总结)

来源:互联网 发布:陕西省广电网络营业厅 编辑:程序博客网 时间:2024/05/18 02:54


呼。。终于可以摒弃网上带广告的改键工具了。。 历经三天,写出自己的dota改键软件最简单版了。 还学习了两个新知识,钩子和动态链接库。下面以一个新手的角度,总结下这三天遇到的大小问题。


一般钩子在什么时刻被调用?
操作系统把消息放进进程的消息队列后, 进程GetMessage()前。 

钩子分类?
局部钩子:只能监视本进程内的线程。
远程钩子:远程钩子分为以下两种(两种一般都要DLL注入,极个别不用)
远程单线程钩子:监视单一线程。(魔兽改键。。 我用的就是这个~~)
全局钩子:监视所有线程。

钩子过程函数中,怎么样修改键值?
经测试,不可以修改健值。可能采取了副本复制之类的吧。可以keybd_event产生新消息,并屏蔽原消息。也可以用SendMessage...


貌似还可以用 WH_KEYBOARD_LL 来避免 DLL注入。。以后有心情再研究。备注下:

WH_KEYBOARD WH_KEYBOARD_LL 的区别?
WH_KEYBOARD的钩子过程在GetMessage或PeekMessage要取回一个键盘消息时调用,直接在被监视的线程中执行
WH_KEYBOARD_LL的钩子过程在一个键盘消息被投递到一个线程的消息队列之前调用,这个是向安装钩子的线程发送消息,让安装钩子的线程执行钩子过程,WH_KEYBOARD_LL必须是全局钩子,而且不需要在dll中

 

附上屏蔽组合键方法 WIN型 ALT型 与 CTRL 型

p  =  (PKBDLLHOOKSTRUCT)  lParam;  switch  (wParam)    {  case  WM_KEYDOWN:    case  WM_SYSKEYDOWN:  case  WM_KEYUP:          case  WM_SYSKEYUP:    fEatKeystroke  =  //  屏蔽Win(p->vkCode  ==  VK_LWIN)    || (p->vkCode  ==  VK_RWIN) ||      //  屏蔽Alt+Tab  ((p->vkCode  ==  VK_TAB)  &&  ((p->flags  &  LLKHF_ALTDOWN)  !=  0))    ||  //  屏蔽Alt+Esc  ((p->vkCode  ==  VK_ESCAPE)  &&  ((p->flags  &  LLKHF_ALTDOWN)  !=  0))   ||//  屏蔽Ctrl+Esc  ((p->vkCode  ==  VK_ESCAPE)  &&  ((GetKeyState(VK_CONTROL)  &  0x8000)  !=  0));  break;  default:  break;  }  



 

DLL源码 主要部分:

#include <windows.h>//设置数据段为共享#pragma data_seg(".wzy")HHOOK g_hKeyboard=NULL;static WORD g_KeyNumber[10]={0};int g_lenth=0;#pragma data_seg()#pragma comment( linker,"/section:.wzy,RWS" )LRESULT CALLBACK KeyboardProc(  int code,       // hook code  WPARAM wParam,  // virtual-key code  LPARAM lParam   // keystroke-message information){if(code == HC_ACTION){// 显血功能if( wParam == VK_HOME &&  (((lParam>>31)&1) == 0) )  //按下HOME键{keybd_event(VK_OEM_4,0,0,0);         //就一直按下 [ 键来显血return 1;}if( wParam == VK_END &&  (((lParam>>31)&1) == 0) )  //按下END键{keybd_event(VK_OEM_4,0,KEYEVENTF_KEYUP,0);         //就弹起 [ 键来 结束显血return 1;}if( wParam == g_KeyNumber[0]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD7,0,0,0);keybd_event(VK_NUMPAD7,0,KEYEVENTF_KEYUP,0);return 1;}if( wParam == g_KeyNumber[1]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD8,0,0,0);keybd_event(VK_NUMPAD8,0,KEYEVENTF_KEYUP,0);return 1;}if( wParam == g_KeyNumber[2]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD4,0,0,0);keybd_event(VK_NUMPAD4,0,KEYEVENTF_KEYUP,0);return 1;}if( wParam == g_KeyNumber[3]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD5,0,0,0);keybd_event(VK_NUMPAD5,0,KEYEVENTF_KEYUP,0);return 1;}if( wParam == g_KeyNumber[4]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD1,0,0,0);keybd_event(VK_NUMPAD1,0,KEYEVENTF_KEYUP,0);return 1;}if( wParam == g_KeyNumber[5]){if( ((lParam>>31)&1) == 1) // 如果是弹起,忽略掉return 1;keybd_event(VK_NUMPAD2,0,0,0);keybd_event(VK_NUMPAD2,0,KEYEVENTF_KEYUP,0);return 1;}}return CallNextHookEx(g_hKeyboard,code,wParam,lParam);}_declspec(dllexport) void SetHook(HWND hwnd,WORD KeyNumber[],int lenth){//参数先拷好。for(int i=0;i<lenth;++i)g_KeyNumber[i]=KeyNumber[i];g_lenth = lenth;g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle("KeyboardProc.dll"),GetWindowThreadProcessId( FindWindow("Warcraft III",0),NULL)); }_declspec(dllexport) void DelHook(HWND hwnd){UnhookWindowsHookEx(g_hKeyboard);g_hKeyboard = NULL;  //没卸载成功也强制弄成NULL}

对话框部分,主要是一个定时器:

// 增加定时器 判断魔兽是否已经打开void CChangeKeyDlg::OnTimer(UINT nIDEvent) {// TODO: Add your message handler code here and/or call defaultif(nIDEvent==1){if( m_bCheck == FALSE ){if( ::FindWindow("Warcraft III",0) ){m_bCheck = TRUE;WORD modi;UpdateData(TRUE);m_Key7.GetHotKey( KeyNumber[0] , modi);m_Key8.GetHotKey( KeyNumber[1] , modi);m_Key4.GetHotKey( KeyNumber[2] , modi);m_Key5.GetHotKey( KeyNumber[3] , modi);m_Key1.GetHotKey( KeyNumber[4] , modi);m_Key2.GetHotKey( KeyNumber[5] , modi);MessageBox("目标进程开启了");DelHook(m_hWnd);SetHook(m_hWnd,KeyNumber,6);    // 一发现目标进程,就安装钩子。}}else{if( ::FindWindow("Warcraft III",0) == 0) {DelHook(m_hWnd);m_bCheck = FALSE;}}}

源码下载地址(DLL版):http://download.csdn.net/detail/a576323437/4613035



原创粉丝点击