From 8de1128c07aff8fadc7df89fb291d32316186240 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Nov 2014 01:02:31 +0000 Subject: [PATCH] Return correct menu pointer for wxEVT_MENU_{OPEN,CLOSE} in MDI frames. These events are supposed to carry a pointer to the menu which was opened or closed, but wxMenuEvent::GetMenu() always returned NULL for the menus opened when a child MDI frame was active, as its menu bar, containing the menu, was not searched for it. Fix this by overriding MSWFindMenuFromHMENU() at wxMDIParentFrame level, just as we already do for FindItemInMenuBar(). git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78130 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/msw/mdi.h | 5 +++-- samples/mdi/mdi.cpp | 23 +++++++++++++++++++---- samples/mdi/mdi.h | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/msw/mdi.cpp | 14 ++++++++++++++ 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index d880ff3f80..df68cb53d5 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -114,6 +114,7 @@ wxMSW: - Fix updating wxSlider background when its parent background changes. - Implement wxListBox::EnsureVisible() (RIVDSL). - Drastically improve efficiency of selecting all items in wxDataViewCtrl. +- Fix wxMenuEvent::GetMenu() for wxEVT_MENU_{OPEN,CLOSE} in MDI frames. wxOSX/Cocoa: diff --git a/include/wx/msw/mdi.h b/include/wx/msw/mdi.h index 867ea302c1..457414c949 100644 --- a/include/wx/msw/mdi.h +++ b/include/wx/msw/mdi.h @@ -103,9 +103,10 @@ public: virtual bool MSWTranslateMessage(WXMSG* msg); #if wxUSE_MENUS - // override wxFrameBase function to also look in the active child menu bar - // and the "Window" menu + // override the menu-relayed methods to also look in the active child menu + // bar and the "Window" menu virtual wxMenuItem *FindItemInMenuBar(int menuId) const; + virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu); #endif // wxUSE_MENUS protected: diff --git a/samples/mdi/mdi.cpp b/samples/mdi/mdi.cpp index ee5acc77e7..bf6d57c3e6 100644 --- a/samples/mdi/mdi.cpp +++ b/samples/mdi/mdi.cpp @@ -70,6 +70,9 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame) EVT_MENU(wxID_CLOSE_ALL, MyFrame::OnCloseAll) + EVT_MENU_OPEN(MyFrame::OnMenuOpen) + EVT_MENU_CLOSE(MyFrame::OnMenuClose) + EVT_CLOSE(MyFrame::OnClose) wxEND_EVENT_TABLE() @@ -91,6 +94,9 @@ wxBEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame) EVT_SIZE(MyChild::OnSize) EVT_MOVE(MyChild::OnMove) + EVT_MENU_OPEN(MyChild::OnMenuOpen) + EVT_MENU_CLOSE(MyChild::OnMenuClose) + EVT_CLOSE(MyChild::OnCloseWindow) wxEND_EVENT_TABLE() @@ -132,7 +138,8 @@ bool MyApp::OnInit() // Define my frame constructor MyFrame::MyFrame() : wxMDIParentFrame(NULL, wxID_ANY, "wxWidgets MDI Sample", - wxDefaultPosition, wxSize(500, 400)) + wxDefaultPosition, wxSize(500, 400)), + MenuEventLogger("parent", this) { SetIcon(wxICON(sample)); @@ -175,9 +182,13 @@ MyFrame::MyFrame() #endif // wxUSE_STATUSBAR - m_textWindow = new wxTextCtrl(this, wxID_ANY, "A help window", + m_textWindow = new wxTextCtrl(this, wxID_ANY, "A log window\n", wxDefaultPosition, wxDefaultSize, - wxTE_MULTILINE | wxSUNKEN_BORDER); + wxTE_MULTILINE | wxTE_READONLY); + + // don't clutter the text window with time stamps + wxLog::DisableTimestamp(); + delete wxLog::SetActiveTarget(new wxLogTextCtrl(m_textWindow)); #if wxUSE_TOOLBAR CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL); @@ -203,6 +214,9 @@ MyFrame::~MyFrame() // and disconnect it to prevent accessing already deleted m_textWindow in // the size event handler if it's called during destruction Disconnect(wxEVT_SIZE, wxSizeEventHandler(MyFrame::OnSize)); + + // also prevent its use as log target + delete wxLog::SetActiveTarget(NULL); } #if wxUSE_MENUS @@ -414,7 +428,8 @@ MyChild::MyChild(wxMDIParentFrame *parent) parent, wxID_ANY, wxString::Format("Child %u", ++ms_numChildren) - ) + ), + MenuEventLogger("child", this) { m_canvas = new MyCanvas(this, wxPoint(0, 0), GetClientSize()); diff --git a/samples/mdi/mdi.h b/samples/mdi/mdi.h index cadb23695c..59612e2e6e 100644 --- a/samples/mdi/mdi.h +++ b/samples/mdi/mdi.h @@ -37,8 +37,42 @@ private: wxDECLARE_EVENT_TABLE(); }; +// Helper class logging menu open/close events. +class MenuEventLogger +{ +public: + MenuEventLogger(const char* label, wxFrame* frame) + : m_label(label), + m_frame(frame) + { + } + +protected: + void LogMenuOpenClose(wxMenuEvent& event, const char *action) + { + event.Skip(); + + wxString what; + + wxMenu* const menu = event.GetMenu(); + if ( menu ) + what.Printf("Menu with title \"%s\"", menu->GetTitle()); + else + what = "Unknown menu"; + + wxLogMessage(m_frame, "%s was %s in the %s frame", + what, action, m_label); + } + + const wxString m_label; + wxFrame* const m_frame; + + wxDECLARE_NO_COPY_CLASS(MenuEventLogger); +}; + // Define a new frame -class MyFrame : public wxMDIParentFrame +class MyFrame : public wxMDIParentFrame, + private MenuEventLogger { public: MyFrame(); @@ -56,6 +90,9 @@ private: void OnQuit(wxCommandEvent& event); void OnCloseAll(wxCommandEvent& event); + void OnMenuOpen(wxMenuEvent& event) { LogMenuOpenClose(event, "opened"); } + void OnMenuClose(wxMenuEvent& event) { LogMenuOpenClose(event, "closed"); } + void OnClose(wxCloseEvent& event); wxTextCtrl *m_textWindow; @@ -63,7 +100,8 @@ private: wxDECLARE_EVENT_TABLE(); }; -class MyChild : public wxMDIChildFrame +class MyChild : public wxMDIChildFrame, + private MenuEventLogger { public: MyChild(wxMDIParentFrame *parent); @@ -82,6 +120,8 @@ private: void OnClose(wxCommandEvent& event); void OnSize(wxSizeEvent& event); void OnMove(wxMoveEvent& event); + void OnMenuOpen(wxMenuEvent& event) { LogMenuOpenClose(event, "opened"); } + void OnMenuClose(wxMenuEvent& event) { LogMenuOpenClose(event, "closed"); } void OnCloseWindow(wxCloseEvent& event); #if wxUSE_CLIPBOARD diff --git a/src/msw/mdi.cpp b/src/msw/mdi.cpp index 725d47ab49..b54b58580a 100644 --- a/src/msw/mdi.cpp +++ b/src/msw/mdi.cpp @@ -447,6 +447,20 @@ wxMenuItem *wxMDIParentFrame::FindItemInMenuBar(int menuId) const return item; } +wxMenu* wxMDIParentFrame::MSWFindMenuFromHMENU(WXHMENU hMenu) +{ + wxMenu* menu = GetActiveChild() + ? GetActiveChild()->MSWFindMenuFromHMENU(hMenu) + : NULL; + if ( !menu ) + menu = wxFrame::MSWFindMenuFromHMENU(hMenu); + + if ( !menu && m_windowMenu && GetHmenuOf(m_windowMenu) == hMenu ) + menu = m_windowMenu; + + return menu; +} + WXHMENU wxMDIParentFrame::MSWGetActiveMenu() const { wxMDIChildFrame * const child = GetActiveChild();