WTL 如何在同一窗口中使用 2 个自定义绘制的 CListViewCtr

WTL how to use 2 custom-draw CListViewCtr in the same window

本文关键字:自定义 绘制 CListViewCtr 窗口 WTL      更新时间:2023-10-16

如何CHAIN_MSG_MAP_MEMBER用于两个成员?
下面的示例适用于单个列表视图和单个CHAIN_MSG_MAP_MEMBER.有了这两个我,我都崩溃了。

class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
        public CMessageFilter, public CIdleHandler
{
public:
    DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
    virtual BOOL PreTranslateMessage(MSG* pMsg)
    {
        return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
    }
    BEGIN_MSG_MAP(CMainFrame)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
        COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
        COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
        CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
        CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
        CHAIN_MSG_MAP_MEMBER(m_listView)            //< 
        CHAIN_MSG_MAP_MEMBER(m_listView2)           //< ISSUE: crash with both, works with one.
    END_MSG_MAP()
    LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
    {
         // create a list box   
        RECT r = {0,0,182,80};    
        m_listView.Create(m_hWnd,r,CListViewCtrl::GetWndClassName(),WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | LVS_REPORT, WS_EX_CLIENTEDGE    );
        RECT r2 = {0,80,182,80+80};    
        m_listView2.Create(m_hWnd,r2,CListViewCtrl::GetWndClassName(),WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | LVS_REPORT, WS_EX_CLIENTEDGE    );
        ...
        populate
    }
} 
class MyListView : public CWindowImpl<MyListView, CListViewCtrl>,
                   public CCustomDraw<MyListView>                   
{
public:
  BEGIN_MSG_MAP(MyListView)    
    CHAIN_MSG_MAP(CCustomDraw<MyListView>)
    END_MSG_MAP()           
    DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
    {       
        ...
    }
    DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
    {
        ...
    }
    DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
    {
        ...
    }
    ............
}

CCustomDraw是WTL类,假设你使用BEGIN_MSG_MAP_EX,而不是ATL的BEGIN_MSG_MAP

#include <atlcrack.h>
class MyListView : public CWindowImpl<MyListView, CListViewCtrl>,
                   public CCustomDraw<MyListView>                   
{
public:
BEGIN_MSG_MAP_EX(MyListView) // <<--- Here we go   
    CHAIN_MSG_MAP(CCustomDraw<MyListView>)
END_MSG_MAP()           
};

经验法则是,只要您利用 WTL,就永远不要使用BEGIN_MSG_MAP

另外,值得一提的是,这种CHAIN_MSG_MAP_MEMBER的使用对我来说毫无意义。