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详解:的更多相关文章

  1. VC/MFC中的CComboBox控件使用详解

    CComboBox控件详解 CComboBox控件又称作组合框控件,其有三种形态可供选择,1.简单组合框(Simple)2.下拉组合框(Drop-down)3.下拉列表式组合框(Drop-down l ...

  2. SQL Server 2008 CDC增量变更捕获详解

    1 背景: 随着公司业务的成长,数据量也随之的不断增长.随之而来的问题是在做ETL的时候,时间花费也越来越长.为了节省时间开销,我们只想要更新最新的数据,不想要把公司历年所有的数据都进行处理.这种情况 ...

  3. VC 与Matlab混合编程之引擎操作详解

    Visual C++ 是当前主流的应用程序开发环境之一,开发环境强大,开发的程序执行速度快.但在科学计算方面函数库显得不够丰富.读取.显示数据图形不方便. Matlab 是一款将数值分析.矩阵计算.信 ...

  4. MFC创建动态链接库DLL并调用方法详解

    实例一: 1.创建一个动态链接库工程,如login_dll. 2.在原工程头文件或者新建头文件如showdlg.h定义动态链接库的导出函数,代码如下: #include "stdafx.h& ...

  5. vc中调用Com组件的所有方法详解

    首先,对于Com组件的入门学习,可以看一下<Windows程序设计技术基础——MFC与.NET> 任哲编著的21世纪重点大学规划教材那本书,适合入门(虽然不一定会使用),了解些基础原理. ...

  6. VC++界面编程之--阴影窗口的实现详解

    转载:http://blog.csdn.net/rmxming/article/details/11661365 对于我们这些控件狂来说,窗口阴影也是一个必不可少的实现需求.虽说其没多大用,但对于增加 ...

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

    转自 http://blog.csdn.net/guoquan2003/article/details/4534716 CDC是Windows绘图设备的基类. CClientDC:(1)(客户区设备上 ...

  8. VC/MFC 编程技巧大总结

    1 toolbar默认位图左上角那个点的颜色是透明色,不喜欢的话可以自己改. 2 VC++中 WM_QUERYENDSESSION WM_ENDSESSION 为系统关机消息. 3 Java学习书推荐 ...

  9. VC++ MFC单文档应用程序SDI下调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错原因分析及解决办法:glewInit()初始化的错误

    1.问题症状 在VC++环境下,利用MFC单文档应用程序SDI下开发OpenGL程序,当调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错,出错代码如下: OpenG ...

随机推荐

  1. jq实现批量图片上传

    http://blog.csdn.net/lmj623565791/article/details/31513065 jq实现批量图片上传 http://blog.csdn.net/lmj623565 ...

  2. 【python】python版本升级,从2.6.6升级到2.7.13

    centos6.5系统自带了2.6.6版本的python,有时候为了项目上的需要,需要将python版本升级到2.7.13,下面介绍了如何进行升级. 说明:python从2.6升级到2.7会引发很多问 ...

  3. IOS 长姿势---双击Home键

    这不值得大惊小怪,因为按两次Home键后,苹果只是简单第提供了一个历史任务列表,而不是人们以为的当前任务列表——这在苹果网站上已经说得很清楚了.至于为什么苹果没有能力为用户提供一个“任务管理器”,我们 ...

  4. P3231 [HNOI2013]消毒

    P3231 [HNOI2013]消毒 二维覆盖我们已经很熟悉了 扩展到三维,枚举其中较小的一维,这里定义为$a$ 以$a$为关键字状压,$1$表示该面全选 剩下的面和二维覆盖一样二分图匹配 如果还没接 ...

  5. manacher小结

    P3805 [模板]manacher算法 题目大意 n个字符组成的字符串,求最长回文串 $O$$($$n^3$$)$ 枚举两端点,暴力往中间搜 $O$$($$n^2$$)$ 枚举回文串终点,暴力往两边 ...

  6. 20145239杜文超 《Java程序设计》第3周学习总结

    20145239 <Java程序设计>第3周学习总结 教材学习内容总结 一.第四章: (1)对象和类: 使用Java撰写程序几乎都在使用对象,要产生对象必须先定义类,类是对象的设计图,对象 ...

  7. curl的安装与使用

    linux 下的curl扩展安装,记录一下(发现网上好多抄袭的也不检测一下能不能用) 1.下载curl安装包: https://curl.haxx.se/download.html 2.解压: 如 t ...

  8. checkbox怎么判断是否选中

    下面这种可以使用 if($("#checkbox1").is(':checked')) { alert("1"); } else { alert("0 ...

  9. leetcode 304. Range Sum Query 2D - Immutable(递推)

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  10. intent实现Activity之间跳转的各种传值

    一.在Activity之间传递String类型的数据 传递 @Override public void onClick(View v) { String num1 = firstNum.getText ...