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

发表评论