图片浏览器开发日志-02(图像移动)

摘要:本文将介绍用鼠标移动图像的算法

移动图像算法

根据第一章的模型,要移动图像只需移动A1的位置即ta的左上角坐标即可。
如下图:
在这里插入图片描述
A1的坐标改变之后,A0在A1 中的相对位置发生改变,则从视觉效果上看,相当于对图像进行了移动。
假设移动起码的鼠标坐标是 P(x0,y0),移动后的坐标是p(x1,y1),则鼠标移动后,A1 的坐标修改为:
A1(x,y)=A1(x,y) -( P1-P0)
注意到,移动时,图像大小不变。

图像边界之外的“图像”

上面的计算并没有考虑图像范围之外的背景问题,笔者在Java的版本中自己制作了个一个缓冲区,以应对图像边界之外的图像问题。幸好在MFC中,利用MFC提供的图像处理函数,提供了边界之外的图像问题,这样省去了很多操作。

移动图像的示意代码

本代码截取本人的原程序:
CseePictureDlg::MovePic(CPoint newPnt, CPoint oldPnt, int dist) {

int a, b;
a = (newPnt.x - oldPnt.x);
b = (newPnt.y - oldPnt.y);
if (dist*dist > a*a + b*b) return false;
//change to the point in the imagevew rect
CRect rect;//定义一个矩形框,包含左上角和右下角可访问成员
GetDlgItem(IDC_STATIC_PICTURE)->GetClientRect(rect);//获取Picture控件的位置信息,存入rect中
GetDlgItem(IDC_STATIC_PICTURE)->ClientToScreen(rect);//转换成屏幕坐标

ClientToScreen(&newPnt);
ClientToScreen(&oldPnt);

if (rect.PtInRect(newPnt))//判断point是否在rect内部
{

	float x1, y1, x2, y2;// move the m_A2 which is the view to see the picture, must be float or double!!!!
	x1 = newPnt.x - oldPnt.x + m_A2.left;
	y1 = newPnt.y - oldPnt.y + m_A2.top;
	if (x1 == 0 && y1 == 0) return false;//
	x2 = x1 + m_A2.Width();
	y2 = y1 + m_A2.Height();
	m_A2.SetRect(x1, y1, x2, y2);
	.....
	}
}
return true;

}

移动图像值之技术细节

技术细节有两点,鼠标形状的改变和坐标的变化,也就是要实现dragdrop 事件。
dragdrop event的模拟操作,MFC window 消息中没有现成的dragdrop 事件,因此需要自己模拟。
需要响应三个鼠标事件,鼠标按下, 移动 和鼠标抬起,要采用适当的变量记录鼠标的状态和坐标。具体请参考三个事件的代码:
鼠标左键按下事件:
void CseePictureDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
m_lastDragPnt = point;//记录当钱鼠标位置

ClientToScreen(&point);//将鼠标坐标转换成屏幕坐标
CRect rect;//定义一个矩形框,包含左上角和右下角可访问成员
GetDlgItem(IDC_STATIC_PICTURE)->GetClientRect(rect);//获取Picture控件的位置信息,存入rect中
GetDlgItem(IDC_STATIC_PICTURE)->ClientToScreen(rect);//转换成屏幕坐标
m_lmsBtnDow = false;
if (rect.PtInRect(point))//判断鼠标是否在图像内部按下。
{
	m_lmsBtnDown = true;/
	SetCursor(LoadCursor(NULL, IDC_HAND));//改变鼠标形状
}
CDialogEx::OnLButtonDown(nFlags, point);

}

鼠标移动事件:
void CseePictureDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (!m_lmsBtnDow ) return;//如果没有按下,则返回
SetCursor(LoadCursor(NULL, IDC_HAND));
//m_lmsBtnDow = false;

if (MovePic(point, m_lastDragPnt, 4)) {//移动图像
	m_lastDragPnt = point;
}
CDialogEx::OnMouseMove(nFlags, point);

}

鼠标抬起事件:
该事件中对现场进行恢复。
void CseePictureDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
m_lmsBtnDow = false;
SetCursor(LoadCursor(NULL, IDC_ARROW));
CDialogEx::OnLButtonUp(nFlags, point);
}

为了不至于频繁响应鼠标移动事件,增加了一个距离变量,用来控制移动的距离的门限。
下文中将探讨窗口缩放的实现,并将发现的问题进行汇总。
谢谢大家阅读。

2020-3-19 于北京海淀泛五道口地区。

发布了7 篇原创文章 · 获赞 0 · 访问量 239

猜你喜欢

转载自blog.csdn.net/Uman/article/details/104962871