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,相匹配的内存DC
	CClientDC dc( this );
	CDC memdc;
	memdc.CreateCompatibleDC( &dc ); //::CreateCompatibleDC
	//将位图的数据送给内存DC
	CBitmap bmp;
	bmp.LoadBitmap( IDB_BITMAP1 ); //::LoadBitmap


	CBitmap* oldbmp = memdc.SelectObject( &bmp );//::SelectObject
	//成像
	dc.BitBlt( 100, 100, 48, 48, &memdc, 0, 0, SRCCOPY );//::BitBlt
	//将位图数据要回来
	memdc.SelectObject( oldbmp );//::SelectObject
	//销毁位图
	bmp.DeleteObject( );//::DeleteObject
	//销毁内存DC
	memdc.DeleteDC( );//::DeleteDC
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jvm -Djava.library.path 无法打开共享对象文件:

项目代码修改 java -jar -Xms1024m -Xmx1024m -Dloader.path/data/encrypt/lib -Djava.library.path/data/encrypt/libVtExtAPI.so server-1.0.0-SNAPSHOT.jar 重新启动

JavaScript基础语法

速通回顾一遍 引入方式 一般会把<script>标签置于<body>元素底部&#xff0c;改善显示速度&#xff1a; 内部脚本&#xff1a;<script></script>标签内外部脚本&#xff1a;<script src""></script>配置src 外部js文件中&…

Cacti 前台SQL注入漏洞复现(CVE-2023-39361)

0x01 产品简介 Cacti 是一套基于 PHP,MySQL,SNMP 及 RRDTool 开发的网络流量监测图形分析工具。 0x02 漏洞概述 该漏洞存在于graph_view.php文件中。默认情况下,访客用户无需身份验证即可访问graph_view.php,在启用情况下使用时会导致SQL注入漏洞。 攻击者可能利用此漏洞…

跨平台兼容,无限可能:Apple Remote Desktop for Mac让远程控制更简单

Apple Remote Desktop for Mac是一款远程桌面管理软件&#xff0c;提供了一系列强大的功能&#xff0c;让用户可以轻松地管理和控制远程计算机。以下是该软件的一些主要功能和特点&#xff1a; 实时远程访问和控制&#xff1a;使用Apple Remote Desktop&#xff0c;用户可以在…

文件操作函数总结(Linux)

目录 一、fopen/fclose 二、fgetc/getc/getchar 三、fputc/putc/putchar 四、fgets/gets 五、fputs/puts 六、fread/fwrite 六、open/close 七、ftell/fssek/rewind/fflush 八、sprintf/sscanf/fprintf/fscanf 九、opendir/closedir/readdir 十、stat 十一、动态/静态…

一款开源且不限制大小可以设置过期时间的支持分享的的开源文件共享系统picoshare 部署教程

1.拉取镜像 2.部署 创建目录 mkdir -p /opt/picoshare/data 部署 其中:"somesecretpass"是密码 docker run \--env "PORT4001" \--env "PS_SHARED_SECRETsomesecretpass" \--publish 10005:4001/tcp \--volume "/opt/picoshare/data:…

UG阵列-数字递增

在UG中&#xff0c;我们对一个文本进行阵列&#xff0c;可以得到很多个相同文本&#xff0c;但是如果文本中的数据是递增数列&#xff0c;需要用到表达式 先画一根参考线&#xff0c;标注参考线长度&#xff0c;并记录系统生成对应长度的表达式&#xff0c;例如p15 然后插入一个…

IO、NIO、IO多路复用

IO是什么&#xff1f; IO分为两类&#xff0c;它们之间是有区别的&#xff0c;而且有很大的区别&#xff1b;1. 文件系统的IO 也叫本地io&#xff0c;就是和磁盘或者外围存储设备进行读写操作&#xff0c;外围设备有USB、移动硬盘等等&#xff1b;2. 网络的IO 将数据发送给对方…

Android12 授予APK默认权限

不同于以往的Android版本 可以直接在此处设置: Android/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java private void grantDefaultSystemHandlerPermissions(PackageManagerWrapper pm, int userId) {Log.i(TAG, &q…

flutter 环境搭建异常记录

flutter 环境搭建异常记录 1.执行flutter doctor自检报错 排查Android studio里配置的sdk是哪个 SDK Platforms选中 8.0 SDkTools也只勾选8.0 2.bash_profile 文件配置 没有的话 在根目录新建 export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_…

【Npm】一文了解透彻package.json里的script字段以及相关知识

本文会从介绍npm run的原理、script字段作用、node_modules/.bin文件夹是什么 一、什么是npm script 在package.json里面定义的scripts字段就是&#xff0c;它的每一个属性都对于一段脚本。 {// ..."scripts": {"build": "node build.js"} }其…

6.3.5编辑视频

6.3.5编辑视频 除了上面的功能外&#xff0c;Camtasia4还能进行简单的视频编辑工作&#xff0c;如媒体的剪辑、连接、画中画等。 下面我们就利用Camtasia4的强大功能来实现一个画中画效果&#xff0c;在具体操作之前&#xff0c;需要准备好两个视频文件&#xff0c;一个作为主…

docker:Java通过nginx获取客户端的真实ip地址

问题现象 我们的平台使用Spring Cloud微服务架构&#xff0c;使用Spring Boot构建Java服务&#xff0c;使用google的jib插件打成docker镜像包我们使用docker虚拟化部署&#xff0c;使用docker-compose统一管理所有服务&#xff0c;包括Java服务和nginx等组件我们前后端分离&am…

蓝天采集器,功能逆天的网站数据抓取神器,轻松助你成为采集达人,附带搭建配置文档

源码介绍 蓝天采集器是一款专为web服务器打造的数据采集神器。与市面上常见的桌面端采集工具&#xff08;如火车头等&#xff09;相比&#xff0c;蓝天采集器在易用性、上手成本和灵活性方面更胜一筹。它部署简便&#xff0c;无需复杂的设置&#xff0c;即可迅速融入您的web服…

路由器初始化配置、功能配置

实验环境 拓扑图 Ip规划表&#xff08;各组使用自己的IP规划表&#xff09; 部门 主机数量 网络地址 子网掩码 网关 可用ip Vlan 市场部 38 192.168.131.0 255.255.255.0 192.168.131.1 2-254 11 研发部 53 192.168.132.0 255.255.255.0 192.168.132.1 2-2…

浅析CXL P2P DMA加速数据传输拥堵问题的解决方案

接上文&#xff1a;CXL P2P DMA加速数据传输的拥堵问题 为了改善这个问题&#xff0c;CXL 3.0引入了Unordered-IO和Back Invalidate Snoop新机制&#xff0c;允许更直接和高效点对点数据传输&#xff0c;以减轻上游CXL通道的压力并减少延迟。 (1)Unordered-IO (UIO) 在传统PCI…

Java如何做到无感知刷新token含示例代码(值得珍藏)

1. 前言 在系统页面进行业务操作时&#xff0c;有时会突然遇到应用闪退&#xff0c;并被重定向至登录页面&#xff0c;要求重新登录。此问题的出现&#xff0c;通常与系统中用于存储用户ID和token信息的Redis缓存有关。具体来说&#xff0c;这可能是由于token过期所导致的身份…

shell编程-3

文章目录 shell学习第三天while 循环第一天的小游戏练习: 编写抽同学回答问题的脚本要想让这个脚本永久有效如何知道两个文件里的内存一样&#xff1f;如何判断某个人已经抽过了 文本处理相关命令seqxargsuniqsorttrcutawkpastesplitcoljoin小结一下作业 小知识点写脚本的流程怎…

【蓝桥杯EDA设计与开发】资料汇总以及立创EDA及PCB相关技术资料汇总(持续更新)

[18/01/2024]&#xff1a;目前为了准备蓝桥杯做一些资料贴&#xff0c;于是写下这一篇博客。 各种资料均来源于网络以及部分书籍、手册等文档&#xff0c;参考不保证其准确性。 如果在准备蓝桥杯&#xff0c;可与我私信共同学习&#xff01;&#xff01;&#xff01;&#xf…