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还有一些其他的不同,大家使用时应注意。