我在使用MESSAGE_MAP和/或PreTranslateMessage时遇到问题。这可能是设计问题,但我不确定。主要问题是未调用MESSAGE_MAP代码,并且不确定如何通过PreTranslateMessage进行操作。即如下:

    //MyCDialogEx : public CDialogEx
    class MyCDialogEx::Init()
    {
        CFlatSplitterWnd m_cSplitter; //http://www.codersource.net/2010/01/29/mfc-splitter-window/
        m_pFrame = new CFlatFrameWnd;
        m_pFrame->Create(strMyClass, L"", WS_CHILD, rect, this);
        m_pFrame->ShowWindow(SW_SHOW);
        m_cSplitter.CreateStatic(m_pFrame, 1, 2);

        m_cSplitter.ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_NOSIZE | SWP_NOACTIVATE);
        m_cSplitter.CreateView(0, 0, RUNTIME_CLASS(CHolderView), CSize(100, 100), &ccc);

        CHolderView* pView = (CHolderView*)m_cSplitter.GetPane(0, 0);
        ASSERT_VALID(pView);
        pView->setWnd(&m_TreeCtrl);
        pView->setOwner(this, IDC_TREECTRL);

        const DWORD dwStyle = LBS_NOTIFY | WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES
         | TVS_LINESATROOT | TVS_CHECKBOXES | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP;
        m_TreeCtrl.Create(dwStyle, CRect(0, 0, 1, 1), pView, IDC_TREECTRL);
    }

    BEGIN_MESSAGE_MAP(MyCDialogEx, CDialogEx)
        ON_NOTIFY_REFLECT(WM_ONMYCLICK, OnClickTreectrl) //this & following not called
        ON_NOTIFY(NM_CLICK, IDC_TREECTRL, OnClickTreectrl)
        ON_NOTIFY(TVN_ITEMCHANGED, IDC_TREECTRL, OnItemchangedTreectrl)
        ON_NOTIFY(TVN_SELCHANGED, IDC_TREECTRL, OnSelchangedTreectrl)
        ON_NOTIFY(TVN_KEYDOWN, IDC_TREECTRL, OnKeydownTreectrl)
    END_MESSAGE_MAP()

    BOOL MyCDialogEx::PreTranslateMessage(MSG* pMsg)
    {
        if (GetFocus() && GetFocus()->GetDlgCtrlID() == IDC_TREECTRL)
        {
            //what/how goes in here to catch NM_CLICK, TVN_ITEMCHANGED etc??

            if (pMsg->message == WM_LBUTTONDOWN)
            {
                switch (LOWORD(pMsg->wParam))
                {
                case NM_CLICK:
                    break;
                }
            }
            if (pMsg->message == WM_KEYDOWN)
                TRACE(L"WM_KEYDOWN\n");

            if (pMsg->message == WM_KEYUP)
                TRACE(L"WM_KEYUP\n");
        }
        return MyCDialogEx::PreTranslateMessage(pMsg);
    }
    void MyCDialogEx::OnClickTreectrl(NMHDR *pNMHDR, LRESULT *pResult) //not called
    {
        TRACE(L"tree click\n");
        *pResult = 0;
    }

如果将它们放在CHolderView类MESSAGE_MAP中,则MESSAGE_MAP可以工作,但我宁愿不这样做,因为它只是一个容器类,并且可能在我的项目的其他地方使用。

我真正想做的是使用MESSAGE_MAP通过PreTranslateMessage最小化编码(&如果可以重定向到MESSAGE_MAP,怎么办?)。如果我必须求助于PreTranslateMessage或其他,那么我该如何使用它,以便可以捕获相关的NM_CLICK,TVN_ITEMCHANGED进行树控制等。

谢谢。

编辑:哦,以下内容无济于事,不相关或没有充分解释:
  • How to get Click Event of Treeview(CTreeCtrl) in MFC created at runtime?
  • How to redirect MFC messages to another object?
  • How can identify Mouse Click event in PreTranslateMessage?
  • 最佳答案

    问题在于树形 View 会将其所有通知发送到父窗口。父窗口是CHolderWindow。

    邮件不会像WM_COMMAND邮件那样进行路由。因此,WM_COMMAND消息的处理程序可以驻留在通知路径中的任何位置。

    但是常规窗口控件通知始终在窗口的直接父级中处理。在MFC中,您可以将此类通知重定向到子窗口控件本身。使用ON _..._ REFLECT。

    一个窍门可以是:将指向窗口的指针设置到应该接收所有消息的Holder窗口。然后在“持有者”窗口中接受所有WM_COMMAND和所有WM_NOTIFY消息,然后将它们重新发送到新窗口。

    PreTranslateMessage是另一回事。目标窗口始终首先接收 call 。比所有 parent 都有机会,直到PreTranslateMessage调用链中的某人返回TRUE。

    08-24 21:51