戏说 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

相关文章

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

Windows下Nginx的安装及开机启动

1、将nginx-1.16.1.zip解压拷贝至D:\web\nginx目录下。 2、启动Nginx,两种方法: (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过。 (2)打开cmd命令窗口,切换到nginx目录下,输入命令 nginx.exe 或者 start nginx ,回车即可。 3、检查nginx是否启动成功。 直接在浏览器地址栏输入网址 http://lo

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

C++实现俄罗斯方块(Windows控制台版)

C++实现俄罗斯方块(Windows控制台版) 在油管上看到一个使用C++控制台编写的俄罗斯方块小游戏,源代码200多行,B站上也有相关的讲解视频,非常不错,值得学习。 B站讲解视频地址为:【百万好评】国外技术大神C++游戏编程实战教程,油管580W收藏,新手10小时入门,并快速达到游戏开发能力(中英字幕) B站 CSDN博主千帐灯无此声还为此写了一篇博客:C++实现俄罗斯方块(源码+详解),讲

Windows下php扩展开发c++动态库

PHP扩展开发,从零了解到初步完成一个小项目,经过三天的仔细研究,现整理如下 一、需求介绍 PHP扩展开发,调用自己之前的c++动态库,完成功能 二、项目之前 系统:windows xp  开发工具:vs 2008 web环境:apache2.4  PHP5.3.29-VC9-ts-x86 aphach和PHP 环境之前已经搭建完成 PHP源码:去官网http://www.php.n

OpenStack镜像制作系列4—Windows Server2019镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录  CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系

Windows与linux中docker的安装与使用

windos中安装使用docker 下载Docker_Desktop 安装包进入docker官网下载Docker_Desktop: https://www.docker.com/ 启用wsl 我们搜索“启用或关闭Windows功能”,打开后勾选适用于Linux的Windows 子系统 Docker_Desktop设置 出现Docker Engine stopped的解决

Windows 10 各版本

对应于服务选项的 Windows 10 当前版本 Version服务选项上市日期OS build最后修订日期1803半年频道7/10/201817134.1917/24/2018Microsoft 建议使用1803半年频道(定向)4/30/201817134.1917/24/20181709半年频道1/18/201816299.5797/24/20181709半年频道(定向)10/17/2017

Windows系统不关机故障的解决方法

当Windows系统出现不关机故障时,首先要查找引起Windows系统不关机的原因,然后根据 具体的故障原因采取相应的解决方法。   Windows系统不关机故障的解决方法如下。   1.检查所有正在运行的程序   检查运行的程序主要包括关闭任何在实模式下加载的TSR程序、关闭开机时从启动组自动启 动的程序、关闭任何非系统引导必需的第三方设备驱动程序。   检查运行的程序并停