再谈平移图像 简单却足以说明原理

 方式一:


第1步-----重载ONEraseBkgnd, 直接返回FALS,不要自动刷新背景,避免平移闪烁

BOOL CImgView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
 	return FALSE;  //表示未处理背景刷新
}

第2步----左键按下消息

		SetCapture(); //捕获鼠标
		SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR_HANDOPEN));// 手形光标
		m_prePoint = point; //记录下左键按下时的位置

第3步----移动鼠标消息

	if (nFlags&MK_LBUTTON){
	m_ulPoint.x += point.x - m_prePoint.x; //图像移动后的新初始位置
	m_ulPoint.y += point.y - m_prePoint.y;

	InvalidateRect(m_imgRec); //更新客户区
}

第4步---鼠标弹起消息   释放被窗口捕获的鼠标

void CImgView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
    ReleaseCapture();
	CView::OnLButtonUp(nFlags, point);
}






方式二:

平移图像,要响应三个消息

 

鼠标按下:    目的是记录刚按下时鼠标位置

鼠标移动:    此时鼠标位置-按下时的鼠标位置即为移动偏移量

鼠标UP:       重置变量值。

 

为此,需要3个全局变量:

m_Point   ----------------->目标图片的左上角

m_LbtndownP----------->左键刚按下时的坐标

m_PreP-------------------->移动之前的点的坐标,这个变量在鼠标移动时使用,在鼠标UP时重置

 

原理分析:

     移动过程中,为使得图片正确移动,关键是如何得到移动后图片坐标m_Point, 为此,我们必须先求出移动偏移量,而要求移动偏移量,必先知道左键刚按下时的坐标m_LbtndownP;而当我们知道量后偏移,下一步工作就是反推出当前目标图片坐标,由于偏移量是相对于移动之前的图片,因此,我们必须记录下移动之前的图片坐标m_PreP,才能推出现在目标图片的坐标

 

以下是各个程序:

 

变量定义:

public:
	Image *m_pImage;
	Bitmap *m_pBmp;

	CPoint m_Point;
	CPoint m_LbtndownP;
	CPoint m_PreP;


变量初始化:

 

 

CImageView::CImageView()
{
	m_pImage=NULL;
	m_pBmp=NULL;
	m_Point.x=m_Point.y=0;
	m_PreP=m_LbtndownP=m_Point;
}


左键按下消息:

 

void CImageView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	m_LbtndownP=point;

	CView::OnLButtonDown(nFlags, point);
}


鼠标移动消息:

 

void CImageView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值


	if ((nFlags&MK_LBUTTON)==MK_LBUTTON)
	{


		if (GetPixel(GetDC()->GetSafeHdc(),point.x,point.y)!=RGB(255,255,255))  // 判断鼠标是否在图片上,判断方法可自行修改
		{
			m_Point.x=m_PreP.x+(point.x-m_LbtndownP.x);
			m_Point.y=m_PreP.y+(point.y-m_LbtndownP.y);
			Invalidate(FALSE);
		}
	}


	CView::OnMouseMove(nFlags, point);
}


鼠标UP消息:

 

void CImageView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	m_PreP=m_Point;

	CView::OnLButtonUp(nFlags, point);
}


OnDraw函数:

void CImageView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: 在此添加绘制代码
	CRect rect;
	GetClientRect(&rect);


	if (m_pImage!=NULL)
	{
		if(m_pBmp==NULL)  // OnSize中 delete掉m_pBmp  否则放大对话框时有问题,因为m_pBmp还是原来的尺寸,所以放大可能出现问题
		{
			m_pBmp=new Bitmap(rect.Width(),rect.Height());
		}
		Graphics gbmp(m_pBmp);
		gbmp.Clear(Color(255,255,255,255));
		gbmp.DrawImage(m_pImage,m_Point.x,m_Point.y);
		
		Graphics g(GetDC()->m_hDC);
		g.DrawImage(m_pBmp,0,0);
	}else{

		GetDC()->FillSolidRect(rect,RGB(255,255,255));
	}


}


 

 

以下是整体程序:

.h头文件

#pragma once


// CImageView 视图

class CImageView : public CView
{
	DECLARE_DYNCREATE(CImageView)

protected:
	CImageView();           // 动态创建所使用的受保护的构造函数
	virtual ~CImageView();

public:
	virtual void OnDraw(CDC* pDC);      // 重写以绘制该视图
#ifdef _DEBUG
	virtual void AssertValid() const;
#ifndef _WIN32_WCE
	virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
	DECLARE_MESSAGE_MAP()

protected:
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
public:
	virtual void OnInitialUpdate();

public:
	Image *m_pImage;
	Bitmap *m_pBmp;

	CPoint m_Point;
	CPoint m_LbtndownP;
	CPoint m_PreP;
	
public:
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
public:
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
public:
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
public:
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
public:
	afx_msg void OnSize(UINT nType, int cx, int cy);
};



.cpp源文件

// ImageView.cpp : 实现文件
//

#include "stdafx.h"
#include "TreePath.h"
#include "ImageView.h"


// CImageView

IMPLEMENT_DYNCREATE(CImageView, CView)

CImageView::CImageView()
{
	m_pImage=NULL;
	m_pBmp=NULL;
	m_Point.x=m_Point.y=0;
	m_PreP=m_LbtndownP=m_Point;
}

CImageView::~CImageView()
{
	if (m_pImage!=NULL)
	{
		delete m_pImage;
		m_pImage=NULL;
	}

	GdiplusShutdown(gdiplusToken);


}

BEGIN_MESSAGE_MAP(CImageView, CView)
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_SIZE()
END_MESSAGE_MAP()


// CImageView 绘图


/*
		RectF rc;
		rc.X=rect.left;
		rc.Y=rect.top;
		rc.Width=rect.Width();
		rc.Height=rect.Height();

		gbmp.DrawImage(m_pImage,rc,0,0,m_pImage->GetWidth(),m_pImage->GetHeight(),UnitPixel);
*/


void CImageView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: 在此添加绘制代码
	CRect rect;
	GetClientRect(&rect);


	if (m_pImage!=NULL)
	{
		if(m_pBmp==NULL)  // OnSize中 delete掉m_pBmp  否则放大对话框时有问题,因为m_pBmp还是原来的尺寸,所以放大可能出现问题
		{
			m_pBmp=new Bitmap(rect.Width(),rect.Height());
		}
		Graphics gbmp(m_pBmp);
		gbmp.Clear(Color(255,255,255,255));
		gbmp.DrawImage(m_pImage,m_Point.x,m_Point.y);
		
		Graphics g(GetDC()->m_hDC);
		g.DrawImage(m_pBmp,0,0);
	}else{

		GetDC()->FillSolidRect(rect,RGB(255,255,255));
	}


}


// CImageView 诊断

#ifdef _DEBUG
void CImageView::AssertValid() const
{
	CView::AssertValid();
}

#ifndef _WIN32_WCE
void CImageView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif
#endif //_DEBUG


// CImageView 消息处理程序

void CImageView::OnInitialUpdate()
{
	CView::OnInitialUpdate();
	GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);



	// TODO: 在此添加专用代码和/或调用基类
}

BOOL CImageView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	return FALSE;

	return CView::OnEraseBkgnd(pDC);
}

void CImageView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值


	if ((nFlags&MK_LBUTTON)==MK_LBUTTON)
	{


		if (GetPixel(GetDC()->GetSafeHdc(),point.x,point.y)!=RGB(255,255,255))  // 判断鼠标是否在图片上,判断方法可自行修改
		{
			m_Point.x=m_PreP.x+(point.x-m_LbtndownP.x);
			m_Point.y=m_PreP.y+(point.y-m_LbtndownP.y);
			Invalidate(FALSE);
		}
	}


	CView::OnMouseMove(nFlags, point);
}

void CImageView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	m_LbtndownP=point;

	CView::OnLButtonDown(nFlags, point);
}

void CImageView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	m_PreP=m_Point;

	CView::OnLButtonUp(nFlags, point);
}

void CImageView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	if(m_pBmp)
		delete m_pBmp;
	m_pBmp=NULL;

//	Invalidate(FALSE);

	// TODO: 在此处添加消息处理程序代码
}


 

 

 

 

你可能感兴趣的:(image,null,delete,Class,UP)