走近WTL--GDI篇
WTL中的GDI类的封装与MFC不同,对于这些类的详细描述,可以参见WTL for MFC Programmers, Part IX – GDI Classes, Common Dialogs, and Utility Classes.
在由MFC的GDI向WTL的GDI转换过程中,有以下几个问题需要注意的:
一、OnPaint函数的处理。
在OnPaint函数的声明中,有以下的两种方法:
BEGIN_MSG_MAP_EX(MyWnd) .... MESSAGE_HANDLER(WM_PAINT, OnPaint) ... END_MSG_MAP() LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
或者是:
BEGIN_MSG_MAP_EX(MyWnd) .... MSG_WM_PAINT(OnPaint) ... END_MSG_MAP() LRESULT OnPaint(HDC hdc)
实际上,这两种写法在使用中区别不大,第一种传入的四个参数都不会用到,第二种传入的hdc的值是NULL,所以这些参数都是不可以被OnPaint函数使用。那么在OnPaint中如何开始绘图呢?我们可以使用CPaintDC,如下:
LRESULT HexxagonWnd::OnPaint(HDC hdc) { CPaintDC pDC(m_hWnd); CDCHandle dc(pDC.m_hDC); ... }
这样,我们就可以方便的使用CDCHandle了。这篇文章也对这个问题做了一定的说明,大家可以参考一下:WTL7.0的一个BUG。
二、如何创建双缓冲
在WTL中CDC类被CDCHandle取代,其中对CBitmap的一些操作也有了变化。
CRect lcrcClient; GetClientRect(&lcrcClient); CDCHandle MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 MemDC.CreateCompatibleDC(NULL); MemBitmap.CreateCompatibleBitmap(dc,lcrcClient.Width(),lcrcClient.Height()); HBITMAP pOldBit=MemDC.SelectBitmap((HBITMAP)MemBitmap); //使用MemDC绘制一些图像 .... dc.BitBlt(lcrcClient.left, lcrcClient.top, lcrcClient.Width(), lcrcClient.Height(), MemDC, lcrcClient.left, lcrcClient.top, SRCCOPY); //绘图完成后的清理 MemBitmap.DeleteObject(); MemDC.DeleteDC();
三、SelectObject函数的变化
WTL的几个select函数都是直接使用对应类型的GDI对象,并且传入参数为HPEN、HBRUSH等类型,如下所示:
HPEN SelectPen(HPEN nPen) HBRUSH SelectBrush(HBRUSH nBrush) HFONT SelectFont(HFONT nFont)
一般的CPen等可以通过HPEN操作符直接从CPen转换出HPEN对象,所以保存、恢复GDI对象的代码要做如下改变:
CPen lcPen; lcPen.CreatePen(PS_SOLID, 1, gColorGreen); HPEN lcpOldPen = dc.SelectPen((HPEN)lcPen); dc.SelectPen((HPEN)lcpOldPen);
当然,WTL的GDI与MFC还有一些其他的不同,大家使用时应注意。