戏说 Windows GDI (1)

2023-12-02 12:38
文章标签 windows gdi 戏说

本文主要是介绍戏说 Windows GDI (1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0.题记:

作为QT开发的支持者和践行者,明知道MFC已经过时,但是还不得不用;老板要求,项目组师兄弟代码兼容Balabala~也许这就是中国式项目研发。

好啦,聊点正经事......

1.设备描述表(Device Context,DC):通往各种输出设备的桥梁

在单任务环境如MS-DOS中,运行中的应用程序随时可自由的想做他想做的事,无论是在屏幕上画一条线,重新编写适配器的调色板,还是转换到另一种图像模式。而在窗口化多任务环境如Windows中,程序则无此自由。因为程序A的输出必须与程序B的输出相隔离。首先,这意味着各程序的输出必须限制在自己的窗口中。GDI(Graphic Device Inteface,GDI)使用一简单的机制保证在窗口中画图的各程序遵循这些规则。这种机制即为“设备描述表”,也就是我们常说的DC。

当Windows程序在屏幕、打印机或其他输出设备上画图时,他并不是将像素直接输出到设备上,而是将图绘制到由设备描述表表示的逻辑意义上的“显示平面”上去。设备描述表是深寓于Windows中的一种设备结构,它包含GDI需要的关于显示平面情况的描述字段,包括相连的物理设备和各种各样的状态信息。在平面上画图之前,Windows程序从GDI获取设备描述表的句柄,并且每次调出GDI输出函数时,将句柄返回给GDI。若没有有效的设备描述表聚丙,则GDI不会画第一个像素。

再利用MFC编制Windows程序时,设备描述表具有更加突出的作用。除了可以作为通往各种输出设备的桥梁之外,设备描述表对象还封装了程序用来产生输出的GDI函数。在MFC中,我们不再需要捕获设备描述表句柄和调用GDI输出函数,至少不用直接捕获和调用,而是通过创建设备描述表对象并调用它的成员函数来画图

2.MFC设备描述表类

在MFC应用程序中获取设备描述表的一种方法是调用CWnd::GetDC(),它返回指向表示Windows设备描述表的CDC对象的指针。在画图完毕时,要用CWnd::ReleaseDC()释放由GetDC()获得到的设备吧、描述表的指针。具体如下面程序所示:

CDC* pdc = GetDC();
//do some drawing
ReleaseDC(pdc);
再这里需要我们注意的是,如果在OnPain处理程序中时,则需要Cwnd::BeginPaint和CWnd::EndPaint分别代替GetDC()和ReleaseDC(),以保证合理地处理WM_PAINT消息:

PAINTSTRUCT PS;
CDC* pDC = BeginPaint( & ps );
//do some drawing
EndPaint( & ps );
为避免要记住获取和释放设备描述表时需要调用的函数(并且为了确保在使用设备描述表的消息处理程序结束时设备描述表能合理的被释放)MFC提供了CDC派生类,具体如下:

专门用途的设备描述表类
类名描述
 CPaintDC 用于在窗口客户区画图(仅限于OnPaint处理程序)
 CClientDC 用于在窗口客户区画图(除了OnPaint以外的任何程序中)
 CWindowDC 用于在窗口内任意地方画图,包括非客户区
 CMetaFileDC 用于向GDI原文件画图

这些类在设计的时候可直接进行实例化(类是事物的抽象封装,对象是类的具体化)各个类的构造函数和析构函数调用相应的函数捕获和释放设备描述表,从而使得设备描述表的使用非常方便:

CPaintDC dc(this);//该参数传给CPaintDC的类构造函数,确定设备描述表所属的窗口
//do some drawing
当在栈上构造设备描述表对象时,若对象的生命周期结束,则它的析构函数会被自动调用。而且析构函数一旦被调用,设备描述表就会被返回给Windows。在堆上用new创建的设备描述表时,一定要注意亲自释放设备描述表。示例如下:

CPaintDC *pDC = new CPaintDC (this);//堆上创建指向CPaintDC的对象指针
delete pDC;
CPaintDC类
MFC的CPaintDC类响应WM_PAINT消息,允许在窗口客户区画图。但是,需要注意。我们只能在OnPaint处理程序中使用,不能再其他别的地方应用。WM_PAINT消息有一点与其他Windows消息都不同。如果处理程序调用Windows的::BeginPaint()和::EndPaint函数失败,那么不管有多少绘图工作,都不能将该消息从消息队列中删除。因此,应用程序讲一遍又一遍的处理同一个WM_PAINT消息,这不就陷入死循环了吗?而通过分别从CPaintDC的构造函数和析构函数中调用::BeginPaint和::EndPaint,CPaintDC能保证陷入死循环这种事不发生!

CClientDC和CWindowDC类

Windows程序不是总将绘图限制在OnPaint上,如果编写一个应用程序,只要以单击鼠标吗,应用程序就在屏幕上画一个圆饼,那么我们就希望在接收到按钮单击消息时就立刻画圆,而不必刻意的去等待WM_PAINT消息。这就是CClientDC存在的价值。CClientDC创建了可以在OnPaint外使用的用户区域设备描述表。下面示例程序使用了CClientDC创建了两个CDC成员函数,来完成了在鼠标左键被单击时画一个X链接串口客户区四角的功能。

void CMainWindow::OnButtonDown( UINT nFlag, CPoint point){
CRect rect;
GetClientRect( & rect );CClientDC dc(this);//传递当前窗口指针
dc.MoveTo(rect.left,rect.top);
dc.LineTo(rect.right,rect.bottom);
dc.MoveTo(rect.right,rect.top);
dc.LineTo(rect.left,rect.bottom);
}
如果我们不仅想使用窗口客户区,还用使用非客户区(标题栏,窗口边框等),这就需要使用CWindowDC类。比如,我们想自己绘制标题栏和带圆角的窗口,大多数情况下CWindowDC并不常用。因为如果我们想在窗口非客户区作图,可以借助OnNcPaint处理程序捕捉WM_NCPAINT消息。

3.设备描述表属性

下面总结一下设备描述表中最常用的属性和访问这些属性所用的CDC函数:

主要的设备描述表属性
AttributeDefaultSet withGet with
文本颜色BlackCDC::SetTextColorCDC::GetTextColor
背景颜色WhiteCDC::SetBkColorCDC::GetBkColor
背景模式OPAQUECDC::SetBkModeCDC::GetBkMode
映射模式MM_TEXTCDC::SetMapModeCDC::GetMapMode
绘图模式R2_COPYPENCDC::SetROP2CDC::GetROP2
当前位置(0,0)CDC::MoveToCDC::GetCurrentPosition
当前画笔BLACK_PENCDC::SelectObjectCDC::SelectObject
当前画刷WHITECDC::SelectObject
CDC::SelectObject
当前字体SYSTEM_FONTCDC::SelectObject
CDC::SelectObject











毫无疑问,对于Windows编程的新手来说,GDI编程中最困难的部分就是映射模式(mapping mode)。映射模式用于确定从逻辑坐标值到设备坐标值的转换方式。传送给CDC输出函数的是逻辑坐标值。设备坐标值是指窗口相应的像素点位置。调用dc.Rectangle(0,0,200,200)函数是,不知告诉GDI画一个200个像素点宽、100个像素点高的矩形,而是告诉它画一个200个单位宽、100个单位高的矩形。在默认映射模式MM_TEXT下,一个像素点钱钱相当于一个单位。

这篇关于戏说 Windows GDI (1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/445383

相关文章

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Windows的CMD窗口如何查看并杀死nginx进程

《Windows的CMD窗口如何查看并杀死nginx进程》:本文主要介绍Windows的CMD窗口如何查看并杀死nginx进程问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows的CMD窗口查看并杀死nginx进程开启nginx查看nginx进程停止nginx服务

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

windows系统上如何进行maven安装和配置方式

《windows系统上如何进行maven安装和配置方式》:本文主要介绍windows系统上如何进行maven安装和配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. Maven 简介2. maven的下载与安装2.1 下载 Maven2.2 Maven安装2.

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

Windows Server 2025 搭建NPS-Radius服务器的步骤

《WindowsServer2025搭建NPS-Radius服务器的步骤》本文主要介绍了通过微软的NPS角色实现一个Radius服务器,身份验证和证书使用微软ADCS、ADDS,具有一定的参考价... 目录简介示意图什么是 802.1X?核心作用802.1X的组成角色工作流程简述802.1X常见应用802.

windows和Linux安装Jmeter与简单使用方式

《windows和Linux安装Jmeter与简单使用方式》:本文主要介绍windows和Linux安装Jmeter与简单使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows和linux安装Jmeter与简单使用一、下载安装包二、JDK安装1.windows设