MFC 绘图

目录

MFC中绘图

CPaintDC,封装了在WM_PAINT消息中绘图的绘图设备

CClientDC类,封装了在客户区绘图的绘图设备

CGdiObject类(绘图对象类),封装了各种绘图对象相关的操作


MFC中绘图

Windows绘图需要绘图设备,Win32:绘图设备句柄(HDC);MFC:绘图类对象,本质上还是类绑定句柄。

绘图相关类:

CDC类(绘图设备类):封装了各种绘图相关的函数,以及两个非常重要的的成员变量m_hDC和m_hAttribDC。有以下两个子类:

  • CPaintDC类,封装了在WM_PAINT消息中绘图的绘图设备
  • CClientDC类,封装了在客户区绘图的绘图设备

CGdiObject类(绘图对象类):封装了各种绘图对象相关的操作,以及一个非常重要的成员变量m_hObject(绘图对象句柄),有以下几个子类:

  • CPen类,封装了画笔的操作
  • CBrush类,封装了画刷的操作
  • CFont类,封装了字体的操作
  • CBitmap类,封装了位图的操作

CPaintDC,封装了在WM_PAINT消息中绘图的绘图设备

创建一个单文档视图架构的项目,视图类管理视图窗口,是现实图像用的,应该在视图类中使用绘图类。处理WM_PAINT消息,类向导如下:

处理WM_PAINT消息

void CMFCDrawView::OnPaint()
{CPaintDC dc(this); //::BeginPaint
//	dc.Rectangle( 100, 100, 300, 300 );//::Rectangle(...)
//	::Rectangle( dc.m_hDC, 100, 100, 300, 300 );
}

绘图类谁也代表不了,无法代表绘图设备,只有和绘图设备句柄绑定才行。

下断点,看看CPaintDC的构造函数,参数是视图类对象地址,函数内部this是CPaintDC对象地址

函数伪代码如下:

CPaintDC dc(pView) === CPaintDC::CPaintDC(...)//函数内部this为&dc
{Attach(::BeginPaint(pView->m_hWnd, &m_ps))//函数内部this为&dc{m_hDC = hDC;//将BeginPaint获取的绘图设备句柄  保存到dc对象的一个成员变量中SetAttribDC(m_hDC)//函数内部this为&dc{m_hAttribDC = m_hDC;//dc对象的另一个成员变量也保存了绘图设备句柄}}
}

所以m_hDC和m_hAttribDC保存的是绘图设备句柄,本质上依然是Windows API

_AFXWIN_INLINE BOOL CDC::Rectangle(int x1, int y1, int x2, int y2){ ASSERT(m_hDC != NULL); return ::Rectangle(m_hDC, x1, y1, x2, y2); }

等价于

::rectangle( dc.m_hdc, 100, 100, 300, 300 );

在Win API 编程,使用绘图设备,需要有拿到绘图设备句柄和释放。在MFC中这个任务就交给了构造函数和析构函数。

CPaintDC::CPaintDC(CWnd* pWnd)
{ASSERT_VALID(pWnd);ASSERT(::IsWindow(pWnd->m_hWnd));if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))   // 获取绘图设备句柄AfxThrowResourceException();
}CPaintDC::~CPaintDC()
{ASSERT(m_hDC != NULL);ASSERT(::IsWindow(m_hWnd));::EndPaint(m_hWnd, &m_ps);          // 释放绘图设备句柄Detach();
}

代码如下:

void CMFCDrawView::OnPaint()
{CPaintDC dc(this); // device context for painting// TODO: 在此处添加消息处理程序代码// 不为绘图消息调用 CView::OnPaint()dc.Rectangle(100, 100, 300, 300);//::Rectangle(dc.m_hDC, 100, 100, 300, 300);
}

结果如下:

CClientDC类,封装了在客户区绘图的绘图设备

给菜单新加一项,ID为 ID_Client

使用类向导处理点击后的WM_COMMAND消息,四个框架类都可以处理,因为是在视图窗口绘图,所以在视图窗口处理。

生成函数,函数内部this是视图窗口对象地址,用于在视图窗口的客户区的窗口绘图

结果如下:

但是当窗口放大缩小后,圆形消失不见了,但是矩形还在。

原因:触发WM_PAINT消息后,OnPaint函数就会被触发执行,所以矩形一致都在,而OnClient则不是。

CGdiObject类(绘图对象类),封装了各种绘图对象相关的操作

拿画笔举例子:

  1. 创建一根画笔
  2. 把画笔给绘图设备
  3. 使用画笔画画
  4. 要回画笔
  5. 销毁画笔

创建如下4个菜单项

创建处理WM_COMMAND消息的函数

画笔:

void CMFCDrawView::OnPen()
{CClientDC dc( this );CPen pen(PS_SOLID, 2, RGB(255,0,0));  // 实心 像素为2 颜色为红色CPen* oldpen = dc.SelectObject( &pen );//HGDIOBJ nOldPen = ::SelectObject( dc.m_hDC, pen.m_hObject );dc.Rectangle( 100, 100, 300, 300 );//::Rectangle( dc.m_hDC, 100, 100, 300, 300 );dc.SelectObject( oldpen );//::SelectObject( dc.m_hDC, nOldPen );pen.DeleteObject( );//::DeleteObject( pen.m_hObject );
}

跟下CPen的构造函数,伪代码如下:其它也是同理

CPen pen(PS_SOLID, 2, RGB(255,0,0)) === CPen::CPen(PS_SOLID, 2, RGB(255,0,0))
//函数内部this &pen
{Attach(::CreatePen(PS_SOLID, 2, RGB(255,0,0)))//函数内部this &pen{m_hObject = hObject;//将::CreatePen获取的画笔句柄,保存到pen对象的一个成员变量中}
}

画刷:

void CMFCDrawView::OnBrush()
{CClientDC dc(this);CBrush brush(RGB(0,255,0));CBrush* oldbrush = dc.SelectObject( &brush );dc.Rectangle( 100, 100, 300, 300 );dc.SelectObject( oldbrush );brush.DeleteObject( );
}

字体

void CMFCDrawView::OnFont()
{CClientDC dc( this );CFont font;font.CreatePointFont(300, "黑体");//::CreateFont(..............)CFont* oldfont = dc.SelectObject( &font );dc.TextOut( 100, 100, "hello");dc.SelectObject( oldfont );font.DeleteObject();
}

位图:

  1. 添加位图资源
  2. 创建一个和当前DC相匹配的内存DC
  3. 将位图的数据给内存DC
  4. 成像
  5. 将位图数据要回来
  6. 销毁位图
  7. 销毁内存DC

void CMFCDrawView::OnBmp()
{//添加位图资源(操作资源无需写代码)//创建一个和当前DC,相匹配的内存DCCClientDC dc( this );CDC memdc;memdc.CreateCompatibleDC( &dc ); //::CreateCompatibleDC//将位图的数据送给内存DCCBitmap bmp;bmp.LoadBitmap( IDB_BITMAP1 ); //::LoadBitmapCBitmap* oldbmp = memdc.SelectObject( &bmp );//::SelectObject//成像dc.BitBlt( 100, 100, 48, 48, &memdc, 0, 0, SRCCOPY );//::BitBlt//将位图数据要回来memdc.SelectObject( oldbmp );//::SelectObject//销毁位图bmp.DeleteObject( );//::DeleteObject//销毁内存DCmemdc.DeleteDC( );//::DeleteDC
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/632674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pyqtgraph绘图类

pyqtgraph绘图类 pyqtgraph绘图有四种方法: 方法描述pyqtgraph.plot()创建一个新的QWindow用来绘制数据PlotWidget.plot()在已存在的QWidget上绘制数据PlotItem.plot()在已存在的QWidget上绘制数据GraphicsLayout.addPlot()在网格布局中添加一个绘图 上面四个方法都接收同样…

OpenHarmony应用开发-进程间通讯

版本:v3.2 Beta5 进程模型 OpenHarmony的进程模型如下图所示: 应用中(同一包名)的所有UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个独立进程中,即图中绿色部分的“Main Process”。…

Linux设备驱动开发学习笔记(等待队列,锁,字符驱动程序,设备树,i2C...)

1. 内核工具和辅助函数 1.1宏container_of container_of函数可以通过结构体的成员变量检索出整个结构体 函数原型: /* pointer 指向结构体字段的指针 container_type 结构体类型 container_field 结构体字段名称 返回值是一个指针 */ container_of(pointer, con…

在线App封装技术:HTML5的新生命

HTML5封装的魅力所在HTML5带来了丰富的多媒体功能、地理位置服务、离线存储等特性,使得Web应用的体验更加接近原生App。封装HTML5到App中,可以大大缩短开发周期,降低开发成本,并且一次编写,多平台运行,极大…

MySQL面试题 | 15.精选MySQL面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

.NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

前言 在.NET 6之前我们一直是使用QRCoder来生成二维码(QRCoder是一个非常强大的生成二维码的组件,用到了System.Drawing.Common 包),然后从.NET 6开始,当为非 Windows 操作系统编译引用代码时,平台分析器会…

外汇天眼:Alpha Group International在2023财年实现营收同比增长12%

Alpha Group International plc,一家为企业和机构提供金融解决方案的公司,今天发布了截至2023财年的贸易更新。 营收增长12%,达到1.1亿英镑(2022财年:9830万英镑)。 税前利润增长超过140%,达到…

xhr、jQuery、axios、fetch、vue-resource简单了解和对比

1. xhr 不常用(太麻烦),一般进行二次封装,或者使用成型的第三方封装jQuery,axios等。axios和jQuery都是对xhr的封装。 2. jQuery 核心是封装Dom操作,80%的内容都是关于Dom的,Vue和React的使用…

第16章_网络编程拓展练习(TCP编程,UDP编程)

文章目录 第16章_网络编程拓展练习TCP编程1、学生与老师交互2、查询单词3、拓展:查询单词4、图片上传5、拓展:图片上传6、多个客户端上传文件7、群聊 UDP编程8、群发消息 第16章_网络编程拓展练习 TCP编程 1、学生与老师交互 案例:客户端模…

Qt程序如何在Release模式下进行断点调试

有些时候,因为某些工程pro文件设置了debug和Release版本的原因,导致在编译运行的时候,程序会自动生成带d后缀的一些库文件,进行调试。 debug模式下我们打断点进行调试,大家都知道。但是Release模式下,如果你直接Ctrl + R运行,肯定是无法断点调试的。 那么这个时候,我…

AEB滤镜再破碎,安全焦虑「解不开」?

不久前,理想L7重大交通事故,再次引发了公众对AEB的热议。 根据理想汽车公布的事故视频显示,碰撞发生前3秒,车速在178km/h时驾驶员采取了制动措施,但车速大幅超出AEB(自动紧急刹车系统)的工作范…

如何搭建Z-blog网站并结合内网穿透实现无公网ip访问本地站点

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员,自己搭建网站制作网页是绕…

hadoop下载,安装

下载: https://mirrors.tuna.tsinghua.edu.cn/ 从清华源下载 找到apache 找到hadoop 找到对应的版本 使用64位版本 上传到linux的 /usr/local 目录下 使用tar -zxvf 文件。 命令解压 添加path路径 1,vim /etc/profile 2, 追加hadoop的两个bin路径…

Ps:使用钢笔工具快速精准抠图的技巧

众所周知,钢笔工具是 Photoshop 中最精准的、适用于硬边缘(清晰轮廓)对象的抠图工具。但是,如果从头开始一个锚点一个锚点的勾勒,既费时又费眼。 我们可以先用选区工具或选区命令做一个基础选区,然后将选区…

【Linux】权限的深度解析

前言:在此之前我们学习了一些常用的Linux指令,今天我们进一步学习Linux下权限的一些概念 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:Linux的学习 👈 💯代码仓库:卫卫周大胖的学习日记&a…

python实现图片式PDF转可搜索word文档[OCR](已打包exe文件)

目录 1、介绍 1.1、痛点 1.2、程序介绍 2、安装方式 2.1、🔺必要环节 2.2、脚本安装 2.2.1、不太推荐的方式 2.2.2、节约内存的方式 2.3、⭐完整版安装 3、使用 3.1、最终文件目录 3.2、主程序 3.2.1、绝对路径 3.2.2、是否为书籍 3.2.3、⭐截取区域 …

lvgl移植流程

移植准备 基于梁山派屏幕扩展板mcu屏幕源码Screen_MCU移植下载lvgl 8.3版本源码下载地址:https://github.com/lvgl/lvgl参考文档:Set-up a project — LVGL documentation 移植步骤 1. 删除源码 删除源码中不需要的文件夹,仅保留如下内容 demos : lvgl综合案例e…

QtCreator12无法识别Qt5.15.2的安卓SDK与NDK配置解决

解决方法: 设置JDK为JDK11 使用Android Studio下载 Android SDK Command-line Tools 10.0 打开Android SDK Location : 双击打开cmdline-tools 复制10.0中所有东西到latest中 点击Manage Kits并选择Devices 然后点击Android会弹出下图窗口,并自动更 安装完成 成功识别

股票套牢,如何解套?当下行情怎么赚钱?

今年开年大盘继续一路下行,今天更是直接跌破2800点,很多朋友都是套牢的阶段,这种时候我们怎样解套,在这种情况下,作为散户的我们又如何才可以赚到钱呢? 股票被套可以借用哪些工具解套?详细操作…

新数智空间:阿里云边缘云持续保持中国公有云市场第一

全球领先的 IT 市场研究和咨询公司 IDC 发布 《中国边缘云市场解读(2023H1)》报告 中国边缘公有云服务市场 阿里云持续第一 稳居市场第一,“边缘”逆势生长 近日,全球领先的 IT 市场研究和咨询公司 IDC 最新发布《中国边缘云市…