`

CPaintDC, CClientDC与CWindowDC的区别

 
阅读更多

CClientDC(客户区设备上下文)用于客户区(不包含标题栏、边框)的输出,它在构造函数中封装了GetDC(),在析构函数中封装了ReleaseDC()函数。一般在响应非窗口重画消息(如键盘输入时绘制文本、鼠标绘图)绘图时要用到它。用法是:

CClientDC dc(this);//this一般指向本窗口或当前活动视图

dc.TextOut(10,10,str,str.GetLength());

//利用dc输出文本,如果是在CScrollView中使用,还要注意调

//用OnPrepareDC(&dc)调整设备上下文的坐标。

CPaintDC用于响应窗口(包含标题栏、边框)重绘消息(WM_PAINT)是的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。CPaintDC也只能用在WM_PAINT消息处理之中。

使用CPaintDC、CClientDC、CWindowDC的方法

首先,定义一个这些类的实例变量,通常在栈中定义。然后,使用它。

例如,MFC中CView对WM_PAINT消息的实现方法如下:

void CView::OnPaint()

{

// standard paint routine

CPaintDC dc(this);

OnPrepareDC(&dc);

OnDraw(&dc);

}

在栈中定义了CPaintDC类型的变量dc,随着构造函数的调用获取了设备描述表;设备描述表使用完毕,超出其有效范围就被自动地清除,随着析构函数的调用,其获取的设备描述表被释放。

如果希望在堆中创建,例如

CPaintDC *pDC;

pDC = new CPaintDC(this)

则在使用完毕时,用delete删除pDC:

delete pDC;

直接使用CDC

需要注意的是:在生成CDC对象的时候,并不像它的派生类那样,在构造函数里获取相应的Windows设备描述表。最好不要使用::GetDC等函数来获取一个设备描述表,而是创建一个设备描述表。其构造函数如下:

CDC::CDC()

{

m_hDC = NULL;

m_hAttribDC = NULL;

m_bPrinting = FALSE;

}

其析构函数如下:

CDC::~CDC()

{

if (m_hDC != NULL)

::DeleteDC(Detach());

}

在CDC析构函数中,如果设备描述表句柄不空,则调用DeleteDC删除它。这是直接使用CDC时最好创建Windows设备描述表的理由。如果设备描述表不是创建的,则应该在析构函数被调用前分离出设备描述表句柄并用::RealeaseDC释放它,释放后m_hDC为空,则在析构函数调用时不会执行::DeleteDC。当然,不用担心CDC的派生类的析构函数调用CDC的析构函数,因为CDC::~CDC()不是虚拟析构函数。

直接使用CDC的例子是内存设备上下文,例如:

CDC dcMem; //声明一个CDC对象

dcMem.CreateCompatibleDC(&dc); //创建设备描述表

pbmOld = dcMem.SelectObject(&m_bmBall);//更改设备描述表属性

…//作一些绘制操作


dcMem.SelectObject(pbmOld);//恢复设备描述表的属性

dcMem.DeleteDC(); //可以不调用,而让析构函数去删除设备描述表

系统何时发送WM_PAINT消息?

(来自:http://dev.csdn.net/article/74/74935.shtm)

系统会在多个不同的时机发送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是否为空等。

分享到:
评论

相关推荐

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

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

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

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

    CDC.rar_CDC_CPtrArray ondraw_metafile_onpaint cdc

    如何让CDC上输出的文字、图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,滚动窗口的实现,坐标空间,映射方式,设备坐标与逻辑坐标的转换...

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

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

    滚动窗口的实现兼容DC实现图形的保存和再现

    如何让CDC上输出的文字、图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,滚动窗口的实现,坐标空间,映射方式,设备坐标与逻辑坐标的转换...

    《VC++深入详解》第11章 图形的保存和重绘

    如何让CDC上输出的文字和图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,滚动窗口的实现,坐标空间、映射方式、设备坐标与逻辑坐标的转换...

    Draw_Form.rar_CPaintDC_Draw the windows_MFC cdc绘图_MFC 绘图_VC++ CD

    关于VC和windows 的绘图机制,使用GDI(图形设备接口)对象,通常使用CDC 类,CPaintDC也一样(device-context)设备上下文 Windows下的MFC编程机制,消息驱动,事件等待.

    VC++几何绘图实例

    摘要:VC/C++源码,其它分类,几何绘图 VC++几何绘图实例,如何让CDC上输出的文字、图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,滚动窗口...

    CPaintDCDemo

    通过vc编写基于对话框的实例。读者可以参考以便学习应用哦

    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++ 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...

    VC学习大纲 VC学习讲义

    如何让CDC上输出的文字、图形具有保持功能,元文件设备描述表的使用,CpaintDC与CClientDC的区别与应用,OnPaint与Ondraw在CView中的关系及实现内幕,集合类CObArray的使用,滚动窗口的实现,设备坐标与逻辑坐标的...

    在对话框上绘制背景

    MFC在对话框上绘制背景实例小程序,学习如何在程序开发中在对话框上绘制背景

    基于GDI绘图各种DC的使用

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

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

    实例146——在视图中使用CPaintDC进行进行窗口重绘操作 实例147——在视图中使用CWindowDC在整个窗口进行绘图 实例148——在对话框窗口中进行绘图操作 实例149——创建字体进行文本输出 实例150——制作简单的...

    mfc绘图~内含mfc绘制的心形图案~敬请享用吧~

    mfc绘图~内含mfc绘制的心形图案~使用鼠标绘图~使用CClientDC类~心形图案绘制使用CPaintDC类~使用三叶玫瑰线中的两叶旋转的到的~敬请享用吧~~课程设计尽管来吧~qq~叁~玖~捌~贰~肆~肆~捌~叁~柒~~~

    Led 显示 类 数码管 数码 数字

    用户应自己设置好 rtDispRect与iFontWidth iFontHeight 的大小关系. 如果iFontHeight大于rtDispRect.Height(),则超出DispRect区域显示字符. 但左右可能不会超出显示(用户可设置m_bShowWhenOverstepRect来控制是否...

    Visual.C#2010从入门到精通

    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 其他绘图方式 133 8.5 映射模式 ...

    stdafx.h代码

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

    ClipPaint.rar

    说明如何使用InvalidateRect(&rc); CPaintDC; m_ps.rcPaint。 同时包括CWnd的ScrollWindow(delta,0);

Global site tag (gtag.js) - Google Analytics