目录
- 设置钩子(安装钩子)
- 取消钩子(卸载钩子)
- 回调监听消息(钩子程序或函数)
- 补充
- 例子
1 - 设置钩子(安装钩子)函数
HHOOK SetWindow(int idHook,//钩子类型比如WH_KEYBOARDHOOOKPROC lpfn,//回调函数地址HINSTANCE hMod,//实例句柄DWORD dwThreadid//线程id,可设置为0,但需要dll的回调写入第二参数。可使用GetCurrentThreadId()获取当前线程id)
返回值:若此函数执行成功,则返回值就是该挂钩处理过程的句柄;若此函数执行失败,则返回值为NULL(0).若想获得更多错误信息,请调用GetLastError函数.
idHook:钩子的类型,即它处理的消息类型
lpfn:钩子子程序的地址指针(回调函数名字)。如果dwThreadId参数为0或是别的进程创建的线程id,则lpdn必须指向DLL中的钩子程序。dwThreadId其他情况之外,lpfn可以指向当前进程的一段钩子子程序。获取当前进程的线程id,可以通过GetCurrentThreadId()函数获取。钩子函数的入口地址,当钩子够到任何相关消息后,就会调用这个回调函数。
hMod:应用程序实例句柄。标识包含lpfn所指的子程序(钩子函数)的dll。
dwThreadId:与安装的钩子子程序相关的线程标识符。如果为0,钩子子程序与所有的线程关联,即为全局钩子。
继续启用钩子
hhk:为当前钩子的句柄,由SetWindowsHookEx()函数返回。
NCode:为传给钩子过程的事件代码。
wParam和lParam: 分别是传给钩子子程的wParam值IParam值,其具体含义与钩子类型有关。
2- 取消钩子(卸载钩子)函数
BOOL WINAPI UnhookWindowsHookEx(HHOOK hhk//要删除的钩子句柄。这个参数是上一个函数SetWindowsHookEx的返回值。);
返回值:如果失败,返回0;如果成功,返回非0。BOOL类型。
3- 回调监听消息回调函数(钩子程序)
格式如下
LRESULT CALLBACK FunctionName(int code,//一个代码钩子过程使用,以确定如何处理该信息。如果code小于0,钩子过程必须将信息传递给CallNextHookEx方法不经进一步处理和返回其返回值WPARAM wParam, //附加消息,根据钩子类型而定LPARAM lParam//附加消息,根据钩子类型而定);
注意:该钩子程序也是SetWindows()函数的第二个参数。
补充
函数功能: 该函数检取表示键名的字符串。
int GetKeyNameText(long iParam,//指定被处理的键盘消息(例如WM_KEYDOWN)的第二个参数。LPTSTR lpString,//指向接受键名的缓冲区的指针。int nSize//指定键名的最大字符长度,包括空结束符。)
返回值:若成功,将拷贝一个以空结尾的字符串到指定的缓冲区中,且返回值为该字符串的长度(字符数),不计空字符。若失败,返回0。
iParam:该参数一共32位,每一位如下部分
1、16-23:扫描码
2、24:扩展标记,用于区别增强型键盘上的某些键
3、25:无关位,调用该函数的应用程序设置此位来表示函数不应区分诸如左右按键。
备注:键名字符串的格式取决于当前键盘布局,键盘驱动程序持有一张字符串形式的键名表(每个名字长度大于一个字符)并依据当前安装的键盘布局对键名进行翻译。每个字符键的名字是该字符本身,该键的名字被完整的拼写出来。
例子
#include<windows.h>#include<tchar.h>#include<stdio.h>//钩子变量HHOOK hHook = 0;#pragma comment (lib,"winmm.lib")//拦截信息处理程序(钩子函数)LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam){//打开文件FILE*fp = fopen("key.dat", "a");//继续截获if (fp == NULL){return CallNextHookEx(hHook, code, wParam, lParam);}//获取按键的名称if (code < 0 || code == HC_NOREMOVE){return CallNextHookEx(hHook, code, wParam, lParam);}//lParam是32位 每一位都是特殊含义if (lParam & 0x40000000){return CallNextHookEx(hHook, code, wParam, lParam);}//按键名称char szKeyName[100] = { 0 };GetKeyNameTextA(lParam, szKeyName, 100);//写入文件fwrite(szKeyName, 1, strlen(szKeyName), fp);fwrite("\r\n", 1, 2, fp);//关闭文件fclose(fp);return 0;}LRESULT CALLBACK WndPro(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hpreinstance, LPSTR lpCmdLine, int nCmdShow){//窗口类名TCHAR szWindowClass[] = TEXT("win32程序");//【1】窗口类WNDCLASSEX wnd;wnd.cbClsExtra = 0;//根据窗口类结构分配额外的字节数wnd.cbSize = sizeof(WNDCLASSEX);//窗口类结构大小wnd.cbWndExtra = 0;//窗口实例化之后分配的额外字节数wnd.hbrBackground = CreateSolidBrush(RGB(20, 120, 120));//窗口背景wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//窗口鼠标样式wnd.hIcon = LoadIcon(hinstance, IDI_APPLICATION);//类图标wnd.hInstance = hinstance;//窗口句柄wnd.hIconSm = LoadIcon(wnd.hInstance, IDI_APPLICATION);//与窗口关联的图标wnd.lpfnWndProc = WndPro;//窗口过程函数wnd.lpszClassName = szWindowClass;//窗口类名wnd.lpszMenuName = NULL;//菜单名wnd.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;//窗口变化重绘//【2】注册窗口类if (!RegisterClassEx(&wnd)){MessageBox(NULL, L"注册失败", L"提示", NULL);return 1;}//【3】创建窗口HWND hwnd = CreateWindow(szWindowClass,L"win32",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,500, 500,NULL, NULL,hinstance,NULL);if (!hwnd){MessageBox(NULL, L"创建窗口失败", L"提示", NULL);return 1;}//【4】展示窗口ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd);//【5】消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0) != -1){//[1]翻译消息TranslateMessage(&msg);//[2]转发消息DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WndPro(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){//HMODULE hMod;int i = 0;switch (message){case WM_CREATE:/*hMod= GetModuleHandle(L"win32");if (hMod==0)MessageBox(NULL, L"HOOK_ERROR", L"提示", NULL);*/hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, 0, GetCurrentThreadId());//0表示全局钩子,也可以修改成线程idif (hHook == NULL)MessageBox(NULL, L"HOOK_ERROR", L"提示", NULL);break;case WM_PAINT:break;case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:UnhookWindowsHookEx(hHook);PostQuitMessage(0);break;default:break;}return DefWindowProc(hwnd, message, wParam, lParam);}
结果在data.dat文件。当打开一个其他的程序(如命令窗口dos时),该钩子程序会监听键盘消息,并记录在data.dat文件。