Reputation: 185
I have a window class which creates a popup menu on right click.
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);
}
The issue was, when on right click, popup menu appears and before user clicks on any menu option, the window needs to be closed, the application crashes.
To take care of this, I defined a function clear(), which sends message to remove popup menu.
MyWnd::Clear()
{
if (GetSafeHwnd())
{
SendMessage(WM_CANCELMODE);
}
}
So, first clear is called then window is destroyed. Using this, Popup menu is removed but the application still crashes in RButtonDown function in line
m_RightClickMenu.DestroyMenu();
or sometimes in
CWnd::OnRButtonDown(nFlags, point);
What I think is, after clear, window is getting destroyed in same thread. But the call in RButtonDown is stuck in separate thread. So, when RButtonDown resumes its execution, MyWnd class is either completely destroyed or in process of destroying. Hence crash is occurring.
What I was thinking of making it thread safe using locks. But how to know if I need to wait for lock or not in destructor of MyWnd is not clear. Since I am not sure if popup menu is created or not.
Please suggest what should be done. How to stop execution of RButtonDown when WM_CANCELMODE is called or any other way.
EIDT : my m_RightClickMenu is type CMenu
Upvotes: 0
Views: 3872
Reputation: 15355
The problem seams to be, that the window object is already destroyed. So the access to the this pointer to m_RightClickMenu will cause the crash.
Why do you destroy the menu in this location. All menu classes I know destroy themselves in the destructor. So from my point of view there is no need to call DestroyMenu here.
Also call just don't call the base class RButtonDown. Why? You already done an action that shouldn't cause further action. And because the base class is CWnd there is even no action. Better way: Call it first and than do your sustom stuff.
PS: You didn't wrote what kind of class m_RightClickMenu is.
PS2: You know that there is a special CContextMenuManager inside the MFC?
Upvotes: 2