失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 消息钩子与定时器(VC_Win32)

消息钩子与定时器(VC_Win32)

时间:2024-06-27 17:03:08

相关推荐

消息钩子与定时器(VC_Win32)

目录

消息钩子

定时器

(本章节中例子都是用 VS 编译调试的)

消息钩子

[概述][相关函数][编写消息钩子]

概述

钩子过程

操作系统在传递消息时,将我们感兴趣的消息先传递给HOOK过程,在此函数中进行检查,然后在决定是否放行该消息,就好像逃犯在逃亡时可能会经过许多段路段,为了抓住他,警察要在某些地方设置检查站,以便检查过往的车辆和行人,我们可以把车辆和行人看做是消息,检查站就好像是HOOK过程,如果在摸个检查站发现了这个逃犯,就会把他抓起来,这样就相当于阻止了逃犯的逃亡过程,让他无法在继续逃亡下去了,这个道理和钩子过程是一样的,操作系统将我们感兴趣的消息都交给钩子过程,后者实际就是一个函数,在此函数中进行判断,如果是我们希望屏蔽的消息,那么就直接处理掉,不然它继续向下传递.如果我们不感兴趣的消息,就直接放弃对它们的处理,这就好像对于那些不是逃犯的行人和车辆一样,警察会让他们继续前进

钩子链

SetWindowsHookEx函数作用是安装一个应用程序定义的钩子过程,并将其放到钩子链中,为了让读者更好的理解钩子的概念,让我们在看看前面所举的逃犯的例子.警察在抓捕逃犯时,可以再多个地方设置检查站,逐一对车辆和行人进行排查,同样地,应用程序也可以在多个地方安装钩子函数,对我们感兴趣的多个消息逐一进行排查,这样多个钩子过程就形成了钩子链,要注意的是,最后安装的钩子过程总是排列在该链的前面

消息钩子分类

进程内钩子勾取本进程消息全局钩子 勾取所有消息

相关函数

显示相关函数

[设置消息钩子][消息钩子回调函数][移除消息钩子]

设置消息钩子 SetWindowsHookEx

函数原型

HHOOK SetWindowsHookEx(int idHook, // hook typeHOOKPROC lpfn, // hook procedureHINSTANCE hMod, // handle to application instanceDWORD dwThreadId // thread identifier);

参数说明

idHook

指定要安装的钩子过程的类型

WH_CALLWNDPROC 安装一个钩子过程,在操作系统将消息发送到目标窗口处理过程之前,对该消息进行监视WH_CALLWNDPROCRET安装一个钩子过程,它对被目标窗口处理过了的消息进行监视WH_CBT 安装一个钩子过程,接受对CBT应用程序有用的消息WH_DEBUG 安装一个钩子过程,以便对其他钩子过程调试WH_FOREGROUNDIDLE 安装一个钩子过程,该钩子过程当应用程序的前提线程即将进入空闲状态时被调用,它有助于在空闲时间内执行低优先级的任务WH_GETMESSAGE安装一个钩子过程对发送到消息队列的消息进行监视WH_JOURNALPLAYBACK安装一个钩子过程,对此前由WH_JORNALRECORD钩子过程记录的消息进行发送WH_JOURNALRECORD 安装一个钩子过程,对发送到系统消息队列的输入消息进行记录WH_KEYBOARD 安装一个钩子过程,对键盘按键消息进行监视WH_KEYBOARD_LL 安装一个钩子过程,只能在Windows NT中安装,用来对底层的键盘输入事件进行监视WH_MOUSE 安装一个钩子过程,对鼠标消息进行监视WH_MOUSE_LL 安装一个钩子过程,只能在Windows NT中安装,用来对底层的鼠标输入事件进行监视WH_MSGFILTER 安装一个钩子过程,以监视由对话框,消息框,菜单条,或滚动条中输入事件引发的消息WH_SHELL安装一个钩子过程,以接受外壳应用程序有用的通知WH_SYSMSGFILTER 安装一个钩子过程,以监视对话框,消息框,菜单条,或滚动条中输入事件引发的消息,该钩子过程对系统中所有应用程序的这里消息都进行监视

对应的回调函数也就是钩子函数的处理过程的形式在MSDN查阅

如果钩子函数返回非零值,表示已经对当前消息进行了处理,这样系统就不会在将这个消息传递给目标窗口过程,因此,如果钩子过程对于当前消息进行处理,则返回一个非零值,以避免系统再次将此消息传递给目标窗口过程;否则建议调用CallNextHookEx含返回该函数的返回值,以便其他安装了此消息类型钩子过程的应用程序捕获相应的通知

lpfn

指向相应的钩子过程,如果dwThreadId参数为0,或者指定了一个其他进程创建的线程标识符,那么参数lpfn必须指向一个位于动态链接库中的钩子过程.否则,参数lpfn可以指向当前进程相关的代码中定义的一个钩子过程

hMod

指定lpfn指向的钩子过程所在的DLL的句柄,如果参数dwThreadId指定的线程由当前进程穿件,并且相应的钩子过程定义与当前进程相关的代码中,那么必须将参数hMod设置为NULL(全局钩子,此参数必须指向DLL句柄)

dwThreadId

指定与钩子过程相关的线程标识,如果值为0,那么按照的钩子过程将与桌面上运行的所有线程都有关(安装的钩子过程可以与某个特定线程相关,也可以和所有线程相关,取决于这个参数的取值)

返回值

如果成功返回的值是钩子过程的句柄,如果函数失败返回的是NULL

钩子回调函数原型 CallNextHookEx

函数原型

LRESULT CallNextHookEx(HHOOK hhk, // handle to current hookint nCode, // hook code passed to hook procedureWPARAM wParam, // value passed to hook procedureLPARAM lParam // value passed to hook procedure);

参数说明

hhk:指定当前钩子过程句柄nCode,wParam,lParam:后三个参数是钩子过程回调函数的三个参数

返回值

这个值是在钩子链中的下个钩子函数的返回值

取消消息钩子函数 UnhookWindowsHookEx

函数原型

BOOL UnhookWindowsHookEx(HHOOK hhk // handle to hook procedure);

参数说明

hhk:要被移除的消息钩子

编写消息钩子

流程图:

进程钩子 全局钩子

代码样例:

进程钩子

程序源码:

View Code

#include<windows.h>#include<string.h>HHOOK g_hKeyboard=NULL;HHOOK g_hMouse=NULL;LRESULT CALLBACK MouseProc(int nCode,// hook codeWPARAM wParam, // message identifierLPARAM lParam // mouse coordinates){return 1;}LRESULT CALLBACK KeyboardProc(int code, // hook codeWPARAM wParam, // virtual-key codeLPARAM 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 windowUINT uMsg,// message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter);int WINAPI WinMain( HINSTANCE hInstance, // handle to current instanceHINSTANCE hPrevInstance, // handle to previous instanceLPSTR lpCmdLine,// pointer to command lineint 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 windowUINT uMsg,// message identifierWPARAM wParam, // first message parameterLPARAM 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);}

运行结果:

全局钩子

动态链接库源码:

View Code

// .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 codeWPARAM wParam, // message identifierLPARAM lParam // mouse coordinates){return 1;}LRESULT CALLBACK KeyboardProc(int code, // hook codeWPARAM wParam, // virtual-key codeLPARAM 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);}

程序源码:

View Code

#include<windows.h>//加载动态连接库头文件#include"../dllHook/dllHook.h"//加载动态连接库的引入库(LIB)#pragma comment(lib, "../debug/dllHook.lib")LRESULT CALLBACK textprom(HWND hwnd,// handle to windowUINT uMsg,// message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter);int WINAPI WinMain( HINSTANCE hInstance, // handle to current instanceHINSTANCE hPrevInstance, // handle to previous instanceLPSTR lpCmdLine,// pointer to command lineint 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 windowUINT uMsg,// message identifierWPARAM wParam, // first message parameterLPARAM 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 );

参数说明:

hWnd: 指定定时器的关联窗口nIDEvent: 指定了不为零的定时器标识符.nElapse: 指定了定时值;以毫秒为单位.lpfnTimer: 指定了应用程序提供的TimerProc回调函数的地址,该函数被用于处理WM_TIMER消息.如果这个参数为NULL,则WM_TIMER消息被放入应用程序的消息队列并由CWnd对象来处理.

返回值

如果函数成功,则返回新定时器的标识符.应用程序可以将这个值传递给KillTimer成员函数以销毁定时器.如果成功,则返回非零值;否则返回0

说明:

所属类 CWnd相对事件 WM_TIMER这个函数设置一个系统定时器.指定了一个定时值,每当发生超时,则系统就向设置定时器的应用程序的消息队列发送一个WM_TIMER消息,或者将消息传递给应用程序定义的TimerProc回调函数.lpfnTimer回调函数不需要被命名为TimerProc,但是它必须按照如下方式定义:

void CALLBACK EXPORT TimerProc(HWND hWnd, // 调用SetTimer的窗口的句柄UINT nMsg, // WM_TIMER UINT nIDEvent // 定时器标识DWORD dwTime // 系统时间 );

定时器是有限的全局资源;因此对于应用程序来说,检查SetTimer返回的值以确定定时器是否可用是很重要的

消除已存在定时器

函数原型

BOOL KillTimer( int nIDEvent );

参数说明

nIDEvent: 传递给SetTimer的定时器事件值

返回值

指定了函数的结果.如果事件已经被销毁,则返回值为非零值.如果KillTimer成员函数不能找到指定的定时器事件,则返回0

说明

所属类 CWnd销毁以前调用SetTimer创建的用nIDEvent标识的定时器事件.任何与此定时器有关的未处理的WM_TIMER消息都从消息队列中清除

编写定时器

流程图:

代码样例:

程序源码:

View Code

#include"windows.h"#include<cstdlib>#include<iostream>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<<"定时器消息回调函数调用成功"<<endl;//关闭定时器if(KillTimer(NULL,dwEvent))PostQuitMessage(0);}

运行结果:

如果觉得《消息钩子与定时器(VC_Win32)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。