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文件。
// KeyBoardHook.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "KeyBoardHook.h"
#include
#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