作者:朱金灿
来源:http://blog.csdn.net/clever101/
下面是对话框的OnPaint函数(就是WM_PAINT消息的响应函数)的两种写法。
写法一:
void CMyDlg::OnPaint() { CDC *pDC = GetDC(); // 我的绘制代码 MyDrawFunction(pDC); ReleaseDC(pDC); }
写法二:
void CMyDlg::OnPaint() { CPaintDC dc(this); // 我的绘制代码 MyDrawFunction(&dc); }
开始以为这两种写法并无区别。今天偶然发现了这个区别。这个区别大家也可测试一下。建一个基于对话框的工程。然后添加下面绘图代码:
void CColorPaletteDlg::DrawLine(CDC *pDC) { assert(NULL!=pDC); Gdiplus::Pen red (Color(255, 255, 0, 0),2.0f); Gdiplus::Graphics graphics(pDC->GetSafeHdc()); graphics.DrawLine(&red, 0, 0, 100,100); }
然后把它放在两个不同的OnPaint函数里调用,如下:
void CColorPaletteDlg::OnPaint() { CDC *pDC = GetDC(); DrawLine(pDC); ReleaseDC(pDC); }
或是:
void CColorPaletteDlg::OnPaint() { CPaintDC dc(this); DrawLine(&dc); }
一开始启动程序二者并无区别,但是在切换到其它程序窗口,比如打开一个txt文件再打开这个程序,你就会发现区别,写法一的效果会变为如下:
写法二的效果如下:
注意写法二能正常显示下面两个按钮。
让我们看看MSDN对CPaintDC是如何解释的?
CPaintDC objects encapsulate the common idiom of Windows, calling the BeginPaint function, then drawing in the device context, then calling the EndPaint function. The CPaintDC constructor calls BeginPaint for you, and the destructor calls EndPaint. The simplified process is to create the CDC object, draw, and destroy the CDC object. In the framework, much of even this process is automated. In particular, your OnDraw function is passed a CPaintDC already prepared (via OnPrepareDC), and you simply draw into it. It is destroyed by the framework and the underlying device context is released to Windows upon return from the call to your OnDraw function.
CClientDC objects encapsulate working with a device context that represents only the client area of a window. The CClientDC constructor calls the GetDC function, and the destructor calls the ReleaseDC function.CWindowDC objects encapsulate a device context that represents the whole window, including its frame.
大致的翻译是:CPaintDC对象封装了Windows的,调用BeginPaint函数,然后在设备上下文上绘图,然后调用EndPaint函数的常见用法。该CPaintDC构造函数调用BeginPaint函数,在析构函数调用EndPaint。简化的处理过程就是创造CDC对象,绘制,并摧毁了CDC对象。在框架内,即使是这个过程的大部分是自动的。特别是,你的OnDraw函数传递一个CPaintDC已经准备通过OnPrepareDC(),你通过它进行简单的绘图。它是由框架销毁和从调用您的OnDraw函数返回到基本设备上下文被释放后回Windows。(这一句的翻译有问题)
CClientDC对象封装与一个设备上下文,表示只有一个窗口的客户区。该CClientDC构造函数调用GetDC的功能,析构函数调用ReleaseDC function.CWindowDC对象封装了表示整个窗口(包括它的框架)的设备上下文。
也就是说,第二种写法比第一种写法做的工作要多。在此多谢VC知识库的benben、bl、sjdev等诸位大侠。