右クリックでポップアップ メニューを作成するウィンドウ クラスがあります。
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 です