MFC程序设计(十二)绘图

news/2025/2/13 7:35:56/

 

只有类对象和绘图设备句柄进行绑定,该类对象才可以进行绘图

相关类

m_hDC和m_hAttribDC保存了同一个绘图设备句柄

CPaintDC类和CClientDC类继承于CDC类

CPaintDC类在WM_PAINT消息的OnPaint消息处理函数中使用,CClientDC类在其他消息,如COMMAND消息的消息处理函数中使用

接下来我们通过MFC向导创建一个单文档视图架构项目进行分析CPaintDC类和CClientDC

CPaintDC类对象

首先通过类向导添加WM_PAINT消息

接下来我们可以在类向导为我们生成的函数中进行绘图

void CMFCDrawView::OnPaint()
{CPaintDC dc(this); //类对象与绘图句柄绑定,其中this为视图窗口dc.Rectangle(100, 100, 300, 300);//其内部实现为::Rectangle//也可::Rectangle(dc.m_hDC, 100, 100, 300, 300);
}

该代码绘制了一个矩形。接下来我们通过第一行代码观察MFC是如何将类对象和绘图句柄绑定在一起的,我们进入CPaintDC dc(this)内部观察

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

通过代码可知,在CPaintDC dc(this)的内部,MFC将绘图句柄和类对象进行了绑定

在上述代码中,我们在CPaintDC dc(pView)构造函数的内部发现了Win32的::BeginPaint,与之配对的::EndPaint则存在与CPaintDC dc(pView)的析构函数中。由于dc是局部变量,因此在离开OnPaint函数时,dc被析构,出现::EndPaint

CClientDC类对象

接下来我们将通过点击菜单项,在视图窗口客户区进行绘图

首先添加一个菜单项

如图,这是我们添加的菜单项,ID为ID_CLIENT

我们为该菜单项添加消息处理函数

void CMFCDrawView::OnClient()
{CClientDC dc(this);dc.Ellipse(300, 300, 500, 500);
}

此时便绘画了一个圆形。

但这个圆和上文的矩形有所差别,当视图窗口改变时,这个圆会消失,而矩形不会消失。这是因为当窗口发生改变时,就会产生绘图消息,OnPaint就会被调用,重新绘制矩形,而上述代码绘制的圆形,只有在点击菜单项时才会被调用

绘图相关类

接下来我们将针对这些类进行一个应用学习

首先我们添加一些菜单,并添加相应的消息处理函数,使得我们点击相关菜单项时触发不同的消息处理函数

CPen的ID为ID_PEN

CBrush的ID为ID_BRUSH

CFont的ID为ID_CFont

CBitmap的ID为ID_BMP

CPen应用

//MFC写法
void CMFCDrawView::OnCfont()
{CClientDC dc(this);//CClientDC类对象绑定绘图设备句柄CPen pen(PS_SOLID, 2, RGB(255, 0, 0));//CPen类对象绑定画笔句柄CPen* oldpen = dc.SelectObject(&pen);//函数返回原来的CPen类对象dc.Rectangle(100, 100, 300, 300);dc.SelectObject(oldpen);//恢复原来的CPen类对象pen.DeleteObject();
}
//win32写法
void CMFCDrawView::OnPen()
{CClientDC dc(this);CPen pen(PS_SOLID, 2, RGB(255, 0, 0));HGDIOBJ nOldPen = ::SelectObject(dc.m_hDC, pen.m_hObject);::Rectangle(dc.m_hDC, 100, 100, 300, 300);::SelectObject(dc.m_hDC, nOldPen);::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获取的画笔句柄hObject,保存到pen对象的一个成员变量中}
}

在接下来的CBrush,CFont等等都是通过上述代码的方式进行类成员和绘图句柄进行绑定的

CBrush应用

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

运行程序,出现一个实心的矩形

CFont应用

void CMFCDrawView::OnCfont()
{CClientDC dc(this);CFont font;font.CreatePointFont(300, "黑体");dc.SelectObject(&font);CFont* oldfont = dc.SelectObject(&font);dc.TextOutA(100, 100, "hello");dc.SelectObject(&oldfont); 
}

运行程序,出现字体hello

CBitmap应用

1.添加一个位图资源,ID = IDB_BITMAP1

2.代码实现

void CMFCDrawView::OnClient()
{//添加位图资源CClientDC dc(this);//当前DC//创建一个和当前DC相匹配的内存DC CDC mendc;//内存DCmendc.CreateCompatibleDC(&dc);//内存DC和当前DC进行匹配  //将位图数据送给内存DCCBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);CBitmap* oldbmp = mendc.SelectObject(&bmp);//传送位图数据//成像dc.BitBlt(100, 100, 50, 50, &mendc, 0, 0, SRCCOPY);//将位图数据要回来mendc.SelectObject(oldbmp);//销毁位图bmp.DeleteObject();//销毁内存DCmendc.DeleteDC();
}


http://www.ppmy.cn/news/1571640.html

相关文章

3.2 > Bash

概览 在上一节中我们了解了关于 Shell 的执行流程,知道了在 Linux 环境中一般有哪些常用的 Shell。而在本节中,将会学习到 Linux 中最常见的一个 Shell —— Bash,了解到 bash 的相关知识和用法。 本节目录 概览相关知识bash 命令提示符bas…

k8s管理工具之lens

什么是lens Lens 是当前市场上最强大的K8S IDE。它是一个独立的单机应用,可以同时运行在macOS、Windows和Linux上。 作为K8S IDE,该有的它基本都有了! 集群管理 导入已有集群 首先,你需要在 Lens 中添加你的 Kubernetes 集群。点…

【蓝桥杯嵌入式】8_IIC通信-eeprom读写

全部代码网盘自取 链接:https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码:3ii2 1、电路图 这个电路允许通过I2C总线与EEPROM(M24C02-WMN6TP)和数字电位器(MCP4017T-104ELT)进行通信。EEPROM用于存储数据,而数字电位器可以用…

基于 Gauss 公式的日期计算

Gauss 公式(或称 Gauss 算法)是一种用于日期计算的经典数学方法,主要用于将一个给定的天数(从某个固定日期开始计算的天数)转换为具体的年、月、日。 Gauss 公式的核心思想是基于闰年规则 和天数累积规律 ,…

【课设者】SSM课设-图书管理系统

【课设者】SSM课设-图书管理系统 分为 管理员 和 普通用户 技术栈 前端: HtmlCssJavaScriptLayUI 后端: Spring、Spring MVC、MyBatis、MySQL、JSP 通用部分 --登陆 注册 退出 --首页 --文件上传 --文件导出 用户端 --借阅图书 借出 --借阅时间线 --修改资料 修改个人资…

Qt开发:QDataStream的常用方法

文章目录 一、QDataStream的构造函数二、QDataStream的读写操作符三、QDataStream的状态检查四、QDataStream的版本控制五、QDataStream的序列化自定义类型 一、QDataStream的构造函数 在 Qt 中,QDataStream 类提供了对二进制数据的序列化和反序列化功能&#xff0…

js实现异步的方法

所有异步任务都是在同步任务执行结束之后,从任务队列中依次取出执行。 回调函数是异步操作最基本的方法,比如AJAX回调,回调函数的优点是简单、容易理解和实现,缺点是不利于代码的阅读和维护,各个部分之间高度耦合&…

深入浅出学算法030-兔子繁殖

题目描述 有一种兔子,出生后一个月就可以长大,然后再过一个月一对长大的兔子就可以生育一对小兔子且以后每个月都能生育一对。现在,我们有一对刚出生的这种兔子,那么,n个月过后,我们会有多少对兔子呢&…