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

CDCMFCDC的一个类
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
MFCDC的一个类
CDC
等设备上下分类,都含有一个类的成员变量:m_nHdc;HDC类型的句柄.


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


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

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

 

其派生类:
1.PaintDC:
封装BeginPaintEndPaint两个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)
可在非客户区绘制图形,而CClientDCCPaintDC只能在客户区绘制图形。
(2)
坐标原点是在屏幕的左上角,CClientDCCPaintDC下坐标原点是在客户区的左上角。
(3)
关联一特定窗口,允许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种DCWM_NCPAINT消息一起发送


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

 

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

CDC包含两个设备描述表,m_hDCm_hAttribDC对应于相同的设备,CDCm_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
除了上面说的白白区域, 还包括菜单栏和工具栏等

CClientDCCWindowDC CPaintDC 的区别大点
DC的获取方面 CClientDCCWindowDC 使用的是并只能是 GetDC ReleaseDC
CPaintDC 使用的是并只能是 BeginPaint EndPaint

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


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


系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过InvalidateRectInvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRectInvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindowRedrawWindowUpdateWindow会检查窗口的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.mzph.cn/news/407803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;底部工具条作为一个信息显示区域显示…