MFC案例:利用双缓冲技术绘制顶点可移动三角形

ops/2025/2/28 5:45:16/

        案例目标:在屏幕上出现一个三角形,同时显示各顶点坐标,当用鼠标选择某顶点并拖动时,三角形随鼠标移动而变形。具体步骤为:

一、在VS2022上建立一个基于对话框的MFC应用,项目名称:DrawMovableTriangle,其它步骤使用缺省。进入对话框界面,选择对话框,将其适当拉大一些。然后,删除其自带的控件。
二、打开解决方案资源管理器,找到DrawMovableTriangleDlg.h文件
  1、先以public方式声明一个函数:

  void drawTriangle(); //这是绘制三角形的主要函数

  2、再以protected方式声明三个变量:

 CPoint vertexPos[3]; //三角形的三个顶点坐标BOOL boolLBDown; //鼠标左键按下标志,TRUE按下,FALSE抬起int vertexNum; //顶点序号

三、利用类向导添加三个消息处理函数
  1、鼠标左键按下处理函数
       步骤:项目->类向导->确认类名是*Dlg->单击消息->找到并单击WM_LBUTTONDOWN->点击添加处理程序,这样在DrawMovabletriangleDlg.h文件中就有了如下声明:

  afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

  2、采用类似步骤,继续添加鼠标移动消息处理函数和左键抬起消息处理函数,如下:
      afx_msg void OnMouseMove(UINT nFlags, CPoint point);
      afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
      以上三个消息处理程序不但在这里进行了声明,同时还在DrawMovableTriangleDlg.cpp中进行了实现,只是实现函数中还没有我们需要的代码,我们需要做的就是将这些代码添上。
四、在DrawMovableTriangleDlg.cpp中找到OnInitDialog()函数,在TODO:行下面,完成几个变量的赋初值。代码如下:

  CRect rect;// 定义矩形类对象GetClientRect(rect);//GetClientRect将窗口客户区宽、高等数据存入rectvertexPos[0] = CPoint(rect.Width()/2,rect.Height()/4); //上顶点vertexPos[1] = CPoint(rect.Width()/4,rect.Height()*3/4); //左下顶点vertexPos[2] = CPoint(rect.Width()*3/4,rect.Height()*3/4); //右下顶点boolLBDown = FALSE; //默认鼠标左键未按下vertexNum = 0; //初始绘制三角形从上顶点开始

五、在DrawMovableTriangle.cpp文件中实现动态绘制三角形函数,在这个函数中要使用到双缓冲技术,具体代码如下:

void CDrawMovableTriangleDlg::drawTriangle()
{CRect rect; //声明矩形结构GetClientRect(&rect); //获取客户区数据存入rectCDC* pDC = GetDC();CDC memDC; //声明一个设备上下文对象(兼容对象)memDC.CreateCompatibleDC(pDC); //兼容对象与当前设备上下文pDC兼容(实际上兼容对象此时尚无空间)CBitmap NewBitmap, * pOldBitmap; //声明一个位图对象和一个位图指针NewBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); //位图对象与pDC兼容,这个位图可以代替pDC用于作图pOldBitmap = memDC.SelectObject(&NewBitmap);//位图对象选入兼容对象中,并将原位图信息存入位图指针,此时在memDC上作图实际上是在NewBitmap上作图memDC.FillSolidRect(rect, pDC->GetBkColor()); //用pDC的背景色填充memDC//在memDC上作图memDC.SelectStockObject(GRAY_BRUSH); //将灰色画刷选入兼容对象for (int i = 0; i < 3; i++) {CString str;str.Format((L"x = %d, y = %d"), vertexPos[i].x, vertexPos[i].y); 将三角形顶点坐标组合成字符串memDC.SetTextColor(RGB(255, 0, 0)); //设置兼容上下文对象的文字颜色memDC.TextOutW(vertexPos[i].x, vertexPos[i].y, str); //输出字符串到兼容上下文对象的文字颜色memDC.Rectangle(vertexPos[i].x - 5, vertexPos[i].y - 5, vertexPos[i].x + 5, vertexPos[i].y + 5); //给三角形顶点绘制小方块if (0 == i)  //画出三角形memDC.MoveTo(vertexPos[i]); //遇三角形第一个顶点则定位elsememDC.LineTo(vertexPos[i]); //不是顶点时则连线(0-1,1-2)}memDC.LineTo(vertexPos[0]); //连接2-0pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); //将兼容对象中的图像copy到设备上下文对象中memDC.SelectObject(pOldBitmap); //恢复兼容对象NewBitmap.DeleteObject();/* Windows 显示设备的属性,共有下面几种:位图、画刷、字体、画笔、区域。如果要设置它们到当前(或兼容)设备里,就需要使用SelectObject 函数,比如上面介绍的字体设置,就会用到这个函数。当你创建一个位图时,这时 Windows 就会在内存里分配一块内存空间,用来保存位图的数据。当你创建字体时,也会分配一块内存空间保存字体。如果程序只是分配,而不去删除,就会造成内存使用越来越多,最后导到 Windows 这幢大楼倒下来。如果你忘记删除它,就造成了内存泄漏。因此,当你创建显示设备资源时,一定要记得删除它们啊,否则运行你的程序越长,就导致系统不稳定。记得使用DeleteObject 函数去删除它们,把占用的内存释放回去给系统。*/memDC.DeleteDC();/* 如果一个设备上下文环境的句柄是通过调用GetDC函数得到的,那么应用程序不能删除该设备上下文环境,应该调用ReleaseDC函数来释放该设备上下文环境。如果是自己生成的,则用DeleteDC释放所占用的资源 */
}

六、接着,还是在DrawMovableTriangle.cpp中找到那三个消息处理函数中,为其添加相关代码如下:
  1、在void CDrawMovableTriangleDlg::OnLButtonDown(UINT nFlags, CPoint point)中TODO:行下面,添加一句代码:

boolLBDown = TRUE;

  2、在176 void CDrawMovableTriangleDlg::OnMouseMove(UINT nFlags, CPoint point)中TODO:行下面添加:

	CDC* pDC = GetDC();for (int i = 0; i < 3; i++) {if (point.x<vertexPos[i].x + 5 && point.x>vertexPos[i].x - 5 && point.y<vertexPos[i].y + 5 && point.y>vertexPos[i].y - 5) {  //判断鼠标是否在三角形顶点上下或左右5个像素范围内SetCursor(LoadCursor(NULL, IDC_HAND));/*上面的设置光标样式为手型,LoadCursor加载windows 自带的光标资源时第一个参数必须为空*/vertexNum = i;} //标记被点击的三角形顶点序号}if (boolLBDown)  vertexPos[vertexNum] = point;//将鼠标位置付给顶点,这里鼠标状态是即按下又在移动ReleaseDC(pDC);//释放pDC,从用此函数也证明pDC不是memDC,若是memDC须用memDC.DeleteDC();drawTriangle(); //调用动态画三角形程序

  3、在207 void CDrawMovableTriangleDlg::OnLButtonUp(UINT nFlags, CPoint point)中TODO:行下面添加:

boolLBDown = FALSE; //恢复左键弹起设置,否则选上三角形定点后放不开

五、运行效果截图:


http://www.ppmy.cn/ops/161868.html

相关文章

WebRTC学习七:WebRTC 中 STUN 协议详解

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 第六篇 WebRTC学习三…

深度学习-11.用于自然语言处理的循环神经网络

Deep Learning - Lecture 11 Recurrent Networks for Natural Language Processing 介绍文本表示用数字表示单词词嵌入(word embedding) 机械翻译编码器 - 解码器循环模型&#xff08;Encoder-decoder recurrent models&#xff09;双向循环网络 注意力机制&#xff08;方法&am…

ASP.NET 解决 NLog、log4net 和 Serilog 在 IIS 部署后不写日志的问题

在使用 NLog、log4net 或 Serilog 等日志框架时&#xff0c;如果将应用程序部署到 IIS 后发现日志无法正常记录&#xff0c;通常是因为权限或配置问题导致的。 简单粗暴&#xff1a;对写log的目录给添加Everyone 权限

DeepSeek 提示词:常见指令类型

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

Go Web 项目实战:构建 RESTful API、命令行工具及应用部署

Go Web 项目实战&#xff1a;构建 RESTful API、命令行工具及应用部署 Go 语言因其简洁高效、并发支持强大等特点&#xff0c;已经成为了后端开发的热门选择之一。本篇文章将通过实战案例带领你学习如何使用 Go 构建一个简单的 RESTful API&#xff0c;开发命令行工具&#xf…

P9420 [蓝桥杯 2023 国 B] 子 2023

P9420 [蓝桥杯 2023 国 B] 子 2023 题目 分析代码 题目 分析 刚拿到这道题&#xff0c;我大脑简单算了一下&#xff0c;这个值太大了&#xff0c;直观感觉就很难&#xff01;&#xff01; 但是&#xff0c;你仔仔细细的一看&#xff0c;先从最简单的第一步入手&#xff0c;再…

算法-数据结构-图的构建(邻接矩阵表示)

数据定义 //邻接矩阵表示图 //1.无向图是对称的 //2.有权的把a,到b 对应的位置换成权的值/*** 无向图* A B* A 0 1* B 1 0*/ /*** 有向图* A B* A 0 1* B 0 0*/import java.util.ArrayList; import java.util.List;/*** 带权图* A B* A 0 1* B 0 0*/ p…

监督学习——基于线性回归的波士顿房价预测:理论、实践与评估

基于线性回归的波士顿房价预测:理论、实践与评估 文章目录 基于线性回归的波士顿房价预测:理论、实践与评估一、引言二、线性回归基础理论2.1 线性回归原理2.2 线性回归在房价预测中的应用逻辑三、波士顿房价数据集介绍3.1 数据集概述3.2 特征说明3.3 目标变量四、波士顿房价…