【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的使用,能使我们快速便捷地处理鼠标键盘的响应事件。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以通过以下步骤在C++ MFC对话框中实现拖动和放缩控件加载的图片: 1. 在对话框资源中添加一个静态图片控件,可以通过拖拽方式添加。 2. 在控件类头文件中添加以下成员变量: ``` CPoint m_ptOrigin; //记录鼠标按下时的坐标 BOOL m_bDragging; //标记是否正在拖拽 ``` 3. 在控件类头文件中添加以下函数: ``` void OnLButtonDown(UINT nFlags, CPoint point); //鼠标左键按下事件处理函数 void OnMouseMove(UINT nFlags, CPoint point); //鼠标移动事件处理函数 void OnLButtonUp(UINT nFlags, CPoint point); //鼠标左键抬起事件处理函数 void OnSize(UINT nType, int cx, int cy); //窗口大小改变事件处理函数 ``` 4. 在控件类实现文件中实现以上四个函数: ``` void CMyStatic::OnLButtonDown(UINT nFlags, CPoint point) { m_bDragging = TRUE; m_ptOrigin = point; SetCapture(); //设置鼠标捕获 } void CMyStatic::OnMouseMove(UINT nFlags, CPoint point) { if (m_bDragging) { CRect rect; GetWindowRect(&rect); ScreenToClient(&rect); //将窗口坐标系转换为客户区坐标系 int dx = point.x - m_ptOrigin.x; int dy = point.y - m_ptOrigin.y; rect.left += dx; rect.top += dy; rect.right += dx; rect.bottom += dy; MoveWindow(&rect); } } void CMyStatic::OnLButtonUp(UINT nFlags, CPoint point) { m_bDragging = FALSE; ReleaseCapture(); //释放鼠标捕获 } void CMyStatic::OnSize(UINT nType, int cx, int cy) { //重新设置图片控件的大小 CStatic::OnSize(nType, cx, cy); if (GetSafeHwnd()) { CImage image; image.Load(_T("your_image_path")); int nWidth = image.GetWidth(); int nHeight = image.GetHeight(); if (nWidth > 0 && nHeight > 0) { int nNewWidth = cx; int nNewHeight = cy; if ((double)nWidth / nHeight > (double)nNewWidth / nNewHeight) { nNewHeight = nNewWidth * nHeight / nWidth; } else { nNewWidth = nNewHeight * nWidth / nHeight; } SetWindowPos(NULL, 0, 0, nNewWidth, nNewHeight, SWP_NOMOVE | SWP_NOZORDER); Invalidate(); //刷新窗口 } } } ``` 5. 在对话框类头文件中添加以下成员变量: ``` CMyStatic m_staticImage; //静态图片控件 ``` 6. 在对话框类实现文件中的OnInitDialog函数中初始化静态图片控件: ``` m_staticImage.SubclassDlgItem(IDC_STATIC_IMAGE, this); //将静态图片控件与对应的对话框控件关联 ``` 7. 在对话框类实现文件中重载OnSize函数,调整静态图片控件的位置和大小: ``` void CMyDialog::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (m_staticImage.GetSafeHwnd()) { CRect rect; m_staticImage.GetWindowRect(&rect); ScreenToClient(&rect); rect.right = rect.left + cx; rect.bottom = rect.top + cy; m_staticImage.MoveWindow(&rect); } } ``` 通过以上步骤,您可以在C++ MFC对话框中实现拖动和放缩控件加载的图片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值