#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
#include "wx/menu.h"
#include "wx/scopedptr.h"
#include "wx/scopeguard.h"
+#include "wx/uiaction.h"
// FIXME: Currently under OS X testing paint event doesn't work because neither
// calling Refresh()+Update() nor even sending wxPaintEvent directly to
CPPUNIT_TEST( ScrollWindowWithHandler );
CPPUNIT_TEST( MenuEvent );
CPPUNIT_TEST( DocView );
+ WXUISIM_TEST( ContextMenuEvent );
CPPUNIT_TEST_SUITE_END();
void OneHandler();
void ScrollWindowWithHandler();
void MenuEvent();
void DocView();
+ void ContextMenuEvent();
DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
};
// get the event in order.
ASSERT_MENU_EVENT_RESULT( menuChild, "advmcpA" );
}
+
+#if wxUSE_UIACTIONSIMULATOR
+
+class ContextMenuTestWindow : public wxWindow
+{
+public:
+ ContextMenuTestWindow(wxWindow *parent, char tag)
+ : wxWindow(parent, wxID_ANY),
+ m_tag(tag)
+ {
+ Connect(wxEVT_CONTEXT_MENU,
+ wxContextMenuEventHandler(ContextMenuTestWindow::OnMenu));
+ }
+
+private:
+ void OnMenu(wxContextMenuEvent& event)
+ {
+ g_str += m_tag;
+
+ event.Skip();
+ }
+
+ const char m_tag;
+
+ wxDECLARE_NO_COPY_CLASS(ContextMenuTestWindow);
+};
+
+void EventPropagationTestCase::ContextMenuEvent()
+{
+ ContextMenuTestWindow * const
+ parent = new ContextMenuTestWindow(wxTheApp->GetTopWindow(), 'p');
+ wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
+
+ ContextMenuTestWindow * const
+ child = new ContextMenuTestWindow(parent, 'c');
+ parent->SetSize(100, 100);
+ child->SetSize(0, 0, 50, 50);
+ child->SetFocus();
+
+ wxUIActionSimulator sim;
+ const wxPoint origin = parent->ClientToScreen(wxPoint(0, 0));
+
+ // Right clicking in the child should generate an event for it and the
+ // parent.
+ g_str.clear();
+ sim.MouseMove(origin + wxPoint(10, 10));
+ sim.MouseClick(wxMOUSE_BTN_RIGHT);
+
+ // At least with MSW, for WM_CONTEXTMENU to be synthesized by the system
+ // from the right mouse click event, we must dispatch the mouse messages.
+ wxYield();
+
+ CPPUNIT_ASSERT_EQUAL( "cp", g_str );
+
+ // Right clicking outside the child should generate the event just in the
+ // parent.
+ g_str.clear();
+ sim.MouseMove(origin + wxPoint(60, 60));
+ sim.MouseClick(wxMOUSE_BTN_RIGHT);
+ wxYield();
+ CPPUNIT_ASSERT_EQUAL( "p", g_str );
+}
+
+#endif // wxUSE_UIACTIONSIMULATOR