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. 设置钩子 2. 释放钩子 3. 钩子进程 4. 调用下一个钩子函数
钩子的建立 1. 建立一个动态连接库的.cpp文件。 // KeyBoardHook.cpp : Defines the entry point for the DLL application. //
#include "stdafx.h" #include "KeyBoardHook.h" #include <Pwinuser.h> #include "BasalMessage.h" //#include "FileManage.h"
#pragma data_seg("KeyHookData") HINSTANCE hInst = NULL; #pragma data_seg()
//告诉编译器设置共享节的访问方式为:读,写,共享 #pragma comment(linker, "/SECTION:KeyHookData,RWS")
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: hInst = (HINSTANCE)hModule; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
// This is an example of an exported variable KEYBOARDHOOK_API int nKeyBoardHook=0;
// This is an example of an exported function. KEYBOARDHOOK_API int fnKeyBoardHook(void) { return 42; }
// This is the constructor of a class that has been exported. // see KeyBoardHook.h for the class definition CKeyBoardHook::CKeyBoardHook() { return; }
extern "C" KEYBOARDHOOK_API void InstallHook(void) { if (hInst) { hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardProc, hInst, 0); } }
extern "C" KEYBOARDHOOK_API void UnHook(void) { if (hKeyHook) { UnhookWindowsHookEx(hKeyHook); hKeyHook = NULL; }
hInst = NULL; }
extern "C" KEYBOARDHOOK_API LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam) { TCHAR t_WndClassName[50] = { 0 }; HWND hCurActiveWnd = NULL; HWND hCurForegroundWnd = NULL; BOOL bIsTaskBarMsg = FALSE; BOOL bIsOEMmsg = FALSE;
PKBDLLHOOKSTRUCT pkbhs = (PKBDLLHOOKSTRUCT)lParam;
if (WM_KEYDOWN == wParam) { uCount++; RETAILMSG(1, (TEXT("WM_KEYDOWN vk %d \r\n"),pkbhs->vkCode)); //响应按键声,并限制需要向上Post的vkCode switch (pkbhs->vkCode) { case VK_UP: break; case VK_DOWN: break; case VK_LEFT: break; case VK_RIGHT: break; case VK_OEM_SELECT: bIsOEMmsg = TRUE; break; case VK_OEM_OK: bIsOEMmsg = TRUE; break; case VK_OEM_BACK: bIsOEMmsg = TRUE; break; case VK_OEM_DIAL: bIsOEMmsg = TRUE; break; case VK_NUMPAD1: case 0x31: break; case VK_NUMPAD2: case 0x32: break; case VK_NUMPAD3: case 0x33: break; case VK_NUMPAD4: case 0x34: break; case VK_NUMPAD5: case 0x35: break; case VK_NUMPAD6: case 0x36: break; case VK_NUMPAD7: case 0x37: break; case VK_NUMPAD8: case 0x38: break; case VK_NUMPAD9: case 0x39: break; case VK_NUMPAD0: case 0x30: break; case VK_OEM_ASTERISK: bIsOEMmsg = TRUE; break; case VK_OEM_POUND: bIsOEMmsg = TRUE; break; case VK_OEM_SIDEUP: bIsOEMmsg = TRUE; break; case VK_OEM_SIDEDOWN: bIsOEMmsg = TRUE; break; case VK_OEM_CAMERA: bIsOEMmsg = TRUE; break; default: uCount = 0; return CallNextHookEx(hKeyHook, nCode, wParam, lParam); //继续传递消息 }
if (bNeedPassOnceMsg) { return TRUE; }
//只发送OEM消息,其它消息并不拦截。 //拦截原消息,发送自定义消息。 //限制需要向上Post的vkCode switch (pkbhs->vkCode) { return CallNextHookEx(hKeyHook, nCode, wParam, (LPARAM)pkbhs); //转换为回车消息传递(未测试) } case VK_OEM_OK: case VK_OEM_BACK: case VK_OEM_DIAL: case VK_OEM_DISCONNECT: bIsOEMmsg = TRUE; break; case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_NUMPAD0: case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: break; case VK_OEM_ASTERISK: case VK_OEM_POUND: case VK_OEM_SIDEUP: case VK_OEM_SIDEDOWN: case VK_OEM_CAMERA: bIsOEMmsg = TRUE; break; default: return CallNextHookEx(hKeyHook, nCode, wParam, lParam); //继续传递消息 }
//只发送OEM消息,其它消息并不拦截。 if (bOnlySendOEMMsg) { if (bIsOEMmsg) { PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), (LPARAM)uCount); return TRUE; //拦截OEM消息,不再向上传递此消息。 } else { return CallNextHookEx(hKeyHook, nCode, wParam, lParam); //继续传递其它消息 } }
//拦截原消息,发送自定义消息。 if (bHoldUpMsg) {//菜单未弹出的情况 PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), 0L); return TRUE; //拦截消息,不再向上传递此消息。 } } else { uCount = 0; }
return CallNextHookEx(hKeyHook, nCode, wParam, lParam); //继续传递消息 }
extern "C" KEYBOARDHOOK_API void SetAppHWND(HWND hCurAppWnd) { hAppWnd = hCurAppWnd; }
extern "C" KEYBOARDHOOK_API void SetTopHWND(HWND hCurTopWnd) { hTopWnd = hCurTopWnd; }
extern "C" KEYBOARDHOOK_API void SetHoldUpMsg(BOOL bHoldUp) { bHoldUpMsg = bHoldUp; }
extern "C" KEYBOARDHOOK_API void SetOnlySendOEMMsg(BOOL bOnlySendOEM) { bOnlySendOEMMsg = bOnlySendOEM; }
extern "C" KEYBOARDHOOK_API void SetNeedPassOnceMsg(BOOL bWhetherNeed) { bNeedPassOnceMsg = bWhetherNeed; } 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. 建立程序主文件 if (hModule) { InHook = (pInstallHook)GetProcAddress(hModule, L"InstallHook"); UnHook = (pUnHook)GetProcAddress(hModule, L"UnHook"); SetAppHWND = (pSetAppHWND)GetProcAddress(hModule, L"SetAppHWND"); SetTopHWND = (pSetTopHWND)GetProcAddress(hModule, L"SetTopHWND"); SetHoldUpMsg = (pSetHoldUpMsg)GetProcAddress(hModule, L"SetHoldUpMsg"); SetOnlySendOEMMsg = (pSetOnlySendOEMMsg)GetProcAddress(hModule, L"SetOnlySendOEMMsg"); SetNeedPassOnceMsg = (pSetNeedPassOnceMsg)GetProcAddress(hModule, L"SetNeedPassOnceMsg");
if (!InHook || !UnHook || !SetAppHWND || !SetTopHWND || !SetHoldUpMsg || !SetOnlySendOEMMsg || !SetNeedPassOnceMsg) { MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK); PostQuitMessage(0); } } else { MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK); PostQuitMessage(0); }
InHook();
DLL的编写,也可以参考以下网址中的内容: http://www.bc-cn.net/Article/kfyy/cyy/jszl/200709/6328_2.html
WinCE上支持三种类型的Hook #define WH_JOURNALRECORD 0 不过前两个使用的时候是使用如下函数: 后者使用SetWindowsHookExW和UnhookWindowsHookEx (91program) |