HDC,CDC,CClientDC,CPaintDC,CWindowDC的区别

CDC是MFC的DC的一个类
HDC
是DC的句柄,API中的一个类似指针的数据类型.
MFC
类的前缀都是C开头的

H
开头的大多数是句柄

首先说一下什么是DC(设备描述表)
解:Windows应用程序通过为指定设备(屏幕,打印机等)创建一个设备描述表(Device Context, DC)在DC表示的逻辑意义的“画布”上进行图形的绘制。DC是一种包含设备信息的数据结构,它包含了物理设备所需的各种状态信息。Win32程序在绘制图形之前需要获取DC的句柄HDC,并在不继续使用时释放掉。

在c++ 编程中常会见到HDC,CDC,CClientDC,CPaintDC,CWindowDC这样的类
HDC
是DC的句柄,API中的一个类似指针的数据类型.
CDC
是MFC的DC的一个类
CDC
等设备上下分类,都含有一个类的成员变量:m_nHdc;即HDC类型的句柄.


CDC及其派生类的继承视图:
CObject
public |------CDC
public |------|------CClientDC
public |------|------CPaintDC
public |------|------CWindowDC
public |------|------CMetaFileDC
(
注意: 除CMetaFileDC以外的三个派生类用于图形绘制.)


CDC类定义了一个设备描述表相关的类,其对象提供成员函数操作设备描述表进行工作,如显示器,打印机,以及显示器描述表相关的窗口客户区域。

通过CDC的成员函数可进行一切绘图操作。CDC提供成员函数进行设备描述表的基本操作,使用绘图工具,选择类型安全的图形设备结构(GDI),以及色彩,调色板。除此之外还提供成员函数获取和设置绘图属性,映射,控制视口,窗体范围,转换坐标,区域操作,裁减,划线以及绘制简单图形(椭圆,多边形等)。成员函数也提供绘制文本,设置字体,打印机换码,滚动,处理元文件。

 

其派生类:
1.PaintDC:
封装BeginPaint和EndPaint两个API的调用。
(1)
用于响应窗口重绘消息(WM_PAINT)是的绘图输出。
(2)CPaintDC
在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。
(3)CPaintDC也只能用在WM_PAINT消息处理之中。


2.CClientDC(客户区设备上下文): 处理显示器描述表的相关的窗体客户区域。
用于客户区的输出,与特定窗口关联,可以让开发者访问目标窗口中客户区,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC。


3.CWindowDC: 处理显示器描述表相关的整个窗体区域,包括了框架和控 件(子窗体)。
(1)
可在非客户区绘制图形,而CClientDC,CPaintDC只能在客户区绘制图形。
(2)
坐标原点是在屏幕的左上角,CClientDC,CPaintDC下坐标原点是在客户区的左上角。
(3)
关联一特定窗口,允许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种DC同WM_NCPAINT消息一起发送。


4.CMetaFileDC: 与元文件相关的设备描述表关联。

 

CDC提供两个函数,GetLayout和SetLayout用于反转设备描述表的布局。用于方便阿拉伯,希伯来的书写文化习惯的设计,以及非欧洲表中的字体布局。

CDC包含两个设备描述表,m_hDC和m_hAttribDC对应于相同的设备,CDC为m_hDC指定所有的输出GDI调用,大多数的GDI属性调用由m_hAttribDC控制。(如,GetTextColor是属性调用,而SetTextColor是一种输出调用。)

 

下面用一些简单的代码看看如果使用这些类
HDC
使用, 每次画线等操作都不MFC封装的类多了个HDC的参数
执行在哪个设备描述表操作
HDC hdc=::GetDC(m_hWnd);//m_hWnd == this->m_hWnd
即当前窗口句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc);//
必须和GetDC配对
可以看到HDC的使用较麻烦, 而且如果::GetDC和::ReleaseDC不配对的话,会造成错误


CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);

CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

CWindowDC dc(this);
CWindowDC dc2(GetDesktopWindow());//
获得整个桌面的句柄, 一些桌面特效程序使用
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

CPaintDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

可以看到 MFC 的类使用方便很多, 因为它们都在构造函数和析构函数调用了响应的函数进行DC的获取和释放.


下面说下一些细点的知识点
CClientDC,CWindowDC
区别不大, 可以说 CWindowDC包含了CClientDC 就拿记事本来说
CClientDC 就只是白白的我们可以编辑文字的那个区域是 客户区
CWindowDC
除了上面说的白白区域, 还包括菜单栏和工具栏等

CClientDC和CWindowDC 与 CPaintDC 的区别大点
在DC的获取方面 CClientDC和CWindowDC 使用的是并只能是 GetDC 和 ReleaseDC
CPaintDC 使用的是并只能是 BeginPaint 和 EndPaint

CPaintDC 只能用在响应 WM_PAINT 事件
CClientDC,CWindowDC
只能用在响应 非WM_PAINT 事件


关于 WM_PAINT 事件
系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。


系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过InvalidateRect和InvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindow和RedrawWindow。UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给我们更多的控制:是否重画非客户区和背景,是否总是发送WM_PAINT消息而不管Update Region是否为空等。

 

 

相互转换:


方法一: 此方法在设备结束时不会销毁原来的资源(即:hDC,hBitmap)
CDC *pDC = CDC::FromHandle(hDC);


方法二: 此方法在设备结束时会销毁原来的资源(即:hDC,hBitmap)
CDC dc;
dc.Attach(hDC);

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/407803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转]经典的C语言著作,“C语言四书五经”

http://blog.chinaunix.net/u/22520/showart_308803.html 经典的C语言著作,“C语言四书五经”一、The C Programming Language C程序设计语言(第2版新版) 原出版社: Prentice Hall PTR 作者: [美]Brian W.Kernighan,De…

d3.js(相当于svg的JQ)

学习文档 https://d3js.org/ 官网 https://github.com/xswei/d3js_doc/tree/master/d3js_doc_old 中文文档 https://www.cnblogs.com/fastmover/p/7779660.html 学习demo

Taro+react开发(10)--多行选择

<Pickermode"multiSelector"onChange{this.multiChange}onColumnChange{this.columnChange}value{code}range{multiArray}range-key"code"><AtList><AtListItem title"三级级联" extraText{this.state.scaleSel} /></AtLis…

INI文件读写--VC6.0

新建一个dialog based MFC Windows Application,命名为&#xff1a;d, 界面为&#xff1a; 为按钮Read和Write添加单击事件&#xff0c;并自定义一个函数GetIniFileName()用来取得ini文件的路径&#xff0c;主要函数代码如下&#xff1a;// read data from config file void CD…

TS入门教程

https://ts.xcatliu.com/introduction/what-is-typescript.html 学习地址

SQL SERVER2000教程-第二章-创建和管理数据库 第六节 压缩数据库

有时&#xff0c;人们可能为预期有一定程度活动的数据库分配了太多的空间&#xff0c;当意识到分配了太多空间时&#xff0c;可能决定压缩分配的空间大小。SQLSERVER提供三种可以压缩数据库大小的方法&#xff0c;autoshrink数据库选项&#xff0c;“企业管理器”和“数据库一致…

Taro+react开发(11)--不能加分号

this.setState({scaleSel: selectorScale[Number(e.detail.value)].name,companySize: code});

访问远程mysql数据库

使用mysql命令窗口模式/工具&#xff0c;比如需要给10.2.9.239 的用户分配mantis123,mantis123访问&#xff0c;则使用如下格式&#xff1a; GRANT ALL PRIVILEGES ON *.* TO mantis12310.2.9.239 IDENTIFIED BY mantis123 WITH GRANT OPTION; 会在mysql里面user表中生成一条授…

逗号表达式的值--最后一项的值

C code: #include <stdio.h> void main(){ int i 2; int cc -1; cc (34, 1-2, 5*2); printf("cc %d/n", cc);} 运行结果&#xff1a; cc 10 注意&#xff1a;逗号表达式一定要加括号&#xff0c;要不然&#xff0c;表达式会被理解为&#xff1a; 1. …

练习git小游戏

https://learngitbranching.js.org/?localezh_CN 用来练习Git的小游戏

Taro+react开发(12)--注意引入user

export const addOrUpdateCurrentUserCompany data > {return request.post1(${user}/ua/customer/company/addOrUpdateCurrentUserCompany,data,"POST"); };

WPA加密

WPA加密即:Wi-Fi Protected Access&#xff0c;其加密特性决定了它比WEP更难以入侵&#xff0c;所以如果对数据安全性有很高要求&#xff0c;那就必须选用WPA加密方式了&#xff08;Windows XP SP2已经支持WPA加密方式&#xff09;。 WPA是目前最好的无线安全加密系统&#xff…

linux apache 配置fastcgi

Redhat 上 FastCGI 安装与配置 软件包 相关软件包:httpd 2.2.14 //注意版本 这个版本不会出问题 注&#xff1a;apache httpd安装 fcgi-2.4.0.tar.gz mod_fastcgi-2.4.6.tar.gz 请仔细阅读其中的README 配置httpd.conf 尾部添加 &#xff1a; LoadModule fastcgi_…

Taro+react开发(13)--多加/不然不能跳转

Taro.navigateTo({url: /pages/companyIntroDetail/index});

安装VS2010旗帜版,出现“某些组件必须安装在 目录下,请检查是否有足够的写入权限以及足够的空间”

安装VS2010旗帜版时&#xff0c;我用的安装文件是一个ISO文件&#xff0c;用虚拟光驱加载的&#xff0c;但是在安装时却出现了错误&#xff1a;“某些组件必须安装在 目录下&#xff0c;请检查是否有足够的写入权限以及足够的空间”&#xff1f;这可怎么办呢&#xff1f; 我试着…

git黑窗口需要你插入,如何下一步

当git黑窗口提示需要你插入字符下一步是&#xff0c;在最下方输入&#xff1a;wq即可

C#下实现在线升级

//这是一个webserviceprivateAppUpdate.UpdateServ UpdateSvr;privatevoidbutton1_Click(objectsender, System.EventArgs e){ if(LinkWebServices()true){this.label1.Text&quot;连接服务器. PASS&quot;;if(CheckVer()true){this.label2.Text&quot;检查最新版本并…

客户端版本和服务器版本上传软件

FileZilla是一个免费开源的FTP软件&#xff0c;分为客户端版本和服务器版本&#xff0c;具备所有的FTP软件功能。可控性、有条理的界面和管理多站点的简化方式使得Filezilla客户端版成为一个方便高效的FTP客户端工具&#xff0c;而FileZilla Server则是一个小巧并且可靠的支持F…

C语言的Trim, LTrim, RTrim

抽空写了个C语言的Trim(), LTrim(), RTrim()&#xff0c;代码如下&#xff1a; #include <iostream>using namespace std;char * LTrim(char * line) // 去除字符串最前面的空格符 {while(isspace(*line))line;return line;}char * RTrim(char * line) // 去除…

一个Ext2+SWFUpload做的图片上传对话框

一个Ext2SWFUpload做的图片上传对话框的例程我们先看看对话框的布局&#xff1a; 布局就是在一个窗口里内嵌一个表格控件&#xff0c;窗口的底部工具条带一个进度条&#xff0c;表格的顶部工具条带几个操作按钮和一个下来选择框&#xff0c;底部工具条作为一个信息显示区域显示…