winapivisual-c++mfcmessage-map

MFC: Have CDockablePane receive ON_NOTIFY_REFLECT messages for a CTreeCtrl?


The MFC Wizard created a project with a CWorkSpaceBar which in my case is actually based on CBCGPDockingControlBar, the MFC equivalent is CDockablePane. The wizard also created a m_wndTree based on CBCGPTreeCtrl (CTreeCtrl). It created it in its OnCreate() like this:

CRect rectDummy;
rectDummy.SetRectEmpty();

// Create tree control:
const DWORD dwViewStyle =   WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS;


if (!m_wndTree.Create(dwViewStyle, rectDummy, this, 1))
{
    TRACE0("Failed to create workspace view\n");
    return -1;      // fail to create
}

Now I would like to handle some of the TreeView notifications so I added these to the CWorkSpaceBar message map:

ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, &CWorkSpaceBar::OnTvnItemExpanding)
ON_NOTIFY_REFLECT(TVN_GETDISPINFO, &CWorkSpaceBar::OnTvnGetDispInfo)

However, I'm not getting the notification messages? Is there something else I need to do to make it work?


Solution

  • You appear to be confusing the ON_NOTIFY_REFLECT and ON_NOTIFY handlers; or rather, the windows for which those handlers should be defined.

    From what you have described, your CWorkSpaceBar class/object is the parent of the tree-view (CTreeCtrl) object; so, when an item is expanded in that tree-view, that parent pane receives a WM_NOTIFY message and the relevant ON_NOTIFY handler (if defined in the message-map) is called. The ON_NOTIFY_REFLECT handler allows the actual tree-view itself to intercept/receive the notification.

    In my projects, I have a similar situation, and the class(es) derived from CDockablePane (such as my UserPane) have message map entries like the following, which work as expected:

        ON_NOTIFY(TVN_ITEMEXPANDING, IDR_USRTV, &UserPane::OnItemExpand)
    

    Note: The IDR_USRTV is the ID value that I give to the tree-view, in its Create function, as shown below; in your example code, you have used the value of 1 (which may or may not be advisable).

    int UserPane::OnCreate(CREATESTRUCT *pCreateStruct)
    {
        CRect rc;   rc.SetRectEmpty();
        const DWORD trvstyle = WS_CHILD | WS_VISIBLE |
            TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_EDITLABELS;
        if (CDockablePane::OnCreate(pCreateStruct) == -1) return -1;
        if (!m_wndTView.Create(trvstyle, rc, this, IDR_USRTV)) return -1;
        //...
    

    A basic outline for the OnItemExpand member function is as follows:

    void UserPane::OnItemExpand(NMHDR *pNotifyStruct, LRESULT *result)
    {
        *result = 0;
        NMTREEVIEW *pTV = reinterpret_cast<NMTREEVIEW *>(pNotifyStruct);
        HTREEITEM hItem = pTV->itemNew.hItem;
        uintptr_t itemData = m_wndTView.GetItemData(hItem);
        if (pTV->action == TVE_EXPAND) {
            //...
        }
        else if (pTV->action == TVE_COLLAPSE) {
            //...
        }
        return;
    }