• HOOK技术键盘鼠标钩子实例


    1.首先创建一个DLL项目,用以生成自定义的DLL文件,在DLL文件中对外有两个接口,安装钩子的函数SetHook和卸载钩子函数UnSetHook函数,对于

       这些函数由于需要导出,所以在工程项目的.h文件中需要声明这些函数需要导出。

    //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);

        这里只有安装钩子函数有参数,该参数是线程ID号,这里需要注意,如果在调用DLL时发现找不到函数地址,那就需要加extern “C” 说明了,当时我就是没有加郁闷了很久才找到这个问题。我思考了一下,应该是DLL中我采用的是C编程语言,而我的调用该DLL的应用程序默认是C++,但是由于C和C++的OBJ的函数名格式不同,所以才会出现找不到函数地址的问题。是对于DLL的头文件按照这个格式就可以导出函数了。

    //MouseKeyboardHook.cpp文件
    
    #include "stdafx.h"
    #include "MouseKeyboardHook.h"
    #include "stdio.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的内存地址,可以重复使用,当做模版
    
    
    MOUSEKEYBOARDHOOK_API int fnMouseKeyboardHook(void)//这个是项目自己生成的没多大用
    {
    	return 42;
    }
    
    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 )//我这里屏蔽所有鼠标消息
    {
    	return ::CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
    }
    // 这是已导出类的构造函数。
    // 有关类定义的信息,请参阅 MouseKeyboardHook.h
    
    CMouseKeyboardHook::CMouseKeyboardHook()
    {
    	return;
    }
    
    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)//卸载钩子函数,不过这个例子有问题,卸载不了,不知道为什么
    {
    
    	BOOL b1 = ::UnhookWindowsHookEx( g_hMouseHook );
    	BOOL b2 = ::UnhookWindowsHookEx( g_hKeyboardHook );
    	if( b1==FALSE || b2==FALSE )
    		MessageBox( NULL, "卸载钩子失败!", "", 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.创建加载该DLL的应用程序

        因为需要监视整个计算机,所以SetHook函数传参是0,代表监视整个计算机。

       在本实例中,对于DLL的加载方式是动态加载的。

       具体流程是:加载DLL文件-->获取导出函数地址-->调用钩子安装函数-->卸载钩子

       程序主要源码如下:

    BOOL bInstall = FALSE;//用来指示是否已经安装了钩子
    // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
    //需要声明导出函数指针
    typedef int ( *pSetHook)(DWORD * );//声明函数类型
    typedef int ( *pUnsetHook)(void);
    
    void CKeyMouseHookAppDlg::OnBnClickedButton1()//程序是按下按钮动态加载DLL的
    {
    	
    	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失败!" );
    }
    


  • 相关阅读:
    对象之间是有联系的
    java发展历程、常用dos命令与jDK工具使用
    java环境变量、集成开发环境与使用两个类
    C++中,将单精度浮点数转换成2进制数
    Java代码规范、基本类型和实例演练
    java方法的理解、调用栈与异常处理
    java面向对象、构造方法 之内部类
    java读代码步骤
    Java中break、continue、return语句的使用区别
    数学图像处理--空间滤波
  • 原文地址:https://www.cnblogs.com/arbboter/p/4225265.html
Copyright © 2020-2023  润新知