2012年12月7日 22:42:14

今天我在csdn网站上通过学习别人的博客学习到了动态画矩形,画线的方法,这使得我对Windows的消息循环机制有了更深刻的理解。首先来总结一下我今天的收获,呵呵有收获就是不错的,说明我进步了,感谢这两篇博文:

VC鼠标拖动动态画矩形框(http://blog.csdn.net/zhouxuguang236/article/details/7686163) 和 VC动态轨迹画线 (http://blog.csdn.net/akof1314/article/details/5547616),更感谢转载前一篇博文的作者(zhouxuguang236),是他给了我第二个博文的链接,使得我不用自己去搜索并尝试哪一篇的博文更便于我的学习。

好了下面开始言归正传:

所谓的动态画线,画矩形,画椭圆的本质就是在于消隐问题的解决以及对Windows消息循环机制的理解,消隐问题:因为MFC中有一个函数SetROP2,通过将该函数的参数设置为R2—NOT(当前绘制的像素值设为屏幕像素值的反色,这里面的“屏幕”二字是指你所绘制的图形所占据的那一部分屏幕区域,即直线所占的屏幕区域就是直线所在的那一段线的区域),利用这一点通过在同一区域重复画两次便可以将该区域的形状消隐。

而Windows消息循环机制更好的体现于MouseMove消息响应中,因为要实现动态画线、画矩形这就体现在鼠标在绘图区的移动上,鼠标在绘图区移动时,产生动态的效果,也就是说在mouse 移动的过程中始终在画线、画矩形,这就要求在MouseMove消息响应中有画线、画矩形的相应函数的调用,但正是因为mouse移动的过程中画了很多的线、矩形,所以我们就要在mouse移动的过程中将之前画出的线、矩形消隐掉,才能保证实现了自己所要实现的功能——动态画线、画矩形,但又没有产生多余的线和矩形。

消隐的问题和动态画图的问题关键在于MouseMove消息响应中的函数调用的顺序:

1.首先将上次所画的图形消隐掉

2.画出临时的图形

3.消息循环的机制:循环执行上述代码(这是Windows循环的机制,不需要自己代码实现)

在最后的LButtonUp消息响应中,需要将上面的MouseMove消息响应中循环的最后一次中最后所画的临时图形消隐掉,之后根据LButtonUp消息响应中point参数画出最终的图形。综上可知:MouseMove中的代码和LButtonUp中消隐临时图形的代码所要实现的功能就是动态这一过程,而图形的最终绘制还在与LButtonUp消息响应及其point参数。

代码如下:

private:
//......HCURSOR m_HCross;UINT m_drawType;CPoint m_OldPoint;CPoint m_startPoint;BOOL m_startRect;
CGISView::CGISView()
{// TODO: add construction code here//....m_startRect=FALSE;m_startPoint=0;m_OldPoint=0;m_drawType=0;//初始化m_HCross为十字光标m_HCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);}
void CGISView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: Add your message handler code here and/or call defaultm_startRect=TRUE; //鼠标左键单击,设置可以开始绘制矩形框m_startPoint=point; //记录起始点m_OldPoint=point;//设置老点也为起始点//设置光标为十字光标::SetCursor(m_HCross);CView::OnLButtonDown(nFlags, point);
}
void CGISView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: Add your message handler code here and/or call defaultCClientDC dc(this); //获取设备句柄dc.SetROP2(R2_NOT);//此为关键dc.SetROP2(R2_NOT);//所绘制的图形并没有消失,所以可以验证下面的连续两次颜色取反不是在一次相应中完成//SetRop2 Specifies the new drawing mode.(MSDN)//R2_NOT   Pixel is the inverse of the screen color.(MSDN)//即:该函数用来定义绘制的颜色,而该参数则将颜色设置为原屏幕颜色的反色//这样,如果连续绘制两次的话,就可以恢复原来屏幕的颜色了(如下)//但是,这里的连续两次绘制却不是在一次消息响应中完成的//而是在第一次拖动响应的绘制可以显示(也就是看到的),第二次拖动绘制实现擦出(也就看不到了)dc.SelectStockObject(NULL_BRUSH);//不使用画刷if(TRUE==m_startRect) //根据是否有单击判断是否可以画矩形{switch(m_drawType){case 1://Rectangle::SetCursor(m_HCross);dc.Rectangle(CRect(m_startPoint,m_OldPoint));dc.Rectangle(CRect(m_startPoint,point));m_OldPoint=point;break;case 2: //Line::SetCursor(m_HCross);//擦去上一次绘制的临时线dc.MoveTo(m_startPoint);dc.LineTo(m_OldPoint);   //绘制这一次的临时线dc.MoveTo(m_startPoint);dc.LineTo(point);//将临时线的终点复制给m_OldPoint,//使其在消息循环的过程中将该值传递到//擦去上一次画线的过程中,以便擦去上一次所画的线m_OldPoint=point;break;case 3:  //Circle::SetCursor(m_HCross);//擦去上一次绘制的临时圆//设定该圆的y坐标,因为要保证两点的x之差等于y之差m_OldPoint.y=m_OldPoint.x-m_startPoint.x+m_startPoint.y;dc.Ellipse(CRect(m_startPoint,m_OldPoint));//绘制临时圆point.y=point.x-m_startPoint.x+m_startPoint.y;dc.Ellipse(CRect(m_startPoint,point));m_OldPoint=point;break;case 4:  //Ellipse::SetCursor(m_HCross);dc.Ellipse(CRect(m_startPoint,m_OldPoint));dc.Ellipse(CRect(m_startPoint,point));m_OldPoint=point;break;case 5:   //Dotbreak;}
        }
}
void CGISView::OnLButtonUp(UINT nFlags, CPoint point)
{// TODO: Add your message handler code here and/or call defaultm_startRect=FALSE;//重置绘制矩形框标志::ClipCursor(NULL);//解锁光标,即将光标恢复为默认光标//消隐最后的一个矩形CClientDC dc(this);//获取设备句柄
//  dc.SetROP2(R2_NOT); //在MouseMove消息响应中使用过该函数了,所以在这里再一次使用会使得其恢复为屏幕的颜色dc.SelectStockObject(NULL_BRUSH);  //设置画刷为空画刷switch(m_drawType){case 1: //Retangle//利用当前画刷绘制矩形,内部由当前空画刷(NULL_BRUSH)填充。//擦去MouseMove消息响应中的临时矩形dc.Rectangle(CRect(m_startPoint,m_OldPoint));//绘制固定矩形dc.Rectangle(CRect(m_startPoint,point));//m_drawType=0;  //该行的可以使得每画一次都要选择所画的形状break;case 2:  //Line//擦去MouseMove消息响应中绘制的最后一次临时线dc.MoveTo(m_startPoint);dc.LineTo(m_OldPoint);//绘制固定线dc.MoveTo(m_startPoint);dc.LineTo(point);break;case 3:  //Circledc.Ellipse(CRect(m_startPoint,m_OldPoint));dc.Ellipse(CRect(m_startPoint,point));break;case 4:  //Ellipsedc.Ellipse(CRect(m_startPoint,m_OldPoint));dc.Ellipse(CRect(m_startPoint,point));break;case 5:  //Dotdc.SetPixel(point,RGB(0,0,0));break;}CView::OnLButtonUp(nFlags, point);
}
void CGISView::OnRectangle()
{// TODO: Add your command handler code herem_drawType=1;//设置所画的为矩形}void CGISView::OnLine()
{// TODO: Add your command handler code herem_drawType=2;
}void CGISView::OnEllipse()
{// TODO: Add your command handler code herem_drawType=4;
}void CGISView::OnDot()
{// TODO: Add your command handler code herem_drawType=5;}void CGISView::OnCircle()
{// TODO: Add your command handler code herem_drawType=3;
}

以上为自己根据实际编程练习和对博文的学习所领悟到的,如果有哪里理解的不对,还望大家指正,谢谢哈!(代码没有问题,可以正常运行。)

注:代码的排版,我多次修改,并确保整齐,但是一旦我发表后,代码的排版就会发生改变,有几行代码就会变得不规则。

VC/MFC动态画线(橡皮线),画圆,画椭圆,画矩形相关推荐

  1. matlab画线不同颜色_怎样画线框图才有意义?

    本文由 Jonathan 译自 https://medium.muz.li/how-to-succeed-in-wireframe-design-2ab3cd5c4bc9 我们常轻忽身边习以为常的事物 ...

  2. matlab画线不同颜色_怎样画线框图才有意义

    我们常轻忽身边习以为常的事物,觉得没有必要为一些看似简单又可有可无的东西浪费时间--例如线框图.虽然没必要凡事都寻根问底,但当面对复杂问题时,脚踏实地回归基本面也许才是根本解法. 本文章深入介绍程序开 ...

  3. canvas实现动态点线背景,鼠标画点连线。

    html: <canvas id="canvas"></canvas> css: canvas{display: block;width: 100%;hei ...

  4. C#编写画直线,简单画线,鼠标交互画线,画一条线

    从最简单C#窗体画线开始,直接打开VS,选择C#的窗体应用程序,然后把代码放进去,事件绑定就OK,下面是详细步骤. using System; using System.Collections.Gen ...

  5. openGL实现中点画线算法、DDA画线算法,Bresenham画线算法,并进行鼠标键盘的交互

    首先设置变量用于进行鼠标交互和键盘交互: int m = 0; GLdouble m1 =0, m2 = 0; 1.实验入口主函数: //主函数 int main(int argc, char** a ...

  6. Python+OpenCV 图像处理系列(3)—— 画线、矩形、画圆、画椭圆、画多边形

    OpenCV 中的绘图函数 使用 OpenCV 绘制不同几何图形,其中包括的函数有 cv2.line() cv2.circle() cv2.rectangle() cv2.ellipse() cv2. ...

  7. java 椭圆拟合,OpenCV画轮廓的外界圆矩形椭圆等

    #include #include #include #include using namespace std; #pragma   comment(lib,"cv.lib") # ...

  8. matlab的图片上如何画线,如何在照片上画线?

    本人做了一个GUI界面,目标是实现在axes坐标中导入一张照片,然后可以在照片上用鼠标画圈,然后就可以计算出画圈部分占照片总面积的比例:同时也可以用白色覆盖多余部分(可以看成橡皮擦功能吧?) 但目前: ...

  9. Unity 实现画线火柴人核心画线功能

    最近抖音上很火的小游戏,其中的核心划线功能. [SerializeField] private float width = 0.1f;[SerializeField] private Color co ...

最新文章

  1. 程序员在囧途之软件投标实战
  2. MATLAB:图像半色调技术简介
  3. 夏季适合IT程序员的养生小妙招
  4. 工作99:任务加1逻辑
  5. SEO 搜索引擎优化
  6. 706. 设计哈希映射
  7. 深入理解Java-final关键字
  8. 取消IE“已限制此网页运行可以访问计算机的脚本
  9. Docker 学习5 Docker容器网络
  10. linux----文件权限管理
  11. python mmap_python标准库基础之mmap:内存映射文件
  12. Android 反编译三种方式
  13. Hive grouping sets 多维度交叉清洗数据
  14. 常用数学符号大学(包含罗马字符)
  15. hg8120c 维修使能工具_ONT 用户手册(中国移动) V300R016C10.doc
  16. Oracle Coherence中文教程五:Coherence调试
  17. linux echo当前路径,Linux系统#echo $PWD和#pwd含义一样,都显示用户当前目录()
  18. adb 判断imei_adb 获取imei
  19. Bagging...
  20. java 时分秒加减_JAVA日期加减运算

热门文章

  1. STM32F103最小系统图例
  2. 码工的工具:全局鼠标手势与explorer文件管理器的tab插件
  3. amixer 如何切通道_ALSA音频工具amixer,aplay,arecord
  4. 产品经理面试会被问到什么?
  5. TCPIP协议学习笔记一(概述三)
  6. xrdp linux 3389 端口,在 Linux 中使用 xrdp - Azure Virtual Machines | Microsoft Docs
  7. 全民国家安全教育线上知识竞赛答题活动方案及模板分享
  8. 使用HTK搭建英文大词汇量连续语音识别系统(三)
  9. C#序列化、反序列化学习
  10. 【Tableau 星球】如何快速学习Tableau?(附带学习资源)