首页 > 编程语言 >【MFC编程(四)】图形图像:CDC类与GDI绘图

【MFC编程(四)】图形图像:CDC类与GDI绘图

时间:2024-11-08 13:15:11浏览次数:6  
标签:MFC CDC int 图形图像 绘图 坐标 GDI 矩形 设备描述

文章目录


绘图引擎简介

Windows环境下二维绘图引擎有多种选择:GDI、GDI+、DirectDraw、Qt/QPainter、Agg、Cairo、skia、Direct2D、Direct3D、OpenGL、Vulkan等。

  • GDI:微软原生的二维绘图引擎。
    优点:微软的全力支持,作为操作系统核心层效率方面不用担心,支持多种开发框架(含语言):WinSDK、MFC、Delphi等。
    缺点:不是面向C++对象组织的,使用起来较为繁琐;不支持反锯齿,不支持复杂的绘图效果(这个相对于GDI+而言)。

  • GDI+/GdiPlus:微软后来推出的二维绘图引擎。
    优点:微软的全力支持,支持多种开发框架(含语言):WinSDK、MFC、Delphi等,可以实现复杂的绘图效果,如反锯齿、路径画刷等;面向对象的架构,使用起来比较方便。
    缺点:绘图效率较GDI稍低,绘图交互性不如GDI(缺少GDI的支持位运算的绘图模式),开启反锯齿后效率不如Qt。如果不考虑绘图的效果,使用Win32 GDI函数直接绘图的效率大约是同样的GDI+的10倍以上。

  • DirectDraw:从GDI、GDI+到Direct 2D的一个过渡产品,微软已明确表示不推荐使用。

  • Direct2D:微软在WindowsVista及之后的Windows版本推出的意在取代GDI、GDI+的二维绘图引擎,支持硬件加速。Direct 2D是微软在后XP时代开发的开发二维绘图引擎。微软出于兼容性的考虑还会继续对GDI、GDI+进行支持,但毫无疑问微软的策略是要Direct 2D取代GDI和GDI+的,因此在WindowsVista及其之后的Windows上进行二维绘图开发,建议是直接使用Direct2D。Direct 2D支持硬件加速,在绘图效率应有一定程度的提升。

  • Direct3D:微软开发的3D绘图引擎。

    DirectX(Direct eXtension,简称DX)是由微软公司创建的多媒体编程接口,也是一种应用程序接口(API)。它可以让以Windows为平台的游戏或多媒体程序获得更高的执行效率,加强3D图形和声音效果,并提供设计人员一个共同的硬件驱动标准。这样,游戏开发者不必为每一品牌的硬件来写不同的驱动程序,同时也降低了用户安装及设置硬件的复杂度。
    DirectX已被广泛使用于Microsoft Windows、Microsoft XBOX、Microsoft XBOX 360和Microsoft XBOX ONE电子游戏开发。其主要包括多个组件,如Direct3D(3D图形渲染)、DirectSound(音频处理)、DirectInput(输入设备管理)等,以满足不同的多媒体应用需求。

  • OpenGL:SGI开发的3D绘图引擎。OpenGL的优势是三维绘图,不建议用来二维绘图,因为OpenGL在二维一些操作并不合适,如二维中的点、线捕捉、自定义图例的添加、打印的支持等等。
    作为图形渲染API,OpenGL和Direct3D的全方位对比
    在这里插入图片描述

  • Vulkan:Vulkan是一个跨平台的2D和3D绘图应用程序接口。同 OpenGL一样,Vulkan也由 Khronos 集团开发。它是 AMD Mantle 的后续版本,继承了前者强大的低开销架构,使软件开发人员能够全面获取 RadeonGPU 与多核 CPU 的性能、效率和功能。Linux上Vulkan是OpenGL的指定接班人。

  • Qt:Qt的二维图形引擎是基于QPainter类的,绘图的效果取决于QPainter的设置。面向对象的方式组织,使用起来较为方便。

  • Cairo:C编写的开源绘图引擎(基于LGPL协议),大名鼎鼎的FireFox就是用这个绘图引擎的。Cairo是非常流行的开源2D图形渲染引擎库,它支持包括X-Windos,Win32,图像,pdf在内的各种输出设备。目前,Cairo已被广泛的使用在多个平台上来渲染图形界面,包括Firefox/Webkit-EFL/GTK+/Poppler/Qt等等。GTK+底层的绘图引擎就是使用Cairo。Qt的QPainter提供的抗锯齿效果没有cairo的好,在理想情况下,cairo的用户可以在打印机和屏幕上获得非常接近的输出效果。cairo 是用 C 编写的,但是为大多数常用的语言提供了绑定。选用 C 语言有助于创建新的绑定,同时在进行 C 语言调用时可以提供高性能。应该特别注意 Python 绑定,它支持快速原型开发,而且降低了学习 cairo 绘图 API 的门槛。 Cairo的绘图效率是接近GDI/GDIPlus的。经过优化算法,可以做到完全忽略绘图效率上的差别。此外,gtk不如qt流行,Qt支持cairo。

  • Skia:Google的Android的绘图引擎。它是一个C++的开源2D向量图形处理函数库,包括字型、坐标转换、位图等等,相当于轻量级的Cairo(Cairo是矢量图形库)。

  • angle:Google宣布了新的开源项目 ANGLE (全称 Almost Native Graphics Layer Engine),这个项目的目标是在 Direct X 9.0c API 的基础上实现一层 OpenGL ES 2.0 API中 的 Web GL 子集接口。在开发的早期,ANGLE 项目将使用 BSD 授权发布,而最终完成后,类似 Google Chrome 之类的浏览器在 Windows 平台上运行 WebGL 内容将不再依赖于任何的 OpenGL 驱动程序。

GDI绘图

GDI(Graphics Device Interface,图形设备接口)
Windows API的一个库。 其相关的函数接口、数据类型等都在WinGDI.h中声明(已经由Windows.h引入),在程序开发时,需要链接到Gdi32.lib。

它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。当Windows应用程序需要显示点、线、图像、文字等内容,在显示器或打印输入这些内容时,就需要用到GDI。Windows应用程序不能直接操作系统的硬件(比如显卡),GDI就为应用程序提供了相关的接口。

GDI是如何实现输出的
要想在屏幕或者其它输出设备上输出图形或者文字,那么我们就必须先获得一个称为设备描述表DC的对象的句柄,以它为参数,调用各种GDI函数实现各种文字或图形的输出。设备描述表DC是GDI内部保存数据的一种数据结构,此结构中的属性内容与特定的输出设备(显示器,打印机等)相关,属性定义了GDI函数的工作细节。

DC设备上下文

GDI库中最基本也是最重要的概念。

DC(Device Contexts)设备上下文又称为设备描述表,或者设备环境。 是一个定义一组图形对象及其属性、影响输出的图形方式(数据)结构。Windows提供设备描述表,用于应用程序和物理设备之间进行交互,从而提供了应用程序设计的平台无关性。

设备描述表是一种数据结构,它包括了一个设备(如显示器和打印机)的绘制属性相关的信息。所有的绘制操作通过设备描述表进行。设备描述表与大多 WIN32结构不同,应用程序不能直接访问设备描述表,只能由各种相关API函数通过设备描述表的句柄间接访问该结构。

  • 设备描述表总是与某种系统硬件设备相关。比如屏幕设备描述表与显示设备相关,打印机设备描述表与打印设备相关等等。

  • 屏幕设备描述表,一般我们简单地称其为设备描述表。它与显示设备具有一定的对应关系,在windows GDI界面下,它总是相关与某个窗口或这窗口上的某个显示区域。通常意义上窗口的设备描述表,一般指的是窗口的客户区,不包括标题栏、菜单栏所占有的区域,而对于整个窗口来说,其设备描述表严格意义上来讲应该称为窗口设备描述表,它包含窗口的全部显示区域。二者的操作方法完全一致,所不同的仅仅是可操作的范围不同而已。

  • Windows窗口一旦创建,它就自动地产生了与之相对应的设备描述表数据结构,用户可运用该结构,实现对窗口显示区域的GDI操作,如划线、写文本、绘制位图、填充等,并且所有这些操作均要通过设备描述表句柄了进行。

系统中可以有多个DC,每一个DC都必须关联到一个特定的图像输出设备。这些设备可以是真实存在的物理设备(显示器、打印机、绘图仪等),也可以使虚拟设备。这些反应在DC的类型上, DC具有4种类型:“显示”、“打印机”、“内存”、“信息”。
其中显示类型DC是最常用的,它被关联到了显示设备上,所有的图像输出操作将直接反映在显示器上。
注:DC也可以只是设备全部输出范围的一部分。比如界面上某个窗口的客户区也可以有DC与之对应,对这样的DC进行操作只会影响到窗口客户区。

  • Common设备描述表通过::GetDC::GetDCEx::BeginPaint来获得一个设备描述表,用毕,用::ReleaseDC::EndPaint释放设备描述表;
  • Printer设备描述表通过::CreateDC创建设备描述表,用::DeleteDC删除设备描述表。
  • Memory设备描述表通过::CreateCompatibleDC创建设备描述表,用::DeleteDC删除。
  • Information设备描述表通过::CreateDC创建设备描述表,用::DeleteDC删除

要使用设备描述表,一般有如下步骤:

  1. 获取或者创建设备描述表;
  2. 必要的话,改变设备描述表的属性;
  3. 使用设备描述表完成绘制操作;
  4. 释放或删除设备描述表。

CDC类

CDC类提供了用来处理显示器或打印机等设备上下文的成员函数,还有处理与窗口客户区关联的显示上下文的成员函数。使用CDC的成员函数可以进行所有的绘图操作,包括处理绘图工具、GDI对象的选择、颜色和调色板的处理、获取和设置绘图属性、映射、窗口范围、坐标转换、剪切以及绘制直线、简单图形、椭圆和多边形等,另外它还为文本输出、处理字体、使用打印机跳转和滚动等提供了成员函数。

如上所述,CDC类几乎封装了所有的Windows GDI函数,另外,MFC中还有几个由CDC类派生的子类,包括CWindowDC、CPaintDC、CClientDC、CMetaFileDC,它们用来进行一些特定的绘图操作。
在这里插入图片描述
很多情况下我们可以调用CWnd::GetDC()函数来获取设备上下文指针,即CDC指针,这个时候记得用完后调用CWnd::ReleaseDC()函数释放设备上下文。

CCientDC
代表窗口客户区的设备描述表。其构造函数CClientDC(CWnd *pWin)通过::GetDC获取指定窗口的客户区的设备描述表HDC,并且使用成员函数Attach把它和CClientDC对象捆绑在一起;其析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用::ReleaseDC释放设备描述表HDC。

CPaintDC
仅仅用于响应WM_PAINT消息时绘制窗口,因为它的构造函数调用了::BeginPaint获取设备描述表HDC,并且使用成员函数Attach把它和CPaintDC对象捆绑在一起;析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用::EndPaint释放设备描述表HDC,而::BeginPaint和::EndPaint仅仅在响应WM_PAINT时使用。

CMetaFileDC
用于生成元文件。

CWindowDC
代表整个窗口区(包括非客户区)的设备描述表。其构造函数CWindowDC(CWnd *pWin)通过::GetWindowDC获取指定窗口的客户区的设备描述表HDC,并使用Attach把它和CWindowDC对象捆绑在一起;其析构函数使用Detach把设备描述表HDC分离出来,调用::ReleaseDC释放设备描述表HDC。

HDC和CDC的区别与转换

  • HDC是WINDOWS的一种数据类型,是设备描述句柄。
    HDC定义的变量指向一块内存,这块内存用来描述一个设备的相关的内容,所以也可以认为HDC定义的是一个指针
  • CDC是MFC里的一个类,它封装了几乎所有的关于HDC的操作。
    CDC类定义一个对象,这个对象拥有HDC定义的一个设备描述表,同时也包含与HDC相关的操作的函数。

CDC *pDCHDC hdc 类似 CWnd *pWndHWnd hWnd

获得CDC

CDC *pDC=new CDC; 
pDC=GetDC();	//1
pDC->Attach(hdc);	//2 hdc转换

获得HDC

HDC hDC;
hDC = ::GetDC(HWND handle); //1
	
hDc = pDC->GetSafeHdc(); //2
	
hDC = pDC->m_hDC;	//3

屏幕绘图成员函数

CDC类有很多成员函数,比较常用的绘图函数包括绘制点、直线、矩形、椭圆、多边形、文本以及位图等的成员函数。

绘制点

	COLORREF SetPixel(int x,int y, COLORREF crColor);
	COLORREF SetPixel(POINT point, COLORREF crColor);

上面两个成员函数用来将指定坐标点的像素设置为指定的颜色,这样就实现了画点功能。

  • 参数x为点的逻辑x坐标;
  • 参数y为点的逻辑y坐标;
  • 参数crColor为要为点设置的颜色;
  • 参数point指定点的逻辑x坐标和逻辑y坐标,可以为其传入POINT结构体变量或者CPoint对象。
	CPoint MoveTo(int x,int y);
	CPoint MoveTo(POINT point);

将当前点移动到指定位置。

  • 参数x指定新位置的逻辑x坐标;
  • 参数y指定新位置的逻辑y坐标;
  • 参数point指定新位置的逻辑x坐标和逻辑y坐标,可以为其传入POINT结构体变量或者CPoint对象。

绘制直线

 	BOOL LineTo(int x,int y);
 	BOOL LineTo(POINT point);

绘制一条从当前点到指定点(不包括指定点)的直线。

  • 参数x为指定点的逻辑x坐标;
  • 参数y为指定点的逻辑y坐标;
  • 参数point为指定点的逻辑x坐标和逻辑y坐标。一般我们绘制直线时就可以先调用MoveTo函数移动当前点到某个位置,然后调用LineTo画直线。

绘制矩形

	BOOL Rectangle(int x1,int y1,int x2,int y2);
	BOOL Rectangle(LPCRECT lpRect);

使用当前画笔绘制矩形。

  • 参数x1指定矩形左上角的x坐标;
  • 参数y1指定矩形左上角的y坐标;
  • 参数x2指定矩形右下角的x坐标;
  • 参数y2指定矩形右下角的y坐标;以上坐标均为逻辑单位。
  • 参数lpRect为矩形对象的指针,可以为其传入CRect对象或RECT结构体变量的指针。

绘制椭圆

	BOOL Ellipse(int x1,int y1,int x2,int y2);
	BOOL Ellipse(LPCRECT lpRect);

绘制椭圆。

  • 参数x1指定椭圆的包围矩形左上角的x坐标;
  • 参数y1指定椭圆的包围矩形左上角的y坐标;
  • 参数x2指定椭圆的包围矩形右下角的x坐标;
  • 参数y2指定椭圆的包围矩形右下角的y坐标;以上坐标均为逻辑单位。
  • 参数lpRect指定椭圆的包围矩形,可以传入CRect对象或RECT结构体变量的指针。

绘制多边形

	BOOL Polyline(LPPOINT lpPoints,int nCount);

由指定的多边形顶点绘制多边形。

  • 参数lpPoints为指向一个POINT结构体变量数组或CPoint对象数组的指针,其中的POINT结构体变量或CPoint对象代表了多边形顶点的坐标;
  • 参数nCount为数组中点的个数,至少为2。

绘制文本

	virtual BOOL TextOut(int x,int y,LPCTSTR lpszString,int nCount);
	BOOL TextOut(int x,int y,const CString& str);

使用当前选择的字体在指定位置输出文本。

  • 参数x指定文本起始点的x坐标;
  • 参数y指定文本起始点的y坐标;
  • 参数lpszString为要输出的文本字符串;
  • 参数nCount指定字符串中的字节个数;
  • 参数str为包含要输出的字符的CString对象。这两个函数在上一节中其实已经讲到了。

绘制位图

   BOOL BitBlt(
          int x,
          int y,
          int nWidth,
          int nHeight,
          CDC* pSrcDC,
          int xSrc,
          int ySrc,
          DWORD dwRop
   );

从源设备上下文拷贝一幅位图到当前设备上下文。

  • 参数x指定目标矩形区域左上角的逻辑x坐标;
  • 参数y指定目标矩形区域左上角的逻辑y坐标;
  • 参数nWidth指定目标矩形区域和源位图的宽度(逻辑单位);
  • 参数nHeight指定目标矩形区域和源位图的高度(逻辑单位);
  • 参数pSrcDC为指向源设备上下文的CDC对象的指针,如果dwRop指定了一个不包含源的光栅操作,那么pSrcDC可以为NULL;
  • 参数xSrc指定源位图左上角的逻辑x坐标;
  • 参数ySrc指定源位图左上角的逻辑y坐标;
  • 参数dwRop指定要执行的光栅操作,光栅操作码定义了GDI如何将当前画刷颜色、源位图颜色和目标位图颜色组合形成新的颜色,下面是一些常用的光栅操作码及含义:
    • BLACKNESS:表示使用与物理调色板的索引0相关的色彩来填充目标矩形区域,(对缺省的物理调色板而言,该颜色为黑色)。
    • DSTINVERT:表示使目标矩形区域颜色取反。
    • MERGECOPY:表示使用布尔型的AND(与)操作符将源矩形区域的颜色与特定模式组合一起。
    • MERGEPAINT:通过使用布尔型的OR(或)操作符将反向的源矩形区域的颜色与目标矩形区域的颜色合并。
    • NOTSRCCOPY:将源矩形区域颜色取反,于拷贝到目标矩形区域。
    • NOTSRCERASE:使用布尔类型的OR(或)操作符组合源和目标矩形区域的颜色值,然后将合成的颜色取反。
    • PATCOPY:将特定的模式拷贝到目标位图上。
    • PATPAINT:通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模式的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并。
    • PATINVERT:通过使用XOR(异或)操作符将源和目标矩形区域内的颜色合并。
    • SRCAND:通过使用AND(与)操作符来将源和目标矩形区域内的颜色合并。
    • SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。
    • SRCERASE:通过使用AND(与)操作符将目标矩形区域颜色取反后与源矩形区域的颜色值合并。
    • SRCINVERT:通过使用布尔型的XOR(异或)操作符将源和目标矩形区域的颜色合并。
    • SRCPAINT:通过使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并。
    • WHITENESS:使用与物理调色板中索引1有关的颜色填充目标矩形区域。(对于缺省物理调色板来说,这个颜色就是白色)。

标签:MFC,CDC,int,图形图像,绘图,坐标,GDI,矩形,设备描述
From: https://blog.csdn.net/qq_39281631/article/details/143487403

相关文章

  • 系统中电源的设计和选择 BOSHIDA acdc电源模块 BAL2.5-5W
    系统中电源的设计和选择BOSHIDAacdc电源模块BAL2.5-5W1.确定所用电源的规格:电源功率电源输出电压,输出端数电源尺寸2.使用标准模块设计系统时,请尽可能使用市场上通用的标准电源模块。这样可缩短设计和开发的时间,提高可靠性。3.尽地减少电源的输出端数一-般很容易买到现成的1......
  • 找不到mfc140u.dll,无法继续执行代码的原因分析与解决方案
    mfc140u.dll是MicrosoftFoundationClasses(MFC)库的一部分,它是VisualStudio2015中的一个重要组件。MFC提供了一组预定义的类和函数,用于简化Windows应用程序的开发过程。mfc140u.dll文件包含了这些类和函数的实现,许多基于MFC开发的应用程序依赖于它来正常运行。......
  • 质子交换膜燃料电池(PEMFC Simulink模型)
        ......
  • VS中MFC如何调用通过C#封装的dll库?
    (1)打开工程属性——配置属性——常规将右侧界面中的MFC的使用一栏改为:在共享DLL中使用MFC(2)同页面中,将字符集改为:使用多字节字符集(3)同页面中,将公共语言运行时支持改为:公共语言运行时支持(/clr)vs2010:vs2022:(4)工程属性——配置属性——C/C++——常规将右侧调试信息格式......
  • MFC的SendMessage与PostMessage的区别
    一、SendMessage同步操作:SendMessage是一个同步函数,它会将消息发送到指定的窗口,并等待该窗口的消息处理过程完成,然后返回。这意味着它会阻塞当前线程,直到消息处理完成。直接调用:SendMessage会将消息直接传递给目标窗口的消息处理函数,因此消息处理函数在当前线程中执行......
  • [Flink/FlinkCDC] 实践总结:Flink 1.12.6 升级 Flink 1.15.4
    FlinkDataStream/API未变的重要特性虽然官宣建议弃用JDK8,使用JDK11+;但:仍继续支持JDK8个人猜测:JDK8的用户群实在太大,牵一发而动全身,防止步子扯太大,遏制自身项目的发展势头。依赖模块的变化版本变化flink.version:1.12.6=>1.15.4flink.connector.version:......
  • 小智桌面遭遇mfc100u.dll加载失败?解决小智桌面因mfc100u.dll缺失导致的加载问题
    在使用小智桌面这款高效、便捷的桌面管理软件时,用户可能会遇到这样一个问题:XZDesktop64.exe在尝试加载mfc100u.dll文件时失败了。这通常意味着系统中缺少了mfc100u.dll这一关键的系统文件,导致小智桌面无法正常运行。本文将详细介绍mfc100u.dll文件的重要性、丢失原因以及多种解......
  • [Flink SQL] FlinkCdcSqlJob启动时因MYSQL serverTimeZone而报错:`The MySQL server ha
    1问题描述FlinkCdcSqlJob启动时报错...Causedby:org.apache.flink.table.api.ValidationException:TheMySQLserverhasatimezoneoffset(0secondsaheadofUTC)whichdoesnotmatchtheconfiguredtimezoneAsia/Shanghai.Specifytherightserver-time-z......
  • ACDC电源模块BAG5-15W系列 双输出电源 BOSHIDA博士达
    ACDC电源模块BAG5-15W系列双输出电源BOSHIDA博士达产品具有以下特点:宽输入电压范围85-265VAC,适用于不同地区的电源电压标准。高效率、高可靠性,保证稳定而可靠的电源输出。空载功耗低,节约能源,减少不必要的电能损耗。隔离电压2500VAC,保证电源的安全性和稳定性。输出过压、过流......
  • XPM_CDC_PULSE
    免责声明:本文所提供的信息和内容仅供参考。作者对本文内容的准确性、完整性、及时性或适用性不作任何明示或暗示的保证。在任何情况下,作者不对因使用本文内容而导致的任何直接或间接损失承担责任,包括但不限于数据丢失、业务中断或其他经济损失。读者在使用本文信息时,应自行验......