当前位置: 首页 > article >正文

MFC程序设计(十二)绘图

 

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

相关类

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;//内存DC
	mendc.CreateCompatibleDC(&dc);//内存DC和当前DC进行匹配  
	//将位图数据送给内存DC
	CBitmap 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();
	//销毁内存DC
	mendc.DeleteDC();
}


http://www.kler.cn/a/543212.html

相关文章:

  • 使用DeepSeek和Kimi快速自动生成PPT
  • 游戏引擎学习第100天
  • 83.在 Vue3 中使用 OpenLayers 利用 TLE 计算并显示单个卫星的轨迹
  • 豆包MarsCode “一键Apply”功能测评:编程效率革新利器
  • 星动纪元ERA-42:端到端原生机器人大模型的里程碑式突破
  • 自制游戏——斗罗大陆
  • 建筑兔零基础自学python记录18|实战人脸识别项目——视频检测07
  • EPL 4.01 Preview
  • 【Elasticsearch】文本分析Text analysis概述
  • 【鸿蒙开发】第二十九章 Stage模型-应用上下文Context、进程、线程
  • Unity 代码优化记录
  • 【c++】shared_ptr是线程安全的吗?
  • fun-transformer学习笔记-Task1——Transformer、Seq2Seq、Encoder-Decoder、Attention之间的关系
  • vivo手机和Windows电脑连接同一个WiFi即可投屏!
  • Spring Cloud 完整引解:优化你的微服务架构
  • GEE批量打开asset权限(anyone can read)
  • YOLOv11融合[AAAI2025]的Mesorch 模型中的高、低频特征提取模块
  • kafka在初始化集群配置当中有哪些重要参数?
  • (定时器,绘制事件,qt简单服务器的搭建)2025.2.11
  • vuedraggable固定某一item的记录
  • 语言大模型基础概念 一(先了解听说过的名词都是什么)
  • 元宵佳节,我的创作纪念日:技术之路的回顾与展望
  • 【多模态大模型】系列1:Transformer Encoder——ViLT、ALBEF、VLMO
  • MVC(Model-View-Controller)framework using Python ,Tkinter and SQLite
  • 机器学习数学基础:22.对称矩阵的对角化
  • LKT4202UGM新一代安全认证加密芯片,守护联网设备和服务安全