关于钩子函数的概念,百科有更详细的注释。
我个人的理解是,任何消息,系统都会有对应的机制或者说函数来处理,钩子函数的意义在于,可以在系统处理之前,先拿到这个具体的消息,然后做出自己的处理,接下来可以选择将消息传给其它钩子函数,或者系统,或者截断消息的传递。
不得不说,由于平台和环境的差异,很多例子根本跑不通,我这个基于VS/C++,基本的鼠标和键盘钩子,就当给自己做个记录吧
1.封装钩子函数的dll
头文件名 MouseKeyboardHook.h
#ifdef MOUSEKEYBOARDHOOK_EXPORTS
#define MOUSEKEYBOARDHOOK_API __declspec(dllexport)
#else
#define MOUSEKEYBOARDHOOK_API __declspec(dllimport)
#endif
extern "C" MOUSEKEYBOARDHOOK_API int SetHook( DWORD dwThreadId );
extern "C" MOUSEKEYBOARDHOOK_API int UnSetHook(void);
执行函数文件名 MouseKeyboardHook.cpp
// MouseKeyboardHook.cpp : 定义 DLL 应用程序的导出函数。
//MouseKeyboardHook.cpp文件
#include "stdafx.h"
#include "MouseKeyboardHook.h"
#include "stdio.h"
#include <atlstr.h>
//共享内存变量
#pragma data_seg("MouseKeyboardHook")
HHOOK g_hMouseHook = NULL;
HHOOK g_hKeyboardHook = NULL;
#pragma data_seg()
// 这是导出变量的一个示例
MOUSEKEYBOARDHOOK_API int nMouseKeyboardHook=0;
// 这是导出函数的一个示例。
int UnSetHook(void);
int fnMouseKeyboardHook(void);
int SetHook( DWORD dwThreadId );
//注意:钩子函数的格式必须是 LRESULT CALLBACK 函数名( int 钩子类型, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK MouseHookProc( int nCode, WPARAM wParam, LPARAM lParam );//处理鼠标的钩子函数
LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam );//处理键盘的钩子函数
HMODULE WINAPI ModuleFromAddress(PVOID pv) ;//这个是获取DLL的内存地址,可以重复使用,当做模版
LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam )
{
if( wParam=='Q' && lParam>0 )//当只有按下Q键的时候才会退出钩子函数。其他其他的话都屏蔽
{
MessageBox( NULL, "卸载钩子中...", "卸载钩子", MB_OK );
UnSetHook();
}
else return TRUE;
return ::CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);//传递消息给其它钩子
}
LRESULT CALLBACK MouseHookProc( int nCode, WPARAM wParam, LPARAM lParam )//我这里屏蔽所有鼠标消息
{
if ( g_hMouseHook != NULL && nCode == HC_ACTION) {
MessageBox( NULL, "安装钩子成功!", "", MB_OK );
//UnSetHook();
return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
//return TRUE;//这里可以写自己的逻辑(回调函数),告诉windows,不用上班了
}
return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
}
MOUSEKEYBOARDHOOK_API int SetHook( DWORD dwThreadId )//安装钩子函数
{
g_hMouseHook = ::SetWindowsHookEx( WH_MOUSE, MouseHookProc, ModuleFromAddress(MouseHookProc), 0 );
g_hKeyboardHook = ::SetWindowsHookEx( WH_KEYBOARD, KeyboardHookProc, ModuleFromAddress(KeyboardHookProc), 0 );
return 0;
}
MOUSEKEYBOARDHOOK_API int UnSetHook(void)//卸载钩子函数
{
MessageBox( NULL, "卸载钩子kaishi!", "", MB_OK );
if (g_hMouseHook != NULL) {
MessageBox( NULL, "卸载钩子lushang", "", MB_OK );
::UnhookWindowsHookEx(g_hMouseHook);
MessageBox( NULL, "卸载钩子成功!", "", MB_OK );
g_hMouseHook = NULL;
}
// if (g_hKeyboardHook != NULL) {
// ::UnhookWindowsHookEx(g_hKeyboardHook);
// MessageBox( NULL, "卸载钩子成功!", "", MB_OK );
// g_hKeyboardHook = NULL;
//}
return TRUE;
//BOOL b1 = ::UnhookWindowsHookEx( g_hMouseHook );
//BOOL b2 = ::UnhookWindowsHookEx( g_hKeyboardHook );
//if( b1==FALSE || b2==FALSE )
// MessageBox( NULL, "卸载钩子失败!", "", MB_OK );
//int a = GetLastError();
//CString str ;
//str.Format("%d", a);
//MessageBox( NULL, "卸载", str, MB_OK );
/*return 0;*/
}
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}
2.建一个简单工程MouseHookTest用来校验钩子函数
将上述生成的MouseKeyboardHook.dll文件加载到自己的工程里
MouseHookTest.cpp文件
//================================================
//===========头文件自己加==========================
//================================================
BOOL bInstall = FALSE;//用来指示是否已经安装了钩子
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
//需要声明导出函数指针
typedef int ( *pSetHook)(DWORD * );//声明函数类型
typedef int ( *pUnsetHook)(void);
//===========================================
//============主函数==========================
//===========================================
void CMouseHookTestDlg::OnBnClickedButton1()//自定义调用函数
{
// TODO: 在此添加控件通知处理程序代码
HMODULE hModule = ::LoadLibrary( "MouseKeyboardHook.dll" );//加载DLL库
if( hModule!=NULL )
{
if( bInstall==FALSE )
{
pSetHook mpSetHook;
mpSetHook = (pSetHook)::GetProcAddress( hModule, "SetHook" );//获取导出函数地址
if( mpSetHook!=NULL )
{
mpSetHook( 0 );//安装全局钩子
bInstall = TRUE;
GetDlgItem( IDC_BUTTON1 )->SetWindowText( "卸载DLL" );
}
else MessageBox( "获取函数地址失败!" );
}
else
{
pUnsetHook mpUnsetHook;
mpUnsetHook = (pUnsetHook)::GetProcAddress( hModule, "UnSetHook" );
if( mpUnsetHook!=NULL )
{
mpUnsetHook();//卸载钩子
bInstall = FALSE;
GetDlgItem( IDC_BUTTON1 )->SetWindowText( "加载DLL" );
}
else MessageBox( "获取函数地址失败!" );
::FreeLibrary( hModule );//释放加载的DLL库
}
}
else MessageBox( "加载DLL失败!" );
}