第九章 GDI Wrappers

图标

第九章  GDI 封装类

无论你的应用程序有多少个视图, 无论你如何管理这些视图, 你总是会在一些视图上做些绘画. WTL 对所有 Win32 GDI 资源对象进行了简单的封装, 如 Table2 所示.

 

Table 2: WTL Wrappers for Win32 GDI Objects
HDC    CDCT      
HPEN    CPenT      
HBRUSH    CBrushT      
HFONT    CFontT      
HBITMAP    CBitmapT      
HRGN    CRgnT      
HPALETTE    CPalletT

 

事实上, 对每个 GDI 资源的封装类都有两种版本:托管的(managed)和非托管的(unmanaged). 托管类负责自动销毁其所拥有的 GDI 资源对象, 而非托管类则把销毁 GDI 资源对象的任务交个程序员来完成. 例如, CFontT 类是 HFONT 资源对象的封装类, 并且它有一个 Boolean 型模版参数指定它是托管的还是非托管的. 这种做法提供了很大的灵活性.
( 译者注:在此托管类与非托管类的概念有别于C#托管代码的概念 )

//atlgdi.h
typedef CFontT<false>        CFontHandle;
typedef CFontT<true>        CFont;

template <bool t_bManaged>
class CFontT
{
public:
// Data members
    HFONT m_hFont;

// Constructor/destructor/operators
    CFontT(HFONT hFont = NULL) : m_hFont(hFont)
    { }

    ~CFontT()
    {

        if(t_bManaged && m_hFont != NULL)
            DeleteObject();
    }

    CFontT<t_bManaged>& operator=(HFONT hFont)
    {
        m_hFont = hFont;
        return *this;
    }

};


我们注意到 CFontT 的析构函数在调用成员函数 DeleteObject 释放 GDI 资源之前检查模版参数 t_bManaged 确定是一个托管类. 两个版本的最终类型为 CFontHandle CFont, 分别是托管类和非托管类. 对其它 GDI 的封装类都是相似的.
typedef CFontT<false>   CFontHandle; typedef CFontT<true>    CFont;


其中最庞大的封装类, 必然是 CDCT, 封装了超过240个成员方法涵盖了 GDI 和 WGL 相关函数, 称为冠军它当之无愧. 从它派生了四个托管版本的 WTL 类:CPaintDC, CWindowDC, CClientDC, CEnhMetaFileDC. CPaintDC 类封装了 PAINTSTRUCT 结构并使用 BeginPaint/EndPaint 函数对获取/释放 DC. CClientDC 类针对窗口客户区, 并使用 GetWindowDC/ReleaseDC 获取/释放 整个窗口的 DC 资源. 最后, CEnhMetaFileDC 类封装了 HENHMETAFILE 结构并调用 CreateEnhMetaFile 和 DeleteEnhMetaFile 创建和销毁 Windows 元数据文件(meta file). 下面的 CPaintDC 类的定义显示了这几个类的工作方式.
//atlgdi.h
class CPaintDC : public CDC
{
public:
    HWND m_hWnd;
    PAINTSTRUCT m_ps;

    CPaintDC(HWND hWnd)
    {
    m_hWnd = hWnd;
        m_hDC = ::BeginPaint(hWnd, &m_ps);
    }

    ~CPaintDC()
    {
        ::EndPaint(m_hWnd, &m_ps);

        Detach();
    }
};

使用托管 GDI 封装类可以简化原生的 GDI 代码. 例如, 我们的位图视图类可以简化成如下形式:
class CBitmapView : public CWindowImpl<CBitmapView>
{
public:
    CBitmapView()
    {
        m_bmp.LoadBitmap(MAKEINTRESOURCE(IDB_ATLWINDOWING));
    }
   
    BEGIN_MSG_MAP(CBitmapView)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
    END_MSG_MAP()
   
    LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&)
    {
        CPaintDC    dc(m_hWnd);
        RECT        rect; GetClientRect(&rect);
        CDC         dcMem; dcMem.CreateCompatibleDC(dc);
       
        CBitmap     bmpOld = dcMem.SelectBitmap(m_bmp);
        BITMAP      bm; m_bmp.GetBitmap(&bm);
        SIZE        size = { bm.bmWidth, bm.bmHeight };
       
        dc.BitBlt(rect.left, rect.top, size.cx, size.cy,  dcMem,
                  0, 0, SRCCOPY);
       
        // Cleanup
        dcMem.SelectBitmap(bmpOld);
       
        return 0;
    }
   
private:
    CBitmap m_bmp;
};

为了获取 GDI 绘图的更多支持, WTL 提供了一些辅助类, 它们都以 Atl 为前缀. 包括 AtlGetStockBrush, AtlGetStockFont, AtlGetStockPalette, AtlGetStockPen, AtlLoadAccelerators, AtlLoadBitmap, AtlLoadBitmapImage, AtlLoadCursor,  AtlLoadString 等等.

 

WTL Helper Classes

To be continued... 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值