MFC的OnMouseMove移动位置和OnMouseWheel缩放实现

MFC的OnMouseMove移动位置和OnMouseWheel缩放实现1 基本作用 OnMouseMove 响应鼠标移动时间 OnMouseWheel 响应鼠标中键的滚动 nbsp 2 参数说明 afx msgvoidOnMou UINTnFlags CPointpoint nFlags 说明 指示虚拟按键是否按下 此参数可以是任何下列值的组合 MK CONTROL nbsp 当 CTRL 键按下时 MK LBUTT

1. 基本作用

OnMouseMove响应鼠标移动时间

OnMouseWheel响应鼠标中键的滚动

 

2. 参数说明

afx_msgvoidOnMouseMove(UINT
nFlags
, CPoint
point
);

nFlags说明:指示虚拟按键是否按下 ,此参数可以是任何下列值的组合

MK_CONTROL 当CTRL键按下时
MK_LBUTTON 当鼠标左键按下时
MK_MBUTTON 当鼠标中键按下时(滚动不属于按下)
MK_RBUTTON 当鼠标右键按下时.
MK_SHIFT 当SHIFT按下时。

point说明:鼠标的X,Y坐标:该坐标为鼠标相对所在窗口左上角为基点的位置,是一个相对位置而不是在屏幕像素上的绝对位置。

 

afx_msg BOOL OnMouseWheel( UINT nFlags, shortzDelta, CPointpt );

nFlags同上

zDelta:大于0时为向上滚动,小于0时为向下滚动。A value less than zero indicates rotating back (toward the user) while a value greater than zero indicates rotating forward (away from the user). Windows下通常向上滚动缩小/窗口上移,反之放大/下移

pt::鼠标的X,Y坐标,是以其父窗口的左上角为基点的。Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.

 

3. 移动的效果实现

要实现移动,例如鼠标左键拖动butoon/图片在窗口上移动,实现的结果附加要求:鼠标放在button/图片的A点,移动之后,鼠标点依然在A点上

我们通过

a. 检测鼠标已在button/图片上(确保不是在哪都可以移动图标),并且左键按下

b. 记录鼠标当前点和上个点,计算两个的偏移值,然后使用这个偏移值来移动button/图片(MoveWindows)

(记录上个点的方法可以使用静态变量,移动完毕后,把当前点赋值给静态变量)(具体实现可以灵活处理)

实现原理是:相对静止—鼠标和对象相对位置不变,鼠标的偏移量,就是我们对象的偏移量

 

4. 缩放的效果实现(以鼠标点为中心缩放)

要实现缩放,例如中件滑轮向上滑动缩小,向下滑动放大button/图片,实现附加要求:鼠标放在button/图片的A点,缩放之后,鼠标点依然在A点上,缩放是以鼠标点为中心

a. 同样检测鼠标已在button/图片上(确保不是在哪都可以缩放button/图片)

b. 获取当前button/图片的高和宽(使用getClientRect)

c. 获取当前pt点x,y相对于button/图片位置,然后计算该位置相对于宽和高的比值

d. 判断zDelta正负确定放大缩小(按比例调整图片高度和宽度),并调整图片左上点(left,top)的位置,确保c中的比值不变(—确保了以鼠标所在点为中心放大或缩小)

实现原理是:相对移动—鼠标和所在对象点位置不变,鼠标所在对象点的周围 长和宽 成比例的缩放



鼠标事件

在日常用到的很多软件里,当鼠标停留在某个菜单或者按钮上一定事件,会弹出关于这个空间的一些提示信息,提示信息可以利用MFC中的CToolTipCtrl 类来实现,输出提示并不难,但是如何判断鼠标停留在某个按钮上呢?可以在对话框中响应WM_SETCOUSE消息,在响应事件中判断发生事件的窗口句柄是不是该控件句柄,如果是做出响应的操作即可,但是如果要判断光标离开控件,则相对复杂一点。因为光标离开控件后,接收鼠标移动消息的窗口句柄肯定不是该控件句柄了,也可以解决,如下:

BOOLCMy12Dlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)

{

         if(pWnd->GetDlgCtrlID() == IDC_BUTTON3)

         {

                   pWnd->SetWindowTextW(_T(“Hover”));

         }

         else if(pWnd->GetDlgCtrlID() != IDC_BUTTON3)

         {

                   GetDlgItem(IDC_BUTTON3)->SetWindowTextW(_T(“Leave”));

         }

         returnCDialogEx::OnSetCursor(pWnd, nHitTest, message);

}

(注:这样做,当鼠标快速的移动的时候,就有可能出现鼠标已经离开了按钮,但按钮还是显示鼠标停留在上面的现象。)

但是如果这样的控件不止一个的时候,难道要用nelse if去判断该句柄是不是对应的控件句柄吗?这样做就有点不合理了,有没有更好的解决办法呢?

经过试验,以下方法可行且相对来说最好:

Cbutton派生子类MyHoverBtn,在子类中响应WM_MOUSEMOVE事件,在该事件的响应函数中添加如下代码来响应鼠标的HoverLeave事件:

void MyHoverBtn::OnMouseMove(UINT nFlags, CPointpoint)

{

         TRACKMOUSEEVENT mouse_event;//定义鼠标移动事件结构体

         mouse_event.cbSize = sizeof(mouse_event);//定义结构体大小

         mouse_event.hwndTrack = m_hWnd;//关联窗口句柄

         mouse_event.dwFlags = TME_HOVER |TME_LEAVE;//设置响应标记

         mouse_event.dwHoverTime = 100/*HOVER_DEFAULT=400*/;//设置Hover的时间

         _TrackMouseEvent(&mouse_event);

 

         CButton::OnMouseMove(nFlags, point);

}

然后在子类MyHoverBtn中响应WM_MOUSEHOVERWM_MOUSELEAVE消息,并在相应的事件响应函数中添加实现代码;例如

void MyHoverBtn::OnMouseLeave()

{

         this->SetWindowTextW(_T(我离开了~”));

         CButton::OnMouseLeave();

}

 

 

void MyHoverBtn::OnMouseHover(UINT nFlags, CPointpoint)

{

         this->SetWindowTextW(_T(我来了~”));

         CButton::OnMouseHover(nFlags, point);

}

 

网上有人说可以在对话框中重载PreTranslateMessage函数,判断消息类型和控件句柄,如果消息是WM_MOUSEMOVE,且该事件发生的控件句柄就是你要控制的控件句柄,则做出响应的处理,代码如下:

BOOLCMy12Dlg::PreTranslateMessage(MSG* pMsg)

{

         CWnd* pWnd = GetDlgItem(IDC_BUTTON1);

         if(pMsg->hwnd == pWnd->GetSafeHwnd() && pMsg->message ==WM_MOUSEMOVE)

         {

                   CPoint point(pMsg->pt);

                   pWnd->ScreenToClient(&point);

                   CRect rect;

                   pWnd->GetClientRect(&rect);

                   if(rect.PtInRect(point))

                            pWnd->SetWindowTextW(_T(“Hover”));

                   else

                            pWnd->SetWindowTextW(_T(“Leave”));

                   returnTRUE;

         }

         returnCDialogEx::PreTranslateMessage(pMsg);

}

请注意绿色部分,这里不合理,因为当光标离开按钮控件后,鼠标移动的事件目标控件就不是该按钮了,与文章开头的方法是一样的,需要另外判断···

说了几种方式,还是派生子类,然后在子类中响应鼠标移动消息,从而做出对应操作最好。但是在设置Hover的时间的时候如果按照默认的HOVER_DEFAULT设置,也就是时间是400毫秒,那么鼠标移动到控件上面后需要等待这个时间才会响应OnMouseHover()于是我将时间减小为100毫秒,比较合理了,如下:

       mouse_event.dwHoverTime = 100/*HOVER_DEFAULT=400*/;//设置Hover的时间

就是不懂如果将时间设置到很小,会不会导致程序不断的提取鼠标移动消息,导致CPU占用增加呢?

经测试将时间设置为1毫秒,相对与设置为100毫秒,cpu也不会大幅增加,MSDN对该参数的解释如下:

dwHoverTime

Specifiesthe hover time-out (if TME_HOVER was specified in dwFlags), in milliseconds.Can be HOVER_DEFAULT, which means to use the system default hover time-out.

 

窗口重绘方面:

Invalidate()使窗口区域无效,以等待下一次重绘WM_PAINT消息将在消息队列为空时发送。与之类似的还有InvalidateRect(),可指定重绘具体的矩形区域。

UpdateWindow() 强制立即更新窗口,在OnPaint()函数中可以用GetUpdateRect()确定重绘区域或者判断是否需要重绘。

RedrawWindowUpdateWindow类似,强制重绘窗口,但是它提供了更多的参数以设置重绘的区域等

在重绘时,需调用BeginPaint()来准备好用于绘画的windows设备环境,填充 PAINTSTRUCT结构,并将DC句柄返回用于重绘。

绘画结束时,需调用EndPaint()来释放设备句柄。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/177589.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午7:09
下一篇 2026年3月26日 下午7:10


相关推荐

  • 互联网服务端测试之RPC接口测试「建议收藏」

    互联网服务端测试之RPC接口测试「建议收藏」开篇碎碎念:18年的时候写过一篇《互联网服务端测试是个啥(入门科普)》(指路https://blog.csdn.net/wangyueshu/article/details/81944250),主要面向的是那些没有接触过服务端测试,尤其是已有端上测试经验、而面对服务端测试时急需转换测试思维的那部分读者。3年过去了,转一圈再回来做服务端测试时,内容也有了扩展。原篇的接口更多的是指代HTTP接口,服务也更多的指代数据服务。而随着算法模型应用的逐渐深入,服务扩展到了模型、策…

    2022年10月13日
    5
  • sstap代理规则网页浏览器_一款Web调试代理工具:Fiddler

    sstap代理规则网页浏览器_一款Web调试代理工具:Fiddler前言在移动软件开发工作中 我们经常需要对 APP 软件进行调试及问题定位 在我们检查定位问题的时候 很多情况下需要查看接口的请求情况 当我们没有在调试模式的情况下 如何才能有效快捷的得到各个接口的请求情况呢 这个时候 我们就需要用到网络代理工具来监控接口请求 今天分享一款常用的 Web 调试代理工具 Fiddler 简介 Fiddler 是一款 Web 调试代理工具 用于记录计算机和 Internet 之间的所有 H

    2026年3月19日
    3
  • 使用playbook安装nginx和mysql

    使用playbook安装nginx和mysql

    2021年5月31日
    134
  • PDF补丁丁( PDFPatcher.)

    PDF补丁丁( PDFPatcher.)PDF 补丁丁是一个用于修改 PDF 文件信息的工具 它具有以下功能 修改 PDF 信息 修改文档属性 页码编号 页面链接 页面尺寸 删除自动打开网页等动作 去除复制及打印限制 设置阅读器初始模式 贴心 PDF 书签编辑器 可批量修改 PDF 书签属性 颜色 样式 目标页码 缩放比例等 在书签中执行查找替换 支持正则表达式及 XPath 匹配 生成 PDF 书签 无需手工输入 自动识别正文标题或目录 为 PDF 文档生成书签 制作 PDF 文件 合并已有 PDF 文件或图片 生成新的 PDF 文件 可挂上书签 拆分或合并 PDF 文件

    2026年3月18日
    2
  • 国内外BaaS服务盘点

    国内外BaaS服务盘点BAAS 为应用开发提供后台的云服务 在当前的移动互联网 云计算热潮中 尤其为这 2 类应用提供了大量的技术支持 包括提供存储 托管环境 也包括提供推送等通行后端技术能力 有单独的 mBAAS 的说法 但大多数人习惯将 BAAS 等同于为移动互联网应用开发而提供的云服务

    2026年3月17日
    1
  • 扣子(Coze)实战:自动生成公众号热点爆文

    扣子(Coze)实战:自动生成公众号热点爆文

    2026年3月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号