⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mousehook.cpp

📁 一个鼠标钩子程序 Mousehook Mousehook
💻 CPP
字号:
// Mousehook.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include <afxdllx.h>
#include "Mousehook.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#pragma data_seg("mydata")
     HWND glhPrevTarWnd=NULL; //上次鼠标所指的窗口句柄 
     HWND glhDisplayWnd=NULL; //显示目标窗口标题编辑框的句柄
	 HHOOK glhHook=NULL; //安装的鼠标勾子句柄 
	 HINSTANCE glhInstance=NULL; //DLL实例句柄 
#pragma data_seg()

HWND XYZWindowFromPoint(HWND hwndParent,      // handle to parent window
                        POINT point,          // structure with point coordinates
                        UINT uFlags  = CWP_SKIPINVISIBLE       // skip options
					   );
static AFX_EXTENSION_MODULE MousehookDLL = { NULL, NULL };

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	// Remove this if you use lpReserved
	UNREFERENCED_PARAMETER(lpReserved);

	if (dwReason == DLL_PROCESS_ATTACH)
	{
		TRACE0("MOUSEHOOK.DLL Initializing!\n");
		
		// Extension DLL one-time initialization
		if (!AfxInitExtensionModule(MousehookDLL, hInstance))
			return 0;

		// Insert this DLL into the resource chain
		// NOTE: If this Extension DLL is being implicitly linked to by
		//  an MFC Regular DLL (such as an ActiveX Control)
		//  instead of an MFC application, then you will want to
		//  remove this line from DllMain and put it in a separate
		//  function exported from this Extension DLL.  The Regular DLL
		//  that uses this Extension DLL should then explicitly call that
		//  function to initialize this Extension DLL.  Otherwise,
		//  the CDynLinkLibrary object will not be attached to the
		//  Regular DLL's resource chain, and serious problems will
		//  result.

		new CDynLinkLibrary(MousehookDLL);
		glhInstance=hInstance; //插入保存DLL实例句柄
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		TRACE0("MOUSEHOOK.DLL Terminating!\n");
		// Terminate the library before destructors are called
		AfxTermExtensionModule(MousehookDLL);
	}
	return 1;   // ok
}

//钩子函数的实现: 
LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)
{
	LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *)lparam;
	if (nCode>=0)
	{
		/*============================================================================
		如下代码是得到父窗口标题文本的做法
		HWND glhTargetWnd=pMouseHook->hwnd;     //取目标窗口句柄
		HWND ParentWnd=glhTargetWnd;
		while (ParentWnd !=NULL)
		{
			glhTargetWnd=ParentWnd;
			ParentWnd=GetParent(glhTargetWnd);   //取应用程序主窗口句柄
		}
		===========================================================================*/
		HWND glhTargetWnd=XYZWindowFromPoint(NULL,pMouseHook->pt);    //用上面的一段注释掉的代码替换此行是得到父窗口标题文本的做法
		if(glhTargetWnd!=glhPrevTarWnd)
		{
			char szCaption[256];
			GetWindowText(glhTargetWnd,szCaption,100);
			//取目标窗口标题
			if(IsWindow(glhDisplayWnd))
				SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption);
			glhPrevTarWnd=glhTargetWnd;
			//保存目标窗口
		}
	}
	return CallNextHookEx(glhHook,nCode,wparam,lparam);
	//继续传递消息
}

CMouseHook::CMouseHook()
{

}

CMouseHook::~CMouseHook()
{
}

//安装钩子并设定接收显示窗口句柄
BOOL CMouseHook::StartHook(HWND hWnd)
{
	BOOL bResult=FALSE;

	glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);
	/*=================================================================================
    HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )
  参数idHook表示钩子类型,它是和钩子函数类型一一对应的。
    比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。 

  Lpfn是钩子函数的地址。 

  HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;
    对于系统钩子,该参数为钩子函数所在的DLL句柄。 

  dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。 

  SetWindowsHookEx返回所安装的钩子句柄。
    值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。
	线程钩子一般在当前线程或者当前线程派生的线程内,
	而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。 
	==================================================================================*/
	if(glhHook!=NULL)
		bResult=TRUE;
	glhDisplayWnd=hWnd;
	//设置显示目标窗口标题编辑框的句柄
	return bResult; 
}

//卸载钩子
BOOL CMouseHook::StopHook() 
{
	BOOL bResult=FALSE;
	if(glhHook)
	{
		bResult= UnhookWindowsHookEx(glhHook);
		if(bResult)
		{
			glhPrevTarWnd=NULL;
			glhDisplayWnd=NULL;//清变量
			glhHook=NULL;
		}
	}
	return bResult;
}

//返回光标(point)所在点的子窗口句柄
HWND XYZWindowFromPoint(HWND hwndParent,   // handle to parent window
                        POINT point,       // structure with point coordinates
                        UINT uFlags        // skip options
)
{
	if(hwndParent != NULL)
		return ::ChildWindowFromPointEx(hwndParent, point, uFlags);
	//返回光标(point)所在点的子窗口句柄

	// Find the smallest "window" still containing the point
	// Doing this prevents us from stopping at the first window containing the point
	RECT rect, rectSearch;
	HWND pWnd, hWnd, hSearchWnd;

	hWnd = ::WindowFromPoint(point);//得到光标(point)所在点的窗口句柄
	if(hWnd != NULL)
	{
		// Get the size and parent for compare later
		::GetWindowRect(hWnd, &rect);	//得到整个窗口在屏幕上的矩形框位置
		pWnd = ::GetParent(hWnd);       //得到父窗口句柄

		// We only search further if the window has a parent
		if(pWnd != NULL)
		{
			// Search from the window down in the Z-Order
			hSearchWnd = hWnd;
			do{
				hSearchWnd = ::GetWindow(hSearchWnd, GW_HWNDNEXT);//如果再也找不到这样的窗口,该函数就会返回NULL
				//GetWindow得到和句柄为hSearchWnd(即首次循环为hWnd)的窗口相关的窗口,其关系由GW_HWNDNEXT决定,这里是寻找兄弟窗口

				// Does the search window also contain the point, have the same parent, and is visible?
				::GetWindowRect(hSearchWnd, &rectSearch);
				if(::PtInRect(&rectSearch, point) && ::GetParent(hSearchWnd) == pWnd && ::IsWindowVisible(hSearchWnd))
				{
					// It does, but is it smaller?比较看谁的面积最小
					if(((rectSearch.right - rectSearch.left) * (rectSearch.bottom - rectSearch.top)) < ((rect.right - rect.left) * (rect.bottom - rect.top)))
					{
						// Found new smaller window, update compare window
						hWnd = hSearchWnd;
						::GetWindowRect(hWnd, &rect);
					}
				}
			}
			while(hSearchWnd != NULL);
		}
	}
	return hWnd;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -