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

89 篇文章 5 订阅

(参考:OnMouseMove_百度百科CWnd::OnMouseWheel | Microsoft Learn)

Owed by: 春夜喜雨 春夜喜雨-CSDN博客  转载请标明来源 

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中的比值不变(---确保了以鼠标所在点为中心放大或缩小)

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

5. 进阶-算法

对于移动与缩放来说,如果看过计算机图形学,或是接触过matrix变换距阵操作的同学,可以基于这一点来理解这一块的操作。

已知

translate 是平移的操作

scale是缩放操作

平移操作: translate(vector)  vector-偏移量

假设坐标原值为

[X.src

Y.src]

对于二维平面来说,在平移时,平移量

[X.move,

Y.move],

平移后的坐标新值为

[X.src + X.move, 

Y.src + Y.move]

缩放操作:  scale(vector, point) vector-缩放量 point-缩放的基点

假设坐标原值为

[X.src

Y.src]

对于二维平面来说,缩放量,因为我们当前缩放比例x/y轴使用相同量,所以X.scale = Y.scale,统一使用scale

[scale,

scale]

a. 对于以原心(0,0)为基础的缩放的话,缩放结果为

[X.src * scale

Y.src * scale]

b. 考虑到以指定点为缩放基点,设指定基点为

[X.base,

Y.base]

则缩放齐次方程为

[scale,    0,     X.base(1-scale)

 0,        scale, Y.base(1-scale)

0,            0,        1]

计算结果(X.src, Y.src)坐标新值为:

[X.src * scale + X.base*(1-scale),

Y.src * scale + Y.base*(1-scale)]

对于中心点的位置,会随着缩放靠近或远离基点,可以根据偏移量定位

X.newcenter = X.base - (X.base - X.oldcenter) * scale

Y.newcenter = Y.base - (Y.base - Y.oldcenter) * scale

旋转操作:rotate(angle, point) angle-旋转角度 point-旋转基点

假设坐标原值为

[X.src

Y.src]

对于二维平面来说,设旋转角度为@度,逆时针旋转,

a. 如果绕着圆心(0,0)旋转的话,

X.dest = R * Cos(OrgAngle + @) = R * sin(OrgAngle) * sin(@)  + R * cos(OrgAngle) * cos (@) = X.src * Sin@ + Y.src * cos@

Y.dest = R * Sin(OrgAngle + @)  = X.src * -Sin(@) + Y.src * cos(@)

相当于乘以矩阵

[ sin@, cos@

 -sin@, cos@]

b. 考虑到绕特定点旋转,设指定基点为

[X.org,

Y.org]

则相当于,偏移特定点为(0,0)点,旋转后再偏移回来

X.dest = X.org +  (X.src - X.org) * sin@ + (Y.src-Y.org)*cos@

Y.dest = Y.org -  (X.src - X.org) * sin@ + (Y.src-Y.org)*cos@

齐次方程为

[ sin@, cos@,  X.org - X.org * sin@ - Y.org * cos@ 

 -sin@, cos@,  Y.org + X.org * sin@ - Y.org * cos@

0,           0,           1]

综述:从图形学的这些计算上来看,我们实现的平移,鼠标点为中心放大 也或 旋转 的算法部分都属于比较基础的应用。还算比较简单,毕竟是二维的。

如果希望深入掌握这些的话,可以阅读下《计算机图形学》这本书。

Owed by: 春夜喜雨 春夜喜雨-CSDN博客  转载请标明来源 

  • 9
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
MFC(Microsoft Foundation Classes)是一种用于开发Windows桌面应用程序的C++框架。如果想要实现鼠标移动放大镜效果,可以按照以下步骤进行操作: 1. 创建一个新的MFC项目。在Visual Studio中,选择“创建新项目”,然后选择“MFC应用程序”模板,可以命名你的项目并选择相应的选项和设置。 2. 在MFC应用程序的主视图类中添加成员变量。打开mainfrm.h文件,在类定义中添加一个CBitmap成员变量和一个标记鼠标状态的布尔变量,例如`CBitmap m_Bitmap;`和`BOOL m_isMouseDown;`。 3. 重写主视图的OnCreate函数。在创建视图时加载一个原始图像作为放大镜的背景图像。在OnCreate函数中,添加以下代码: ```c++ CClientDC dc(this); m_Bitmap.LoadBitmap(IDB_MYBITMAP); // IDB_MYBITMAP代表原始图像资源的ID dc.SelectObject(m_Bitmap); ``` 4. 重写主视图类的OnMouseMove函数。当鼠标移动时,获取鼠标的当前坐标,并计算放大镜的位置和大小。重绘视图以实现放大镜效果。在OnMouseMove函数中,添加以下代码: ```c++ void CMyView::OnMouseMove(UINT nFlags, CPoint point) { if (m_isMouseDown) { CRect rect; GetClientRect(&rect); // 获取视图的客户区矩形 // 计算放大镜的位置和大小 int magnifierWidth = 100; // 放大镜的宽度 int magnifierHeight = 100; // 放大镜的高度 int offsetX = point.x - magnifierWidth / 2; int offsetY = point.y - magnifierHeight / 2; // 裁剪放大镜的位置 if (offsetX < 0) offsetX = 0; if (offsetX > rect.Width() - magnifierWidth) offsetX = rect.Width() - magnifierWidth; if (offsetY < 0) offsetY = 0; if (offsetY > rect.Height() - magnifierHeight) offsetY = rect.Height() - magnifierHeight; // 获取放大镜背景图像的子位图 CBitmap bmp; CDC memDC; memDC.CreateCompatibleDC(&dc); bmp.CreateCompatibleBitmap(&dc, magnifierWidth, magnifierHeight); memDC.SelectObject(&bmp); memDC.BitBlt(0, 0, magnifierWidth, magnifierHeight, &dc, offsetX, offsetY, SRCCOPY); // 放大镜效果的绘制代码 CDC dc; dc.CreateCompatibleDC(pDC); dc.SelectObject(&bmp); CRect destRect(point.x, point.y, point.x + magnifierWidth, point.y + magnifierHeight); pDC->StretchBlt(destRect.left, destRect.top, destRect.Width(), destRect.Height(), &dc, 0, 0, magnifierWidth, magnifierHeight, SRCCOPY); // 清理资源 memDC.DeleteDC(); bmp.DeleteObject(); dc.DeleteDC(); } CView::OnMouseMove(nFlags, point); } ``` 5. 重写主视图类的OnLButtonDown和OnLButtonUp函数。这两个函数用于标记鼠标的按下和抬起状态。在这两个函数中,添加以下代码: ```c++ void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { m_isMouseDown = TRUE; CView::OnLButtonDown(nFlags, point); } void CMyView::OnLButtonUp(UINT nFlags, CPoint point) { m_isMouseDown = FALSE; CView::OnLButtonUp(nFlags, point); } ``` 通过以上步骤,我们可以实现MFC应用程序中实现鼠标移动放大镜效果。当鼠标按下并移动时,会在视图中显示一个放大的区域,该区域随着鼠标的移动而变化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春夜喜雨

稀罕你的喜欢!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值