`
tibaloga
  • 浏览: 865385 次
文章分类
社区版块
存档分类
最新评论

VC/MFC的HDC,CDC,CWindowDC,CClientDC,CPaintDC详解:

 
阅读更多

VC/MFC的HDC,CDC,CWindowDC,CClientDC,CPaintDC详解:

首先说一下什么是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是否为空等。


分享到:
评论

相关推荐

    VC_MFC的HDC,CDC,CWindowDC,CClientDC,CPaintDC详解

    VC_MFC的HDC,CDC,CWindowDC,CClientDC,CPaintDC详解

    MFC中的CDC,CClientDC,CPaintDC,CWindowDC的区别

    MFC中的CDC,CClientDC,CPaintDC,CWindowDC的区别_针对初学者的一些概念。

    stdafx.h代码

    // a Display Context / HDC wrapper class CClientDC; // CDC for client of window class CWindowDC; // CDC for entire window class CPaintDC; // embeddable BeginPaint struct helper class CMenu; // ...

    MFC简单绘图实现代码

    非常适合初学者的学习。 讲述了MFC绘图最基本的一些方法: 用SDK全局函数实现绘制线条,用类,类,CWindowDC类分别,以及画刷,位图画刷,透明画刷的使用方法。

    VC++6.0画图程序

    VC++6.0 画图 CDC CClientDC CWindowDC对比

    基于GDI绘图各种DC的使用

    在vs2008下,基于GDI使用各种DC绘制一个电子签名源码

    EVC图形编程 设备环境类 图形绘制函数 图形对象类

    1. MFC介绍 ...2. 设备环境类(CDC、CPaintDC、CWindowDC、CClientDC) 3. 设备描述表属性 4. 各种图形的绘制(文本、直线、折线、圆、矩形、圆角矩形等) 5. 图形对象类(画笔、画刷、字体、位图类)

    在视图中使用CWindowDC在整个窗口进行绘图

    在视图中使用CWindowDC在整个窗口进行绘图,希望对您有所帮助

    MFC类库详解中文版(chm)

    MFC类目录及头文件 类 描述 头文件 CAnimateCtrl 自动化通用控件 afxcmn.h CArchive afx.h CArchiveException afx.h CArray afxtempl.h CAsyncMonikerFile 在ActiveX控件中提供对异步标记的支持 afxole.h ...

    CWindowDC.zip_CWindowDC

    实例147——在视图中使用CWindowDC在整个窗口进行绘图

    Visual C++ 6.0编程实例详解.part1

    6.2.4 用类CWindowDC管理框架窗口 6.2.5 具有类CMetaFileDC的Windows元文件 6.3 GDI对象 6.3.1 类型 6.3.2 构造 6.3.3 选择 6.3.4 表示和使用颜色 6.4 画笔 6.4.1 分类 6.4.2 创建CPen...

    Visual C++ 6.0编程实例详解.part2

    6.2.4 用类CWindowDC管理框架窗口 6.2.5 具有类CMetaFileDC的Windows元文件 6.3 GDI对象 6.3.1 类型 6.3.2 构造 6.3.3 选择 6.3.4 表示和使用颜色 6.4 画笔 6.4.1 分类 6.4.2 创建CPen...

    新一代 Visual C++2005程序设计 part2

    13.3 CWindowDC与CClientDC 304 13.4 画笔与画刷 305 13.5 基本绘图函数 308 13.6 色彩与调色板 312 13.7 使用调色板 316 13.8 字体与文本输出 318 13.9 示例:时钟 330 第14章 位图 336 14.1 简介 336 14.2...

    Visual.C#2010从入门到精通

    8.2.3 CClientDC类 125 8.2.4 CWindowDC类 126 8.3 GDI对象 127 8.3.1 GDI对象的种类 127 8.3.2 GDI对象的生命周期 127 8.4 绘制图形 129 8.4.1 绘制线条 130 8.4.2 绘制矩形 131 8.4.3 绘制椭圆 132 8.4.4 其他绘图...

    desktopimage_settlersnj8_Cimage截屏窗口中显示保存文件_

    vs2017 c++ mfc利用CimageDC 类 截屏显示保存文件 CWindowDC winDC(pWnd); pWnd->GetWindowRect(&rect); int nBPP = winDC.GetDeviceCaps(BITSPIXEL) * winDC.GetDeviceCaps(PLANES); if (nBPP < 24) { ...

    《Visual C++范例大全》随书光盘 第七章

    实例145——在视图中使用CDC进行绘图操作 实例146——在视图中使用CPaintDC进行进行窗口重绘操作 实例147——在视图中使用CWindowDC在整个窗口进行绘图 实例148——在对话框窗口中进行绘图操作 实例149——创建...

    用C++重写窗口的标题栏

    今天因为呆在家里没有事干就随便弄了个自定义标题栏,在WM_NCPAINT WM_NCACTIVATE的消息中用CWindowDC 重绘了窗口; 还要在WM_NCHITTEST当中过滤HTCLOSE返回值。

Global site tag (gtag.js) - Google Analytics