MFC两种拖动鼠标动态画图的方法

原创 2015年07月09日 20:42:38

一般来说,一次画图的过程分为鼠标左键按下,鼠标移动,鼠标左键弹起。要想在鼠标移动的过程中动态显示所画的图的变化过程,所画的图只能是可以由两个点确定的图形,如直线、矩形、椭圆等等。举例来说,如何画一条线段?我们要知道起点和终点。起点自然是鼠标左键按下时鼠标的位置,终点是鼠标移动时当前的鼠标位置。既然是拖动鼠标动态画图,那么画图的动作自然是在鼠标移动的响应函数OnMouseMove()里完成。要想让图跟着鼠标移动而变化,就必须在鼠标移动时不断根据鼠标新位置画图,然而不停画图,原来画的旧图还停留在那里。本来一次鼠标移动只要画一根线段,现在一次鼠标移动画出好多根线段。所以关键是如何擦除旧图。第一种方法是保存上一次鼠标停留的位置,然后用背景色的画笔把旧图描一遍。

//鼠标左键按下

void C画图Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
  mousemode = 1;//标识鼠标左键已按下
  pt_Begin = pt_End = pt_Mid = point;//pt_Begin标识起点,pt_End标识新终点,pt_Mid标识旧终点
 CDialogEx::OnLButtonDown(nFlags, point);
}

//鼠标移动

void C画图Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if (mousemode == 1)//确保鼠标移动是在鼠标左键按下后
 {
  pt_Mid = pt_End;//将原终点的值赋给pt_Mid
  pt_End = point;//将当前鼠标的位置赋给新终点
  EraseLine(pt_Begin, pt_Mid);//擦掉旧线段
  DrawLine(color,pt_Begin, pt_End);//画新线段

CDialogEx::OnMouseMove(nFlags, point);
  }
 }

但是这样会把原来作好的图也擦掉。想到的解决方法是将原来作好的图的数据(如起点和终点,还可以扩充如画笔颜色,图形种类等,写成一个class)储存在vector里面,擦掉旧图后先把储存在vector里面的图画一遍,再画新图,当然也可以画新图之后再把储存在vector里面的图画一遍。储存画好的图在鼠标左键弹起的时候进行。

//鼠标移动

void C画图Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if (mousemode == 1)//确保鼠标移动是在鼠标左键按下后
 {
  pt_Mid = pt_End;
  pt_End = point;
  EraseLine(pt_Begin, pt_Mid);//擦掉旧线段
  DrawLine(color,pt_Begin, pt_End);//画新线段
  DrawpGraph(vec_pGraph);//重画已画好的图形

CDialogEx::OnMouseMove(nFlags, point);
 }

//鼠标左键弹起

void C画图Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if (mousemode == 1)
 {
  mousemode = 0;
  vector<POINT> vec;
  vec.push_back(pt_Begin);
  vec.push_back(pt_End);
  previousGraph temp(drawmode, color, vec);//previousGraph是储存每个画好的图的数据的class
  vec_pGraph.push_back(temp);//将这次画的图形的种类,颜色,起点和终点存入向量vec_pGraph中
  pt_Begin = { 0, 0 };
  pt_Mid = { 0, 0 };
  pt_End = { 0, 0 };
 }

CDialogEx::OnLButtonUp(nFlags, point);

}

将画好的图的数据储存在vector里面的一个好处是我们可以很容易地进行撤销与重做。然而假如一开始不是在一张空白的图上作画,而是在一张背景图上作画时,这样还是会擦掉背景图。第二种方法可以解决这个问题。

第二种方法进行动态画图的思路是鼠标左键按下时将当前窗口的内容保存为一张图片,鼠标移动过程中每次画新图之前都先载入这张图片。

void CDrawXView::DrawpGraph()//函数,功能是载入保存了鼠标左键按下时窗口图像的图片
{
 test.Attach(image.Detach());//test是CBitmap类型的对象
 CDC MemDC;
 CDC dc;
 MemDC.CreateCompatibleDC(NULL);
 dc.CreateCompatibleDC(&MemDC);
 dc.SelectObject(&test);
 CClientDC ClientDC(this);
 ClientDC.BitBlt(0, 0, //目标设备逻辑横、纵坐标
  AreaWidth, AreaHeight, //显示位图的像素宽、高度
  &dc, //待显示位图数据的设备情境对象
  0, 0, //源数据中的横、纵坐标
  SRCCOPY);
}

//鼠标左键按下
void CDrawXView::OnLButtonDown(UINT nFlags, CPoint point)
{
 mousemode = 1;
 CRect rect; GetClientRect(&rect);//获取画布大小  
 CClientDC dc(this); 
 hbit = CreateCompatibleBitmap(dc, rect.right - rect.left, rect.bottom - rect.top);//创建兼容位图
 HDC hdc = CreateCompatibleDC(dc);      //创建兼容DC,以便将图像保存为不同的格式 
 HBITMAP hOldMap = (HBITMAP)SelectObject(hdc, hbit); //将位图选入DC,并保存返回值  
 BitBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, dc, 0, 0, SRCCOPY); //将屏幕DC的图像复制到内存DC中    
 hbit = (HBITMAP)SelectObject(hdc, hOldMap); 
 image.Attach(hbit);//将图像保存到image中,image是CImage类型
 pt_Begin = pt_End = pt_Mid = point;
 CScrollView::OnLButtonDown(nFlags, point);
}
//鼠标移动
void CDrawXView::OnMouseMove(UINT nFlags, CPoint point)
{
 if (mousemode == 1)
 {
  pt_End = point;
  DrawpGraph();
  DrawLine(color, pt_Begin, pt_End);
 }
 CScrollView::OnMouseMove(nFlags, point);
}

//鼠标左键弹起

void C画图Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if (mousemode == 1)
 {
  mousemode = 0;
  pt_Begin = { 0, 0 };
  pt_End = { 0, 0 };
 }

CDialogEx::OnLButtonUp(nFlags, point);

}


版权声明:本文为博主原创文章,未经博主允许不得转载。

【计算机图形学课程】二.MFC鼠标响应函数模拟画图软件

上一篇文章我们讲述MFC绘制图形的基本函数,包括绘制直线、绘制矩形、绘制椭圆及绘制文字,同时通过绕圆旋转和矩形平移简单的理解了图形学知识。这篇文章我将介绍鼠标响应和键盘响应,通过这些事件让学生实现一个...

绘制连续线条 改变鼠标形状

在前一个练习中,我们绘制的是线段,即鼠标按下时的位置坐标为线段的起点,鼠标左键弹起的位置坐标为线段的终点,线段的位置与这两个操作中间的操作无关。       如果绘制连续的线条,我们必须考虑这一中间操...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

MFC实现鼠标中键滑动WM_MOUSEWHEEL响应,使得图形缩放

MFC实现鼠标中键滑动WM_MOUSEWHEEL响应,使得图形缩放 已经实现,没有问题 CRenderView基类是CView,实现显示操作三维模型。 实现鼠标滚轮缩放简单步骤如下: (1)响...

OpenGL实现鼠标绕任意轴旋转/平移/缩放

刚刚学opengl的童鞋肯定有个苦恼的麻烦,只会绘制一个三角形,但是想像那些三维软件那样用鼠标控制视角还是有点困难的,所以我就封装了一个场景漫游类:RoamingScenceManager,这个类使用...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

MFC下图形任意角度旋转.

图形的旋转公式: x1   =   (x - xcenter) *  cosθ - (y - ycenter)  * sinθ + xcenter;  y1   =   (x - xcenter)...

MFC 鼠标移动画矩形

MFC 鼠标移动画矩形 问题日记:MFC 鼠标移动画矩形 昨天的时候,模仿人家的软件已经七七八八啦,开始不断完善的工作。首先是完善用鼠标拖动矩形选择东西,开始当然进入死胡同,在OnMouseMov...

MFC 实现图片的拖拽功能,代码很详细,贴过去就能用!

拖动是界面编程频繁使用的一个效果,在windows系统下可谓大行其道。纵观时下的应用软件几乎各个都支持各种各样拖动的效果,windows7更是把拖动做到了极致。其实说起来拖动的实现也很简单,对于有句柄...

[C#]GDI+在鼠标移动(MouseMove)时画平滑曲线

关于平滑曲线,相信很多人在网上提过这个问题,如何画出平滑曲线?我也很想知道答案,究竟如何才能在MouseMove事件里画出真正平滑又柔和的曲线?注意本文讨论的重点是在MouseMove事件里,并非相对...
  • luols
  • luols
  • 2012年09月29日 16:46
  • 7781
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC两种拖动鼠标动态画图的方法
举报原因:
原因补充:

(最多只允许输入30个字)