CPaintDC 、CWindowDC、 CClientDC、 CDC
关系图:
一句话概括:
CPaintDC 无效区dc, 相当于BeginPaint, EndPaint
CClientDC 客户区dc, 相当于GetDC, ReleaseDC
CWindowDC 整窗口dc, 相当于GetWindowDC, ReleaseDC
CDC 任何dc, 相当于CreateDC, DeleteDC
CPaintDC
是从CDC派生的
CPaintDC 用于响应窗口重绘消息(WM_PAINT)是的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用 EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。CPaintDC也只能用在WM_PAINT消息处理之中。
如 CPaintDC dc(this);
直接使用,无需显性释放删除。
CClientDC
是从CDC派生的
CClientDC(客户区设备上下文)用于客户区的输出,它在构造函数中封装了GetDC(),在析构函数中封装了ReleaseDC()函数。一般在响应非窗口重画消息(如键盘输入时绘制文本、鼠标绘图)绘图时要用到它。用法是:
CClientDC dc(this);//this一般指向本窗口或当前活动视图 。直接使用,无需显性释放删除。
CWindowDC
CWindowDC类是从CDC派生的。它在构建时调用GetWindowDC窗口函数,在销毁时调用ReleaseDC窗口函数。这意味着CWindowDC对象访aCWnd的整个屏幕区域(客户端和非客户端区域)。
直接使用,无需显性释放删除。
CMemDC其实就是对内存DC的创建与删除进行一个包装。
1、在CMemDC的构造函数中创建内存DC;
2、用户可以在CMemDC dc中进行图像的绘制;
3、在CMemDC的析构函数中进行内存DC到目标DC的拷贝,并做相应的GDI对象清理工作。
直接使用,无需显性释放删除。
- 在你的项目中添加文件memdc.h。
- 将#include“memdc.h”行添加到stdafx.h。
- 添加一个Windows消息处理程序
WM_ERASEBKGND
。 - 更改消息处理程序中的代码如下:
// Change this code BOOL CExampleView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return CView::OnEraseBkgnd(pDC); } // To this code BOOL CExampleView::OnEraseBkgnd(CDC* pDC) { return FALSE; }
- 将您的
OnDraw
代码更改为以下内容:void CExampleView::OnDraw(CDC* dc) { CMemDC pDC(dc); }
CDC
直接使用CDC的例子是内存设备上下文,例如:
CDC dcMem; //声明一个CDC对象
dcMem.CreateCompatibleDC(&dc); //创建设备描述表
pbmOld = dcMem.SelectObject(&m_bmBall);//更改设备描述表属性
…//作一些绘制操作
dcMem.SelectObject(pbmOld);//恢复设备描述表的属性
dcMem.DeleteDC(); //可以不调用,而让析构函数去删除设备描述表
如果通过局部变量的方式,定义cdc对象,可以不用调DeleteDC进行删除,如上面的代码。
CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类。
CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍。
1)获得DC GetDC
可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:
CDC* GetDC( );
来获得DC的指针。
2)释放DC ReleaseDC
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成: