第九章 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... 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值