MFC TrackPopupMenu问题

时间:2013-11-11 08:05:20

标签: c++ visual-c++ mfc

我有一个窗口类,可以在右键单击时创建一个弹出菜单。

MyWnd::OnRButtonDown(/* parameters*/)
{
    // do something
    VERIFY(m_RightClickMenu.CreatePopupMenu());
    MENUINFO MenuInfo;
    m_RightClickMenu.GetMenuInfo(&MenuInfo);
    MenuInfo.dwStyle = MNS_NOTIFYBYPOS;
    m_RightClickMenu.SetMenuInfo(&MenuInfo);
    HMENU hMenu = m_RightClickMenu.GetSafeHmenu();
    if (NULL != hMenu)
    {
        CString tempStr;
        // Add menu Items
        ClientToScreen(&ptMousePos);
        m_RightClickMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | 
                         TPM_HORPOSANIMATION | TPM_VERPOSANIMATION ,
                         ptMousePos.x, ptMousePos.y, this);
        m_RightClickMenu.DestroyMenu();
    }
    CWnd::OnRButtonDown(nFlags, point);
}

问题是,当右键单击时,弹出菜单出现,在用户点击任何菜单选项之前,需要关闭窗口,应用程序崩溃。

为了解决这个问题,我定义了一个函数clear(),它发送消息以删除弹出菜单。

MyWnd::Clear()
{
    if (GetSafeHwnd())
    {
        SendMessage(WM_CANCELMODE);
    }
}

所以,先调用clear然后窗口被破坏。使用此选项,弹出菜单将被删除,但应用程序仍然在行

中的RButtonDown函数中崩溃
m_RightClickMenu.DestroyMenu();

或有时在

CWnd::OnRButtonDown(nFlags, point);

我认为,在清除之后,窗口会在同一个线程中被破坏。但是RButtonDown中的调用被卡在单独的线程中。因此,当RButtonDown恢复执行时,MyWnd类要么被完全破坏,要么正在销毁。因此发生了崩溃。

我在考虑使用锁使其线程安全。但是如何知道我是否需要在MyWnd的析构函数中等待锁定还不清楚。因为我不确定是否创建了弹出菜单。

请建议应该做什么。如何在调用WM_CANCELMODE或其他任何方式时停止执行RButtonDown。

EIDT:我的m_RightClickMenu是类型CMenu

1 个答案:

答案 0 :(得分:2)

问题是,窗口对象已经被破坏了。因此,访问指向m_RightClickMenu的this指针将导致崩溃。

为什么要销毁此位置的菜单。我知道的所有菜单类都在析构函数中自毁。所以从我的观点来看,没有必要在这里调用DestroyMenu。

另外调用只是不要调用基类RButtonDown。为什么?您已经完成了不应该导致进一步操作的操作。因为基类是CWnd,所以甚至没有动作。 更好的方法:首先调用它,而不是做你的事情。

PS:你没有写过m_RightClickMenu是什么类的。

PS2:你知道MFC里面有一个特殊的CContextMenuManager吗?