我有一个窗口类,可以在右键单击时创建一个弹出菜单。
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
答案 0 :(得分:2)
问题是,窗口对象已经被破坏了。因此,访问指向m_RightClickMenu的this指针将导致崩溃。
为什么要销毁此位置的菜单。我知道的所有菜单类都在析构函数中自毁。所以从我的观点来看,没有必要在这里调用DestroyMenu。
另外调用只是不要调用基类RButtonDown。为什么?您已经完成了不应该导致进一步操作的操作。因为基类是CWnd,所以甚至没有动作。 更好的方法:首先调用它,而不是做你的事情。
PS:你没有写过m_RightClickMenu是什么类的。
PS2:你知道MFC里面有一个特殊的CContextMenuManager吗?