【mfc】通过鼠标钩子检测对话框外的点击

文章目录


前言

        前段时间试过用OnActivate方法来检测对话框外部的鼠标点击(为了达到对话框失去焦点后自动隐藏的效果),当nState参数为WA_INACTIVE时表示有外部点击,然而这种方式在使用过程中偶尔会出现未响应的情况(有时连按两次win+D之后点击外部就不会响应OnActivate消息了),于是我转而使用鼠标hook实现该效果。以下为实现方式:


一、自定义用户消息

 声明部分(.h)

#define WM_MOUSEBUTTONDOWN WM_USER+777
afx_msg LRESULT OnMouseButtonDown(WPARAM wParam, LPARAM lParam);

实现部分(.cpp) 

BEGIN_MESSAGE_MAP(CdailycompletionDlg, CBaseTaskDlg)
	//。。。
	ON_MESSAGE(WM_MOUSEBUTTONDOWN, OnMouseButtonDown)
	//。。。
END_MESSAGE_MAP()

 获取对话框的客户矩形区域,并转换到屏幕空间下,以此判断鼠标是否点击的是对话框外:

LRESULT CdailycompletionDlg::OnMouseButtonDown(WPARAM wParam, LPARAM lParam)
{
	if (!IsWindowVisible())return 0;
	CRect rc;
	GetClientRect(&rc);
	ClientToScreen(&rc);
	// 判断点击窗口外
	if (!rc.PtInRect(*(POINT*)lParam))
	{
		// ...
	}
	return 0;
}

二、创建全局钩子

 这里的对话框直接定义为单例了,如果不是单例需要一个全局变量来保存对话框指针。

// 鼠标钩子
HHOOK glHook = NULL;
LRESULT CALLBACK MouseProc(int nCode, WPARAM msg, LPARAM lparam)
{
	if (msg == WM_LBUTTONDOWN)
	{
		auto glWnd = CdailycompletionDlg::Instance();
		if (glWnd && IsWindow(glWnd->GetSafeHwnd()))
		{
			PMOUSEHOOKSTRUCT mh = (PMOUSEHOOKSTRUCT)lparam;
			POINT pt;
			pt.x = mh->pt.x;
			pt.y = mh->pt.y;
			glWnd->SendMessage(WM_MOUSEBUTTONDOWN, 0, (LPARAM)&pt);
		}
	}
	return CallNextHookEx(glHook, nCode, msg, lparam);
}

在OnInitDialog中注册钩子

// 注册鼠标钩子
glHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);

在OnDestroy中释放钩子

if (glHook) 
			UnhookWindowsHookEx(glHook);


三、效果图

以上就是今天要讲的内容,本文仅仅简单介绍了鼠标hook的使用,能使我们快速便捷地处理鼠标键盘的响应事件。

posted @ 2022-10-30 02:31  香菇0_0  阅读(140)  评论(0)    收藏  举报