if (lParam & 0x40000000) // Check the previous key state
{
return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
//将自定义消息发送到主窗口
//wParam 定义了虚拟键代码
//lParam 定义了按键数据
::PostMessage(g_hWnd, WM_KEYSTROKE, wParam, lParam);
return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);
}上面PostMessage函数中的g_hWnd是主窗口的句柄,就是我们用来处理检测到的消息的那个窗口。
WM_KEYSTROKE是我们自己定义的一个消息宏,当钩子检测到消息后,就将这个消息发送到主窗口来进行处理。
#define WM_KEYSTROKE (WM_USER + 101)
我们定义了下面一个函数来安装或卸载一个消息钩子。
[cpp]
//安装或者卸载钩子的函数
BOOL WINAPI SetKeyboardHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)
{
BOOL bOk;
g_hWnd = hWndCaller;
if (bInstall)
{
g_hHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc,
ModuleFromAddress(KeyboardHookProc), dwThreadId);//安装消息钩子
bOk = (g_hHook != NULL);
}
else
{
bOk = ::UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bOk;
}
//安装或者卸载钩子的函数
BOOL WINAPI SetKeyboardHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)
{
BOOL bOk;
g_hWnd = hWndCaller;
if (bInstall)
{
g_hHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc,
ModuleFromAddress(KeyboardHookProc), dwThreadId);//安装消息钩子
bOk = (g_hHook != NULL);
}
else
{
bOk = ::UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bOk;
}ModuleFromAddress函数帮助我们获得模块地址:
[cpp]
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if (::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if (::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}由于上面我们定义的消息钩子的回调函数是和安装钩子的程序代码定义在一起的,而不是定义在外部DLL中,所以这个钩子只能监视本线程的消息,而不是一个全局消息钩子。要想实现能对所有程序的键盘消息进行检测,必须将消息钩子的回调函数定义在DLL模块中。
DLL中的定义如下:
.h
[cpp]
#ifdef HOOKDLL_EXPORTS
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif
//自定义消息,当键盘按键按下和释放时发送消息
#define WM_KEYSTROKE (WM_USER + 101)
#define WM_KEYINPUT (WM_USER + 102)
//导出函数
BOOL HOOKDLL_API WINAPI SetKeyboardHook(BOOL bInstall,
DWORD dwThreadId = 0,
HWND hWndCaller = NULL);
#ifdef HOOKDLL_EXPORTS
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif
//自定义消息,当键盘按键按下和释放时发送消息
#define WM_KEYSTROKE (WM_USER + 101)
#define WM_KEYINPUT (WM_USER + 102)
//导出函数
BOOL HOOKDLL_API WINAPI SetKeyboardHook(BOOL bInstall,
DWORD dwThreadId = 0,
HWND hWndCaller = NULL);
.cpp
[cpp]
#include <windows.h>
#define HOOKDLL_EXPORTS
#include "HookDll.h"
// Shared data among all instances.
#pragma data_seg(".HOOKDATA")
HWND g_hWnd = NULL; // Window handle
HHOOK g_hHook = NULL; // Hook handle
// Get module from address
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if (::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}
// 钩子回调函数(钩子过程)
LRESULT CALLB