EVC编程点滴四 - 钩子

Posted 91program

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EVC编程点滴四 - 钩子相关的知识,希望对你有一定的参考价值。

wince下支持三种钩子:

1.#define WH_JOURNALRECORD 0使应用程序可以监视输入事件。典型地,应用程序使用该HOOK记录鼠标、键盘输入事件以供以后回放。该HOOK是全局HOOK,并且不能在指定线程中使用。

2#define WH_JOURNALPLAYBACK 1使应用程序可以向系统消息队列中插入消息。该HOOK可以回放以前由WH_JOURNALRECORD HOOK录制的鼠标、键盘输入事件。在WH_JOURNALPLAYBACK Hook安装到系统时,鼠标、键盘输入事件将被屏蔽。该HOOK同样是一个全局HOOK,不能在指定线程中使用。

WH_JOURNALPLAYBACK Hook返回一个时间暂停值,它告诉系统,在处理当前回放的消息时,系统等待百分之几秒。这使得此HOOK可以控制在回放时的时间事件

3#define WH_KEYBOARD_LL 20  

 

其中最常用的是键盘钩子,其它两个偶没有用过。

1.  设置钩子 通过SetWindowsHookEx ()函数

2.  释放钩子 UnhookWindowsHookEx()函数

3.  钩子进程 函数HookProc

4.  调用下一个钩子函数 CallNexHookEx()函数

 

钩子的建立

1.  建立一个动态连接库的.cpp文件。

 

  1 // KeyBoardHook.cpp : Defines the entry point for the DLL application.
  2 //
  3  
  4 #include "stdafx.h"
  5 #include "KeyBoardHook.h"
  6 #include <Pwinuser.h>
  7 #include "BasalMessage.h"
  8 //#include "FileManage.h"
  9  
 10 //告诉编译器将变量放入它自己的数据共享节中
 11 #pragma data_seg("KeyHookData")
 12 HINSTANCE hInst = NULL;
 13 #pragma data_seg()
 14  
 15 //告诉编译器设置共享节的访问方式为:读,写,共享
 16 #pragma comment(linker, "/SECTION:KeyHookData,RWS") 
 17  
 18 BOOL APIENTRY DllMain( HANDLE hModule,
 19                        DWORD  ul_reason_for_call,
 20                        LPVOID lpReserved
 21                               )
 22 {
 23     switch (ul_reason_for_call)
 24 {
 25         case DLL_PROCESS_ATTACH:
 26                hInst = (HINSTANCE)hModule;
 27                break;
 28         case DLL_THREAD_ATTACH:
 29         case DLL_THREAD_DETACH:
 30         case DLL_PROCESS_DETACH:
 31                break;
 32     }
 33     return TRUE;
 34 }
 35  
 36  
 37 // This is an example of an exported variable
 38 KEYBOARDHOOK_API int nKeyBoardHook=0;
 39  
 40 // This is an example of an exported function.
 41 KEYBOARDHOOK_API int fnKeyBoardHook(void)
 42 {
 43 return 42;
 44 }
 45  
 46 // This is the constructor of a class that has been exported.
 47 // see KeyBoardHook.h for the class definition
 48 CKeyBoardHook::CKeyBoardHook()
 49 {
 50 return;
 51 }
 52   
 53 extern "C" KEYBOARDHOOK_API void InstallHook(void)
 54 {
 55 if (hInst)
 56 {
 57         hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardProc, hInst, 0);
 58 }
 59 }
 60  
 61 extern "C" KEYBOARDHOOK_API void UnHook(void)
 62 {
 63 if (hKeyHook)
 64 {
 65         UnhookWindowsHookEx(hKeyHook);
 66         hKeyHook = NULL;
 67 }
 68  
 69 hInst = NULL;
 70 }
 71  
 72 extern "C" KEYBOARDHOOK_API LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)
 73 {
 74 TCHAR t_WndClassName[50] = { 0 };
 75 HWND hCurActiveWnd = NULL;
 76 HWND hCurForegroundWnd = NULL;
 77 BOOL bIsTaskBarMsg = FALSE;
 78 BOOL bIsOEMmsg = FALSE;
 79  
 80 PKBDLLHOOKSTRUCT pkbhs = (PKBDLLHOOKSTRUCT)lParam;
 81  
 82 if (WM_KEYDOWN == wParam)
 83 {
 84         uCount++;
 85         RETAILMSG(1, (TEXT("WM_KEYDOWN vk %d /r/n"),pkbhs->vkCode));
 86         //响应按键声,并限制需要向上Post的vkCode
 87         switch (pkbhs->vkCode)
 88         {
 89         case VK_UP:
 90                break;
 91         case VK_DOWN:
 92                break;
 93         case VK_LEFT:
 94                break;
 95         case VK_RIGHT:
 96                break;
 97         case VK_OEM_SELECT:
 98                bIsOEMmsg = TRUE;
 99                break;
100         case VK_OEM_OK:
101                bIsOEMmsg = TRUE;
102                break;
103         case VK_OEM_BACK:
104                bIsOEMmsg = TRUE;
105                break;
106         case VK_OEM_DIAL:
107                bIsOEMmsg = TRUE;
108                break;
109         case VK_NUMPAD1:
110 case 0x31:
111                break;
112         case VK_NUMPAD2:
113 case 0x32:
114                break;
115         case VK_NUMPAD3:
116 case 0x33:
117                break;
118         case VK_NUMPAD4:
119 case 0x34:
120               break;
121         case VK_NUMPAD5:
122 case 0x35:
123                break;
124         case VK_NUMPAD6:
125 case 0x36:
126                break;
127         case VK_NUMPAD7:
128 case 0x37:
129                break;
130         case VK_NUMPAD8:
131 case 0x38:
132                break;
133         case VK_NUMPAD9:
134 case 0x39:
135                break;
136         case VK_NUMPAD0:
137 case 0x30:
138                break;
139         case VK_OEM_ASTERISK:
140                bIsOEMmsg = TRUE;
141                break;
142         case VK_OEM_POUND:
143                bIsOEMmsg = TRUE;
144                break;
145         case VK_OEM_SIDEUP:
146                bIsOEMmsg = TRUE;
147                break;
148         case VK_OEM_SIDEDOWN:
149                bIsOEMmsg = TRUE;
150                break;
151         case VK_OEM_CAMERA:
152                bIsOEMmsg = TRUE;
153                break;
154         default:
155                uCount = 0;
156                return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息
157         }
158  
159         if (bNeedPassOnceMsg)
160         {
161                return TRUE;
162         }
163  
164         //只发送OEM消息,其它消息并不拦截。
165         //拦截原消息,发送自定义消息。
166         //限制需要向上Post的vkCode
167         switch (pkbhs->vkCode)
168         {
169                       return CallNextHookEx(hKeyHook, nCode, wParam, (LPARAM)pkbhs);   //转换为回车消息传递(未测试)
170 }
171         case VK_OEM_OK:
172         case VK_OEM_BACK:
173         case VK_OEM_DIAL:
174         case VK_OEM_DISCONNECT:
175                bIsOEMmsg = TRUE;
176                break;
177         case VK_NUMPAD1:
178         case VK_NUMPAD2:
179         case VK_NUMPAD3:
180         case VK_NUMPAD4:
181         case VK_NUMPAD5:
182        case VK_NUMPAD6:
183         case VK_NUMPAD7:
184         case VK_NUMPAD8:
185         case VK_NUMPAD9:
186         case VK_NUMPAD0:
187 case 0x30:
188 case 0x31:
189 case 0x32:
190 case 0x33:
191 case 0x34:
192 case 0x35:
193 case 0x36:
194 case 0x37:
195 case 0x38:
196 case 0x39:
197                break;
198         case VK_OEM_ASTERISK:
199         case VK_OEM_POUND:
200         case VK_OEM_SIDEUP:
201         case VK_OEM_SIDEDOWN:
202         case VK_OEM_CAMERA:
203                bIsOEMmsg = TRUE;
204                break;
205         default:
206                return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息
207         }
208  
209         //只发送OEM消息,其它消息并不拦截。
210         if (bOnlySendOEMMsg)
211         {
212                if (bIsOEMmsg)
213                {
214                       PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), (LPARAM)uCount);
215                       return TRUE;  //拦截OEM消息,不再向上传递此消息。                    
216                }
217                else
218                {
219                       return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递其它消息
220                }
221         }
222  
223         //拦截原消息,发送自定义消息。
224         if (bHoldUpMsg)
225         {//菜单未弹出的情况
226                PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), 0L);
227                return TRUE;  //拦截消息,不再向上传递此消息。
228         }
229 }
230 else
231 {
232         uCount = 0;
233 }
234  
235 return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息
236 }
237  
238 extern "C" KEYBOARDHOOK_API void SetAppHWND(HWND hCurAppWnd)
239 {
240 hAppWnd = hCurAppWnd;
241 }
242  
243 extern "C" KEYBOARDHOOK_API void SetTopHWND(HWND hCurTopWnd)
244 {
245 hTopWnd = hCurTopWnd;
246 }
247  
248 extern "C" KEYBOARDHOOK_API void SetHoldUpMsg(BOOL bHoldUp)
249 {
250 bHoldUpMsg = bHoldUp;
251 }
252  
253 extern "C" KEYBOARDHOOK_API void SetOnlySendOEMMsg(BOOL bOnlySendOEM)
254 {
255 bOnlySendOEMMsg = bOnlySendOEM;
256 }
257  
258 extern "C" KEYBOARDHOOK_API void SetNeedPassOnceMsg(BOOL bWhetherNeed)
259 {
260 bNeedPassOnceMsg = bWhetherNeed;
261 }

2.  建立头文件

 

// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the KEYBOARDHOOK_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// KEYBOARDHOOK_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef KEYBOARDHOOK_EXPORTS
#define KEYBOARDHOOK_API __declspec(dllexport)
#else
#define KEYBOARDHOOK_API __declspec(dllimport)
#endif
 
// This class is exported from the KeyBoardHook.dll
class KEYBOARDHOOK_API CKeyBoardHook {
public:
CKeyBoardHook(void);
// TODO: add your methods here.
};
 
extern KEYBOARDHOOK_API int nKeyBoardHook;
 
KEYBOARDHOOK_API int fnKeyBoardHook(void);
 
extern "C" KEYBOARDHOOK_API void InstallHook(void);
extern "C" KEYBOARDHOOK_API void UnHook(void);
extern "C" KEYBOARDHOOK_API LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam);
extern "C" KEYBOARDHOOK_API void SetAppHWND(HWND hCurAppWnd);
extern "C" KEYBOARDHOOK_API void SetTopHWND(HWND hCurTopWnd);
extern "C" KEYBOARDHOOK_API void SetHoldUpMsg(BOOL bHoldUp);
extern "C" KEYBOARDHOOK_API void SetOnlySendOEMMsg(BOOL bOnlySendOEM);
extern "C" KEYBOARDHOOK_API void SetNeedPassOnceMsg(BOOL bWhetherNeed);

3.  建立程序主文件

 1 if (hModule)
 2     {
 3         InHook = (pInstallHook)GetProcAddress(hModule, L"InstallHook");
 4         UnHook = (pUnHook)GetProcAddress(hModule, L"UnHook");
 5         SetAppHWND = (pSetAppHWND)GetProcAddress(hModule, L"SetAppHWND");
 6         SetTopHWND = (pSetTopHWND)GetProcAddress(hModule, L"SetTopHWND");
 7         SetHoldUpMsg = (pSetHoldUpMsg)GetProcAddress(hModule, L"SetHoldUpMsg");
 8         SetOnlySendOEMMsg = (pSetOnlySendOEMMsg)GetProcAddress(hModule, L"SetOnlySendOEMMsg");
 9         SetNeedPassOnceMsg = (pSetNeedPassOnceMsg)GetProcAddress(hModule, L"SetNeedPassOnceMsg");
10  
11         if (!InHook || !UnHook || !SetAppHWND || !SetTopHWND || !SetHoldUpMsg || !SetOnlySendOEMMsg || !SetNeedPassOnceMsg)
12         {
13             MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK);
14             PostQuitMessage(0);
15         }
16     }
17     else
18     {
19         MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK);
20         PostQuitMessage(0);
21     }
22  
23 InHook();
24  

DLL的编写,也可以参考以下网址中的内容:

http://www.bc-cn.net/Article/kfyy/cyy/jszl/200709/6328_2.html

 

以上是关于EVC编程点滴四 - 钩子的主要内容,如果未能解决你的问题,请参考以下文章

Web Spider Fiddler - JS Hook 基本使用

编程经验点滴----巧妙解决 Oracle NClob 读写问题

EVC内存检测

EVC在双核PC上调试速度慢的原因

记录代码的点滴!

Spring点滴四:Spring Bean生命周期