什么钩子,到底派什么用的?什么情况下用 用qq吗?默认的快捷件是ctrl+Alt+z,来消息的时候可以弹出窗口,不管焦点在什么地方,这就要用钩子实现 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 下面的文章可能对你有所帮助Win32全局钩子在VC5中的实现 Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子的种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息,外壳钩子可以截取、启动和关闭应用程序的消息等。本文在VC5编程环境下实现了一个简单的鼠标钩子程序,并对Win32全局钩子的运行机制、Win32 DLL的特点、VC5环境下的MFC DLL以及共享数据等相关知识进行了简单的阐述。 一.Win32全局钩子的运行机制 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。对每种类型的钩子由系统来维护一个钩子链,最近安装的钩子放在链的开始,而最先安装的钩子放在最后,也就是后加入的先获得控制权。要实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);,其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。 二.Win32 DLL的特点 Win32 DLL与 Win16 DLL有很大的区别,这主要是由操作系统的设计思想决定的。一方面,在Win16 DLL中程序入口点函数和出口点函数(LibMain和WEP)是分别实现的;而在Win32 DLL中却由同一函数DLLMain来实现。无论何时,当一个进程或线程载入和卸载DLL时,都要调用该函数,它的原型是BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);,其中,第一个参数表示DLL的实例句柄;第三个参数系统保留;这里主要介绍一下第二个参数,它有四个可能的值:DLL_PROCESS_ATTACH(进程载入),DLL_THREAD_ATTACH(线程载入),DLL_THREAD_DETACH(线程卸载),DLL_PROCESS_DETACH(进程卸载),在DLLMain函数中可以对传递进来的这个参数的值进行判别,并根据不同的参数值对DLL进行必要的初始化或清理工作。举个例子来说,当有一个进程载入一个DLL时,系统分派给DLL的第二个参数为DLL_PROCESS_ATTACH,这时,你可以根据这个参数初始化特定的数据。另一方面,在Win16环境下,所有应用程序都在同一地址空间;而在Win32环境下,所有应用程序都有自己的私有空间,每个进程的空间都是相互独立的,这减少了应用程序间的相互影响,但同时也增加了编程的难度。大家知道,在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,当进程在载入DLL时,系统自动把DLL地址映射到该进程的私有空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间,也就是说每个进程所拥有的相同的DLL的全局数据其值却并不一定是相同的。因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。亦即把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。 三.VC5中MFC DLL的分类及特点 在VC5中有三种形式的MFC DLL(在该DLL中可以使用和继承已有的MFC类)可供选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)和Regular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MFC DLL(扩展MFC DLL)。第一种DLL的特点是,在编译时把使用的MFC代码加入到DLL中,因此,在使用该程序时不需要其他MFC动态链接类库的存在,但占用磁盘空间比较大;第二种DLL的特点是,在运行时,动态链接到MFC类库,因此减少了空间的占用,但是在运行时却依赖于MFC动态链接类库;这两种DLL既可以被MFC程序使用也可以被Win32程序使用。第三种DLL的特点类似于第二种,做为MFC类库的扩展,只能被MFC程序使用。 四.在VC5中全局共享数据的实现 在主文件中,用#pragma data_seg建立一个新的数据段并定义共享数据,其具体格式为: #pragma data_seg ("shareddata") HWND sharedwnd=NULL;//共享数据 #pragma data_seg() 仅定义一个数据段还不能达到共享数据的目的,还要告诉编译器该段的属性,有两种方法可以实现该目的(其效果是相同的),一种方法是在.DEF文件中加入如下语句: SETCTIONS shareddata READ WRITE SHARED 另一种方法是在项目设置链接选项中加入如下语句: /SECTION:shareddata,rws 五.具体实现步骤 由于全局钩子函数必须包含在动态链接库中,所以本例由两个程序体来实现。 1.建立钩子Mousehook.DLL (1)选择MFC AppWizard(DLL)创建项目Mousehook; (2)选择MFC Extension DLL(共享MFC拷贝)类型; (3)由于VC5没有现成的钩子类,所以要在项目目录中创建Mousehook.h文件,在其中建立钩子类: class AFX_EXT_CLASS Cmousehook:public CObject public: Cmousehook(); file://钩子类的构造函数 ~Cmousehook(); file://钩子类的析构函数 BOOL starthook(HWND hWnd); file://安装钩子函数 BOOL stophook(); 卸载钩子函数 }; (4)在Mousehook.app文件的顶部加入#include"Mousehook.h"语句; (5)加入全局共享数据变量: #pragma data_seg("mydata") HWND glhPrevTarWnd=NULL; file://上次鼠标所指的窗口句柄 HWND glhDisplayWnd=NULL; file://显示目标窗口标题编辑框的句柄 HHOOK glhHook=NULL; file://安装的鼠标勾子句柄 HINSTANCE glhInstance=NULL; file://DLL实例句柄 #pragma data_seg() (6)在DEF文件中定义段属性: SECTIONS mydata READ WRITE SHARED (7)在主文件Mousehook.cpp的DllMain函数中加入保存DLL实例句柄的语句: DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) file://如果使用lpReserved参数则删除下面这行 UNREFERENCED_PARAMETER(lpReserved); if (dwReason == DLL_PROCESS_ATTACH) TRACE0("MOUSEHOOK.DLL Initializing!\n"); file://扩展DLL仅初始化一次 if (!AfxInitExtensionModule(MousehookDLL, hInstance)) return 0; new CDynLinkLibrary(MousehookDLL); file://把DLL加入动态MFC类库中 glhInstance=hInstance; file://插入保存DLL实例句柄 } else if (dwReason == DLL_PROCESS_DETACH) TRACE0("MOUSEHOOK.DLL Terminating!\n"); file://终止这个链接库前调用它 AfxTermExtensionModule(MousehookDLL); } return 1; } (8)类Cmousehook的成员函数的具体实现: Cmousehook::Cmousehook() file://类构造函数 } Cmousehook::~Cmousehook() file://类析构函数 stophook(); } BOOL Cmousehook::starthook(HWND hWnd) file://安装钩子并设定接收显示窗口句柄 BOOL bResult=FALSE; glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0); if(glhHook!=NULL) bResult=TRUE; glhDisplayWnd=hWnd; file://设置显示目标窗口标题编辑框的句柄 return bResult; } BOOL Cmousehook::stophook() file://卸载钩子 BOOL bResult=FALSE; if(glhHook) bResult= UnhookWindowsHookEx(glhHook); if(bResult) glhPrevTarWnd=NULL; glhDisplayWnd=NULL;//清变量 glhHook=NULL; } } return bResult; } (9)钩子函数的实现: LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam) LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam; if (nCode>=0) HWND glhTargetWnd=pMouseHook->hwnd; file://取目标窗口句柄 HWND ParentWnd=glhTargetWnd; while (ParentWnd !=NULL) glhTargetWnd=ParentWnd; ParentWnd=GetParent(glhTargetWnd); file://取应用程序主窗口句柄 } if(glhTargetWnd!=glhPrevTarWnd) char szCaption[100]; GetWindowText(glhTargetWnd,szCaption,100); file://取目标窗口标题 if(IsWindow(glhDisplayWnd)) SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption); glhPrevTarWnd=glhTargetWnd; file://保存目标窗口 } } return CallNextHookEx(glhHook,nCode,wparam,lparam); file://继续传递消息 } (10)编译项目生成mousehook.dll。 2.创建钩子可执行程序 (1)用MFC的AppWizard(EXE)创建项目Mouse; (2)选择“基于对话应用”并按下“完成”键; (3)编辑对话框,删除其中原有的两个按钮,加入静态文本框和编辑框,用鼠标右键点击静态文本框,在弹出的菜单中选择“属性”,设置其标题为“鼠标所在的窗口标题”; (4)在Mouse.h中加入对Mousehook.h的包含语句#Include"..\Mousehook\Mousehook.h"; (5)在CMouseDlg.h的CMouseDlg类定义中添加私有数据成员: CMouseHook m_hook;//加入钩子类作为数据成员 (6)修改CmouseDlg::OnInitDialog()函数: BOOL CMouseDlg::OnInitDialog() CDialog::OnInitDialog(); ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } SetIcon(m_hIcon, TRUE);//Set big icon SetIcon(m_hIcon, FALSE);//Set small icon file://TODO: Add extra initialization here CWnd * pwnd=GetDlgItem(IDC_EDIT1); file://取得编辑框的类指针 m_hook.starthook(pwnd->GetSafeHwnd()); file://取得编辑框的窗口句柄并安装钩子 return TRUE; file://return TRUE unless you set the focus to a control } (7)链接DLL库,即把..\Mousehook\debug\Mousehook.lib加入到项目设置链接标签中; (8)编译项目生成可执行文件; (9)把Mousehook.DLL拷贝到..\mouse\debug目录中; (10)先运行几个可执行程序,然后运行Mouse.exe程序,把鼠标在不同窗口中移动,在Mouse.exe程序窗口中的编辑框内将显示出鼠标所在的应用程序主窗口的标题。pcc 我用vc6建了一个单文档视图的程序,怎样去掉程序界面的蓝色边框 组合框的问题 函数waveOutGetDevCaps内存泄露怎么解决? 关于listview&listctrl的问题 在其他类里调用View类的变量的问题!!! 200分求一篇文章!在线等! demetry朋友进来取分 各位能否谈谈你们所在公司的源代码管理与备份方案? 最近想通过《ISO9000族及质量体系认证》软件学习一下ISO9000标准!! 关于 vector 的使用?? 如何编程实现word转化成TXT(有酬金)????? 如何使编辑框中的文字处于被选定状态?
息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获
并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子的
种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息
,外壳钩子可以截取、启动和关闭应用程序的消息等。本文在VC5编程环境下实现
了一个简单的鼠标钩子程序,并对Win32全局钩子的运行机制、Win32 DLL的特点
、VC5环境下的MFC DLL以及共享数据等相关知识进行了简单的阐述。 一.Win32全局钩子的运行机制 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当
特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子
函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作
处理而继续传递该消息,还可以强制结束消息的传递。对每种类型的钩子由系统
来维护一个钩子链,最近安装的钩子放在链的开始,而最先安装的钩子放在最后
,也就是后加入的先获得控制权。要实现Win32的系统钩子,必须调用SDK中的AP
I函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是HHOOK SetWind
owsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);,
其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是
包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,
即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包
含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控
制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须
调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直
接返回TRUE来丢弃该消息,并阻止该消息的传递。 二.Win32 DLL的特点 Win32 DLL与 Win16 DLL有很大的区别,这主要是由操作系统的设计思想决定
的。一方面,在Win16 DLL中程序入口点函数和出口点函数(LibMain和WEP)是分
别实现的;而在Win32 DLL中却由同一函数DLLMain来实现。无论何时,当一个进
程或线程载入和卸载DLL时,都要调用该函数,它的原型是BOOL WINAPI DllMain
(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);,其中,第一个
参数表示DLL的实例句柄;第三个参数系统保留;这里主要介绍一下第二个参数,
它有四个可能的值:DLL_PROCESS_ATTACH(进程载入),DLL_THREAD_ATTACH(线
程载入),DLL_THREAD_DETACH(线程卸载),DLL_PROCESS_DETACH(进程卸载)
,在DLLMain函数中可以对传递进来的这个参数的值进行判别,并根据不同的参数
值对DLL进行必要的初始化或清理工作。举个例子来说,当有一个进程载入一个D
LL时,系统分派给DLL的第二个参数为DLL_PROCESS_ATTACH,这时,你可以根据这
个参数初始化特定的数据。另一方面,在Win16环境下,所有应用程序都在同一地
址空间;而在Win32环境下,所有应用程序都有自己的私有空间,每个进程的空间
都是相互独立的,这减少了应用程序间的相互影响,但同时也增加了编程的难度
。大家知道,在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同
的;而在Win32环境中,情况却发生了变化,当进程在载入DLL时,系统自动把DL
L地址映射到该进程的私有空间,而且也复制该DLL的全局数据的一份拷贝到该进
程空间,也就是说每个进程所拥有的相同的DLL的全局数据其值却并不一定是相同
的。因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。
亦即把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的
属性设置为共享。 三.VC5中MFC DLL的分类及特点 在VC5中有三种形式的MFC DLL(在该DLL中可以使用和继承已有的MFC类)可供
选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)和R
egular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MF
C DLL(扩展MFC DLL)。第一种DLL的特点是,在编译时把使用的MFC代码加入到
DLL中,因此,在使用该程序时不需要其他MFC动态链接类库的存在,但占用磁盘
空间比较大;第二种DLL的特点是,在运行时,动态链接到MFC类库,因此减少了
空间的占用,但是在运行时却依赖于MFC动态链接类库;这两种DLL既可以被MFC程
序使用也可以被Win32程序使用。第三种DLL的特点类似于第二种,做为MFC类库的
扩展,只能被MFC程序使用。 四.在VC5中全局共享数据的实现 在主文件中,用#pragma data_seg建立一个新的数据段并定义共享数据,其
具体格式为: #pragma data_seg ("shareddata") HWND sharedwnd=NULL;//共享数据 #pragma data_seg() 仅定义一个数据段还不能达到共享数据的目的,还要告诉编译器该段的属性
,有两种方法可以实现该目的(其效果是相同的),一种方法是在.DEF文件中加
入如下语句: SETCTIONS shareddata READ WRITE SHARED 另一种方法是在项目设置链接选项中加入如下语句: /SECTION:shareddata,rws 五.具体实现步骤 由于全局钩子函数必须包含在动态链接库中,所以本例由两个程序体来实现
。 1.建立钩子Mousehook.DLL (1)选择MFC AppWizard(DLL)创建项目Mousehook; (2)选择MFC Extension DLL(共享MFC拷贝)类型; (3)由于VC5没有现成的钩子类,所以要在项目目录中创建Mousehook.h文件,
在其中建立钩子类: class AFX_EXT_CLASS Cmousehook:public CObject public: Cmousehook(); file://钩子类的构造函数 ~Cmousehook(); file://钩子类的析构函数 BOOL starthook(HWND hWnd); file://安装钩子函数 BOOL stophook(); 卸载钩子函数 }; (4)在Mousehook.app文件的顶部加入#include"Mousehook.h"语句; (5)加入全局共享数据变量: #pragma data_seg("mydata") HWND glhPrevTarWnd=NULL; file://上次鼠标所指的窗口句柄 HWND glhDisplayWnd=NULL; file://显示目标窗口标题编辑框的句柄 HHOOK glhHook=NULL; file://安装的鼠标勾子句柄 HINSTANCE glhInstance=NULL; file://DLL实例句柄 #pragma data_seg() (6)在DEF文件中定义段属性: SECTIONS mydata READ WRITE SHARED (7)在主文件Mousehook.cpp的DllMain函数中加入保存DLL实例句柄的语句: DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) file://如果使用lpReserved参数则删除下面这行 UNREFERENCED_PARAMETER(lpReserved); if (dwReason == DLL_PROCESS_ATTACH) TRACE0("MOUSEHOOK.DLL Initializing!\n"); file://扩展DLL仅初始化一次 if (!AfxInitExtensionModule(MousehookDLL, hInstance)) return 0; new CDynLinkLibrary(MousehookDLL); file://把DLL加入动态MFC类库中 glhInstance=hInstance; file://插入保存DLL实例句柄 } else if (dwReason == DLL_PROCESS_DETACH) TRACE0("MOUSEHOOK.DLL Terminating!\n"); file://终止这个链接库前调用它 AfxTermExtensionModule(MousehookDLL); } return 1; } (8)类Cmousehook的成员函数的具体实现: Cmousehook::Cmousehook() file://类构造函数 } Cmousehook::~Cmousehook() file://类析构函数 stophook(); } BOOL Cmousehook::starthook(HWND hWnd) file://安装钩子并设定接收显示窗口句柄 BOOL bResult=FALSE; glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0); if(glhHook!=NULL) bResult=TRUE; glhDisplayWnd=hWnd; file://设置显示目标窗口标题编辑框的句柄 return bResult; } BOOL Cmousehook::stophook() file://卸载钩子 BOOL bResult=FALSE; if(glhHook) bResult= UnhookWindowsHookEx(glhHook); if(bResult) glhPrevTarWnd=NULL; glhDisplayWnd=NULL;//清变量 glhHook=NULL; } } return bResult; } (9)钩子函数的实现: LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam) LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam; if (nCode>=0) HWND glhTargetWnd=pMouseHook->hwnd; file://取目标窗口句柄 HWND ParentWnd=glhTargetWnd; while (ParentWnd !=NULL) glhTargetWnd=ParentWnd; ParentWnd=GetParent(glhTargetWnd); file://取应用程序主窗口句柄 } if(glhTargetWnd!=glhPrevTarWnd) char szCaption[100]; GetWindowText(glhTargetWnd,szCaption,100); file://取目标窗口标题 if(IsWindow(glhDisplayWnd)) SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption); glhPrevTarWnd=glhTargetWnd; file://保存目标窗口 } } return CallNextHookEx(glhHook,nCode,wparam,lparam); file://继续传递消息 } (10)编译项目生成mousehook.dll。 2.创建钩子可执行程序 (1)用MFC的AppWizard(EXE)创建项目Mouse; (2)选择“基于对话应用”并按下“完成”键; (3)编辑对话框,删除其中原有的两个按钮,加入静态文本框和编辑框,用鼠
标右键点击静态文本框,在弹出的菜单中选择“属性”,设置其标题为“鼠标所
在的窗口标题”; (4)在Mouse.h中加入对Mousehook.h的包含语句#Include"..\Mousehook\Mou
sehook.h"; (5)在CMouseDlg.h的CMouseDlg类定义中添加私有数据成员: CMouseHook m_hook;//加入钩子类作为数据成员 (6)修改CmouseDlg::OnInitDialog()函数: BOOL CMouseDlg::OnInitDialog() CDialog::OnInitDialog(); ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } SetIcon(m_hIcon, TRUE);//Set big icon SetIcon(m_hIcon, FALSE);//Set small icon file://TODO: Add extra initialization here CWnd * pwnd=GetDlgItem(IDC_EDIT1); file://取得编辑框的类指针 m_hook.starthook(pwnd->GetSafeHwnd()); file://取得编辑框的窗口句柄并安装钩子 return TRUE; file://return TRUE unless you set the focus to a control } (7)链接DLL库,即把..\Mousehook\debug\Mousehook.lib加入到项目设置链
接标签中; (8)编译项目生成可执行文件; (9)把Mousehook.DLL拷贝到..\mouse\debug目录中; (10)先运行几个可执行程序,然后运行Mouse.exe程序,把鼠标在不同窗口中
移动,在Mouse.exe程序窗口中的编辑框内将显示出鼠标所在的应用程序主窗口的
标题。pcc