[概述][相关函数][编写消息钩子]
钩子过程
操作系统在传递消息时,将我们感兴趣的消息先传递给HOOK过程,在此函数中进行检查,然后在决定是否放行该消息,就好像逃犯在逃亡时可能会经过许多段路段,为了抓住他,警察要在某些地方设置检查站,以便检查过往的车辆和行人,我们可以把车辆和行人看做是消息,检查站就好像是HOOK过程,如果在摸个检查站发现了这个逃犯,就会把他抓起来,这样就相当于阻止了逃犯的逃亡过程,让他无法在继续逃亡下去了,这个道理和钩子过程是一样的,操作系统将我们感兴趣的消息都交给钩子过程,后者实际就是一个函数,在此函数中进行判断,如果是我们希望屏蔽的消息,那么就直接处理掉,不然它继续向下传递.如果我们不感兴趣的消息,就直接放弃对它们的处理,这就好像对于那些不是逃犯的行人和车辆一样,警察会让他们继续前进
钩子链
SetWindowsHookEx函数作用是安装一个应用程序定义的钩子过程,并将其放到钩子链中,为了让读者更好的理解钩子的概念,让我们在看看前面所举的逃犯的例子.警察在抓捕逃犯时,可以再多个地方设置检查站,逐一对车辆和行人进行排查,同样地,应用程序也可以在多个地方安装钩子函数,对我们感兴趣的多个消息逐一进行排查,这样多个钩子过程就形成了钩子链,要注意的是,最后安装的钩子过程总是排列在该链的前面
消息钩子分类
[设置消息钩子][消息钩子回调函数][移除消息钩子]
设置消息钩子 SetWindowsHookEx
函数原型
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier
);
参数说明
指定要安装的钩子过程的类型
对应的回调函数也就是钩子函数的处理过程的形式在MSDN查阅
如果钩子函数返回非零值,表示已经对当前消息进行了处理,这样系统就不会在将这个消息传递给目标窗口过程,因此,如果钩子过程对于当前消息进行处理,则返回一个非零值,以避免系统再次将此消息传递给目标窗口过程;否则建议调用CallNextHookEx含返回该函数的返回值,以便其他安装了此消息类型钩子过程的应用程序捕获相应的通知
指向相应的钩子过程,如果dwThreadId参数为0,或者指定了一个其他进程创建的线程标识符,那么参数lpfn必须指向一个位于动态链接库中的钩子过程.否则,参数lpfn可以指向当前进程相关的代码中定义的一个钩子过程
指定lpfn指向的钩子过程所在的DLL的句柄,如果参数dwThreadId指定的线程由当前进程穿件,并且相应的钩子过程定义与当前进程相关的代码中,那么必须将参数hMod设置为NULL(全局钩子,此参数必须指向DLL句柄)
指定与钩子过程相关的线程标识,如果值为0,那么按照的钩子过程将与桌面上运行的所有线程都有关(安装的钩子过程可以与某个特定线程相关,也可以和所有线程相关,取决于这个参数的取值)
返回值
如果成功返回的值是钩子过程的句柄,如果函数失败返回的是NULL
钩子回调函数原型 CallNextHookEx
函数原型
LRESULT CallNextHookEx(
HHOOK hhk, // handle to current hook
int nCode, // hook code passed to hook procedure
WPARAM wParam, // value passed to hook procedure
LPARAM lParam // value passed to hook procedure
);
参数说明
返回值
这个值是在钩子链中的下个钩子函数的返回值
取消消息钩子函数 UnhookWindowsHookEx
函数原型
BOOL UnhookWindowsHookEx(
HHOOK hhk // handle to hook procedure
);
参数说明
流程图:
代码样例:
进程钩子
程序源码:
#include
#include
HHOOK g_hKeyboard=NULL;
HHOOK g_hMouse=NULL;
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
//当按下回车键时候取消消息钩子
if(VK_RETURN==wParam)
{
UnhookWindowsHookEx(g_hKeyboard);
UnhookWindowsHookEx(g_hMouse);
MessageBox(NULL,"取消消息钩子","消息",MB_OK);
}
return 1;
}
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
WNDCLASS wndclass;
MSG msg;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=textprom;
wndclass.lpszClassName="text";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,"create windows error!","error",MB_OK | MB_ICONSTOP);
}
HWND hwnd=CreateWindow("text","hellow world",WS_DLGFRAME | WS_MINIMIZEBOX | WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,
400,250,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//设置鼠标和键盘消息钩子
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,GetCurrentThreadId());
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
运行结果:
全局钩子
动态链接库源码:
// .h 头文件 -----------------------------------------------------
#ifndef DLL_API
#define DLL_API _declspec(dllimport)
#endif
#include"windows.h"
HHOOK g_hMouse=NULL;
HHOOK g_hKeyboard=NULL;
DLL_API void SetHook();
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam,LPARAM lParam);
// .cpp 源程序 ---------------------------------------------------
#define DLL_API _declspec(dllexport)
#include"dllHook.h"
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(VK_RETURN==wParam)
{
UnhookWindowsHookEx(g_hMouse);
UnhookWindowsHookEx(g_hKeyboard);
MessageBox(NULL,"取消消息钩子","消息",MB_OK);
}
return 1;
}
void SetHook()
{
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle("dllHook.dll"),0);
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("dllHook.dll"),0);
}
程序源码:
#include
//加载动态连接库头文件
#include"../dllHook/dllHook.h"
//加载动态连接库的引入库(LIB)
#pragma comment(lib, "../debug/dllHook.lib")
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
WNDCLASS wndclass;
MSG msg;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=textprom;
wndclass.lpszClassName="text";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,"create windows error!","error",MB_OK | MB_ICONSTOP);
}
HWND hwnd=CreateWindow("text","hellow world",WS_DLGFRAME | WS_MINIMIZEBOX | WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,
400,250,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK textprom(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(uMsg)
{
case WM_LBUTTONDOWN:
//设置消息钩子
SetHook();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
运行结果(回车钱所有鼠标事件和键盘事件都将被屏蔽)
[相关函数][编写定时器]
[建立定时器][删除定时器]
建立新定时器 SetTimer
函数原型:
UINT SetTimer(
HWND hWnd,
UINT nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc );
参数说明:
返回值
如果函数成功,则返回新定时器的标识符.应用程序可以将这个值传递给KillTimer成员函数以销毁定时器.如果成功,则返回非零值;否则返回0
说明:
void CALLBACK EXPORT TimerProc(
HWND hWnd, // 调用SetTimer的窗口的句柄
UINT nMsg, // WM_TIMER
UINT nIDEvent // 定时器标识
DWORD dwTime // 系统时间
);
定时器是有限的全局资源;因此对于应用程序来说,检查SetTimer返回的值以确定定时器是否可用是很重要的消除已存在定时器
函数原型
BOOL KillTimer( int nIDEvent );
参数说明
返回值
指定了函数的结果.如果事件已经被销毁,则返回值为非零值.如果KillTimer成员函数不能找到指定的定时器事件,则返回0
说明
流程图:
代码样例:
程序源码:
#include"windows.h"
#include
#include
using namespace std;
VOID CALLBACK TimerProc(HWND hwnd,UINT msg ,UINT_PTR dwEvent,DWORD dwTime);
void main()
{
MSG msg;
//建立定时器
UINT TimerID = SetTimer(NULL,1,1000,(TIMERPROC)TimerProc);
//消息循环
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
system("pause");
}
VOID CALLBACK TimerProc(HWND hwnd,UINT msg ,UINT_PTR dwEvent,DWORD dwTime)
{
cout<<"定时器消息回调函数调用成功"<
运行结果: