Better fix for duplicate wxContextMenuEvent generation under MSW.

Fix the bug with multiple wxContextMenuEvent being generated for a single
WM_CONTEXTMENU without breaking context menus for wxTextCtrl (and all the
other native controls). Do this by ensuring that WM_CONTEXTMENU is still
passed to DefWindowProc() if we don't process it instead of just being eaten
completely in any case.

Also add a unit test checking for this bug to ensure it stays fixed.

See #13683.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74329 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2013-07-02 20:24:22 +00:00
parent bdbdb4d181
commit dbd5b2ce42
2 changed files with 85 additions and 19 deletions

View File

@@ -3433,32 +3433,31 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
#if !defined(__WXWINCE__)
case WM_CONTEXTMENU:
{
// As with WM_HELP above, this message is propagated upwards
// the parent chain by DefWindowProc() itself, so we should
// always mark it as processed to prevent it from doing this
// as this would result in duplicate calls to event handlers.
processed = true;
// Ignore the events that are propagated from a child window by
// DefWindowProc(): as wxContextMenuEvent is already propagated
// upwards the window hierarchy by us, not doing this would
// result in duplicate events being sent.
WXHWND hWnd = (WXHWND)wParam;
if ( hWnd != m_hWnd )
{
wxWindowMSW *win = FindItemByHWND(hWnd);
if ( win && IsDescendant(win) )
{
// We had already generated wxContextMenuEvent when we
// got WM_CONTEXTMENU for that window.
processed = true;
break;
}
}
// we don't convert from screen to client coordinates as
// the event may be handled by a parent window
wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
evtCtx.SetEventObject(this);
// we could have got an event from our child, reflect it back
// to it if this is the case
wxWindowMSW *win = NULL;
WXHWND hWnd = (WXHWND)wParam;
if ( hWnd != m_hWnd )
{
win = FindItemByHWND(hWnd);
}
if ( !win )
win = this;
evtCtx.SetEventObject(win);
win->HandleWindowEvent(evtCtx);
processed = HandleWindowEvent(evtCtx);
}
break;
#endif