线程钩子

钩子的本质是一段用以处理系统消息程序,通过系统调用把它挂入系统。钩子种类很 多,每种钩 子可以截获并处理相应的消息当特定发出在到达目窗口之前,每种钩子可以截获并处理相应的消息,每当特定消息发出,在到达目窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。此时钩函数可以对截获的消息进加工处理,甚至可以强制结束消息的传递。这有点类似与 MFC中的 PreTranslateMessage函数数,所不同的是该函数只能用于拦截本进程中消息,而对系统则无为力。

钩子分为全局的钩子和局部的钩子。局部的钩子在程序中写钩子的过程函数就可以了。全局的钩子,则需要在dll中写出过程函数,然后在程序中进行连接使用。

 1.用SetWindowsHookEx安装钩子

HHOOK WINAPI SetWindowsHookEx(
                                                                __in int idHook,            \\钩子类型,例如WH_MOUS、 WH_KEYBOARDWH_KEYBOARD
                                                                __in HOOKPROC lpfn, \\回调函数地址,当钩子钩到任何消息后便调用这个函数;
                                                                __in HINSTANCE hMod, \\实例句柄,钩子所在模块的句柄
                                                                __in DWORD dwThreadId); \\线程ID,指定想让钩子去哪个线程,为 0则拦截整个系统消息此为全局钩子。如果指定确定的线程,即为专用钩子


2.定义钩子函数

LRESULT WINAPI MyHookProc(
                                                      int     nCode ,     // 指定是否需要处理该消息
                                                      WPARAM  wParam,     // 包含该消息的附加消息
                                                      LPARAM  lParam      // 包含该消息的附加消息
                                                    )

钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。

得到控制权的钩子函数在处理完消息后,可以调用另外一个API函数 CallNextHookEx来继续传递该消息,也可以通过直接返回  TRUE来丢弃该消息,阻止该消息继续传递。


3.调用CallNextHookEx把钩子信息传递给钩子链的下一个钩子函数。原型如下:
LRESULT CallNextHookEx(

                                            HHOOK  hhk,       //传递给的钩子句柄

                                            int  nCode,           //下一个钩子程序使用此代码,以确定如何处理钩的信息

                                            WPARAM  wParam,   //要传递的参数

                                            LPARAM  lParam       //要传递的参数

                                            )
当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。


4.用UnhookWindowsHookEx卸载钩子

UnhookWindowsHookEx
                                         (
                                           HHOOK hhk;       //要卸载的钩子
                                         );
函数成功返回TRUE,否则返回FALSE。

例子:

实现一个线程级的鼠标钩子。钩子跟踪当前窗口鼠标移动的位置变化信息。并输出到窗口。

(1)在VC中利用MFC APPWizard生成一个不使用文档/视结构的单文档应用mousehook。打开childview.cpp文件,加入全局变量:
HHOOK hHook;//鼠标钩子句柄

CPoint point;//鼠标位置信息

CChildView*pView;//鼠标钩子函数用到的输出窗口指针
在CChildView::OnPaint()添加如下代码:

CPaintDCdc(this);

charstr[256];
sprintf(str,“x=%d,y=%d",point.x,point.y);//构造字符串
dc.TextOut(0,0,str);//显示字符串
(2)childview.cpp文件中定义全局的鼠标钩子函数。

LRESULT CALLBACK MouseProc( intnCode,WPARAMwParam,LPARAMlParam)

{

//是鼠标移动消息
if(wParam==WM_MOUSEMOVE||wParam==WM_NCMOUSEMOVE)

{
point=((MOUSEHOOKSTRUCT*)lParam)->pt;//取鼠标信息
pView->Invalidate();//窗口重画
}

//传递钩子信息
return CallNextHookEx(hHook,nCode,wParam,lParam);

}
(3)CChildView类的构造函数中安装钩子。

CChildView::CChildView(){
pView=this;//获得输出窗口指针
hHook=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());

}
(4)CChildView类的析构函数中卸载钩子。

CChildView::~CChildView()

{
if(hHook)
UnhookWindowsHookEx(hHook);

}

版权声明:

posted on 2015-03-18 16:09  moffis  阅读(573)  评论(0编辑  收藏  举报

导航