首页 > 技术文章 > ATL一:CWindowImpl

liuhan333 2016-05-22 18:10 原文

1,
#ifdef _ATL_DISABLE_NO_VTABLE
#define ATL_NO_VTABLE
#else
#define ATL_NO_VTABLE __declspec(novtable)
#endif

This form of __declspec can be applied to any class declaration, but should only be applied to pure interface classes, that is, classes that will never be instantiated on their own. The __declspec stops the compiler from generating code to initialize the vfptr in the constructor(s) and destructor of the class. In many cases, this removes the only references to the vtable that are associated with the class and, thus, the linker will remove it. Using this form of __declspec can result in a significant reduction in code size.
__declspec(novtable)最好只用于纯虚接口函数,永远不能对自己实例化。它阻止编译器在类构造和析构的时候初始化虚函数表。通常,在链接的时候会删除虚函数表。这样做可以显著减少代码大小。(总之就是不产生虚函数表,减少运行时间和空间。应为没有虚函数表,不能对虚函数调用,所以这个类不能生在实例。)
If you attempt to instantiate a class marked with novtable and then access a class member, you will receive an access violation (AV).

2,
// CMessageMap - abstract class that provides an interface for message maps
class ATL_NO_VTABLE CMessageMap
{
public:
    virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
        LRESULT& lResult, DWORD dwMsgMapID) = 0;
};//消息处理的接口

// CWindowImpl - Implements a window
template <class TBase /* = CWindow */>
class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
{
//消息过滤
}

template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase >
{
//创建销毁窗口、设置style、默认消息回调函数
}

template <class T, class TBase /* = CWindow */, class TWinTraits /* = CControlWinTraits */>
class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
{
//设置窗口属性,创建窗口
};

3,
// CWndClassInfo - Manages Windows class information
#define DECLARE_WND_CLASS(WndClassName) \
static ATL::CWndClassInfo& GetWndClassInfo() \
{ \
    static ATL::CWndClassInfo wc = \
    { \
        { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
         0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
        NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
    }; \
    return wc; \
}

// Message map
#define BEGIN_MSG_MAP(theClass) \
public: \
    BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
    { \
        BOOL bHandled = TRUE; \
        (hWnd); \
        (uMsg); \
        (wParam); \
        (lParam); \
        (lResult); \
        (bHandled); \
        switch(dwMsgMapID) \
        { \
        case 0:

#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
    if(uMsg >= msgFirst && uMsg <= msgLast) \
    { \
        bHandled = TRUE; \
        lResult = func(uMsg, wParam, lParam, bHandled); \
        if(bHandled) \
            return TRUE; \
    }

#define END_MSG_MAP() \
            break; \
        default: \
            ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
            ATLASSERT(FALSE); \
            break; \
        } \
        return FALSE; \
    }

---------------------------------------------------------------------

4,
template< class THost >
class CSingleThreadWindow : public CWindowImpl< CSingleThreadWindow< THost > >
{
public:
    DECLARE_WND_CLASS( _T("SingleThreadWindowClass") )
    BEGIN_MSG_MAP( CSingleThreadProxy< THost > )
        MESSAGE_RANGE_HANDLER(0, 0xFFFFFFFF, WndProc)
    END_MSG_MAP()
    CSingleThreadWindow( THost *pHost ,BOOL bHeap ){}
    RESULT WndProc( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
    {
        return m_pHost->OnSingleThreadProxyMsg( uMsg, wParam, lParam, bHandled );
    };
protected:
    THost                *m_pHost;
}

HWND CMulThreadProxy::GetMsgWindow()
{
CSingleThreadWindow<CMulThreadProxy> *pObjWindow = new CSingleThreadWindow<CMulThreadProxy>(this,TRUE);
}

推荐阅读