diff --git a/include/wx/frame.h b/include/wx/frame.h index d63f32afdd..f716bc6caa 100644 --- a/include/wx/frame.h +++ b/include/wx/frame.h @@ -173,7 +173,7 @@ public: // show help text for the currently selected menu or toolbar item // (typically in the status bar) or hide it and restore the status bar text // originally shown before the menu was opened if show == false - virtual void DoGiveHelp(const wxString& text, bool show) wxOVERRIDE; + virtual void DoGiveHelp(const wxString& text, bool show); #endif virtual bool IsClientAreaChild(const wxWindow *child) const wxOVERRIDE diff --git a/include/wx/msw/frame.h b/include/wx/msw/frame.h index 54ad3beec4..9a0639e818 100644 --- a/include/wx/msw/frame.h +++ b/include/wx/msw/frame.h @@ -104,6 +104,9 @@ public: // normal frames but is overridden by wxMDIParentFrame virtual WXHMENU MSWGetActiveMenu() const { return m_hMenu; } + virtual bool HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu); + virtual bool DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup); + // Look up the menu in the menu bar. virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu); #endif // wxUSE_MENUS @@ -150,6 +153,10 @@ protected: #if wxUSE_MENUS // frame menu, NULL if none WXHMENU m_hMenu; + + // The number of currently opened menus: 0 initially, 1 when a top level + // menu is opened, 2 when its submenu is opened and so on. + int m_menuDepth; #endif // wxUSE_MENUS private: diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 5692a86383..93427a7a45 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -121,22 +121,6 @@ public: // returns true if the platform should explicitly apply a theme border virtual bool CanApplyThemeBorder() const { return false; } -#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) - bool HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu); - - // handle WM_EXITMENULOOP message for Win95 only - bool HandleExitMenuLoop(WXWORD isPopup); - - // handle WM_(UN)INITMENUPOPUP message to generate wxEVT_MENU_OPEN/CLOSE - bool HandleMenuPopup(wxEventType evtType, WXHMENU hMenu); - - // Command part of HandleMenuPopup() and HandleExitMenuLoop(). - bool DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup); - - // Find the menu corresponding to the given handle. - virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu); -#endif // wxUSE_MENUS && !__WXUNIVERSAL__ - protected: // common part of all ctors void Init(); @@ -251,10 +235,6 @@ private: // MSWGetSystemMenu(). Owned by this window. wxMenu *m_menuSystem; - // The number of currently opened menus: 0 initially, 1 when a top level - // menu is opened, 2 when its submenu is opened and so on. - int m_menuDepth; - DECLARE_EVENT_TABLE() wxDECLARE_NO_COPY_CLASS(wxTopLevelWindowMSW); }; diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 1ece90cae0..294f12aa22 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -535,6 +535,19 @@ public: // behaviour virtual void OnInternalIdle(); +#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) + virtual bool HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu); + + // handle WM_(UN)INITMENUPOPUP message to generate wxEVT_MENU_OPEN/CLOSE + bool HandleMenuPopup(wxEventType evtType, WXHMENU hMenu); + + // Command part of HandleMenuPopup() and HandleExitMenuLoop(). + virtual bool DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup); + + // Find the menu corresponding to the given handle. + virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu); +#endif // wxUSE_MENUS && !__WXUNIVERSAL__ + protected: // this allows you to implement standard control borders without // repeating the code in different classes that are not derived from diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h index cec7501ca2..394acdcafa 100644 --- a/include/wx/toplevel.h +++ b/include/wx/toplevel.h @@ -292,13 +292,6 @@ public: virtual void SetRepresentedFilename(const wxString& WXUNUSED(filename)) { } -#if wxUSE_MENUS || wxUSE_TOOLBAR - // show help text for the currently selected menu or toolbar item - // (typically in the status bar) or hide it and restore the status bar text - // originally shown before the menu was opened if show == false - virtual void DoGiveHelp(const wxString& WXUNUSED(text), bool WXUNUSED(show)) {} -#endif - protected: // the frame client to screen translation should take account of the // toolbar which may shift the origin of the client area diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp index 113420452e..d83b52e725 100644 --- a/src/msw/frame.cpp +++ b/src/msw/frame.cpp @@ -96,6 +96,7 @@ void wxFrame::Init() { #if wxUSE_MENUS m_hMenu = NULL; + m_menuDepth = 0; #endif // wxUSE_MENUS #if wxUSE_TOOLTIPS @@ -429,12 +430,52 @@ void wxFrame::InternalSetMenuBar() #endif // wxUSE_MENUS_NATIVE -#if wxUSE_MENUS +#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) +bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) +{ + // Unfortunately we need to ignore a message which is sent after + // closing the currently active submenu of the menu bar by pressing Escape: + // in this case we get WM_UNINITMENUPOPUP, from which we generate + // wxEVT_MENU_CLOSE, and _then_ we get WM_MENUSELECT for the top level menu + // from which we overwrite the help string just restored by OnMenuClose() + // handler in wxFrameBase. To prevent this from happening we discard these + // messages but only in the case it's really the top level menu as we still + // need to clear the help string when a submenu is selected in a menu. + if ( flags == (MF_POPUP | MF_HILITE) && !m_menuDepth ) + return false; + + return wxWindow::HandleMenuSelect(nItem, flags, hMenu); +} + +bool wxFrame::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup) +{ + // Update the menu depth when dealing with the top level menus. + if ( !popup ) + { + if ( evtType == wxEVT_MENU_OPEN ) + { + m_menuDepth++; + } + else if ( evtType == wxEVT_MENU_CLOSE ) + { + wxASSERT_MSG( m_menuDepth > 0, wxS("No open menus?") ); + + m_menuDepth--; + } + else + { + wxFAIL_MSG( wxS("Unexpected menu event type") ); + } + } + + return wxWindow::DoSendMenuOpenCloseEvent(evtType, menu, popup); +} + wxMenu* wxFrame::MSWFindMenuFromHMENU(WXHMENU hMenu) { return GetMenuBar() ? GetMenuBar()->MSWGetMenu(hMenu) : NULL; } -#endif // wxUSE_MENUS +#endif // wxUSE_MENUS && !defined(__WXUNIVERSAL__) // Responds to colour changes, and passes event on to children. void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index eb461ecc8f..028660b1f6 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -63,15 +63,6 @@ #define ICON_SMALL 0 #endif -// ---------------------------------------------------------------------------- -// globals -// ---------------------------------------------------------------------------- - -#if wxUSE_MENUS || wxUSE_MENUS_NATIVE - extern wxMenu *wxCurrentPopupMenu; -#endif // wxUSE_MENUS || wxUSE_MENUS_NATIVE - - // ---------------------------------------------------------------------------- // stubs for missing functions under MicroWindows // ---------------------------------------------------------------------------- @@ -153,7 +144,6 @@ void wxTopLevelWindowMSW::Init() #endif m_menuSystem = NULL; - m_menuDepth = 0; } WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const @@ -424,38 +414,6 @@ WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WX #endif // #ifndef __WXUNIVERSAL__ } break; - -#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) -#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) - case WM_INITMENUPOPUP: - processed = HandleMenuPopup(wxEVT_MENU_OPEN, (WXHMENU)wParam); - break; - - case WM_MENUSELECT: - { - WXWORD item, flags; - WXHMENU hmenu; - UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu); - - processed = HandleMenuSelect(item, flags, hmenu); - } - break; - - case WM_EXITMENULOOP: - // Under Windows 98 and 2000 and later we're going to get - // WM_UNINITMENUPOPUP which will be used to generate this event - // with more information (notably the menu that was closed) so we - // only need this one under old Windows systems where the newer - // event is never sent. - if ( wxGetWinVersion() < wxWinVersion_98 ) - processed = HandleExitMenuLoop(wParam); - break; - - case WM_UNINITMENUPOPUP: - processed = HandleMenuPopup(wxEVT_MENU_CLOSE, (WXHMENU)wParam); - break; -#endif // wxUSE_MENUS && !__WXUNIVERSAL__ -#endif // !__WXMICROWIN__ } if ( !processed ) @@ -1476,117 +1434,6 @@ void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event) } } -#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) - -bool -wxTopLevelWindowMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) -{ - // Ignore the special messages generated when the menu is closed (this is - // the only case when the flags are set to -1), in particular don't clear - // the help string in the status bar when this happens as it had just been - // restored by the base class code. - if ( !hMenu && flags == 0xffff ) - return false; - - // Unfortunately we also need to ignore another message which is sent after - // closing the currently active submenu of the menu bar by pressing Escape: - // in this case we get WM_UNINITMENUPOPUP, from which we generate - // wxEVT_MENU_CLOSE, and _then_ we get WM_MENUSELECT for the top level menu - // from which we overwrite the help string just restored by OnMenuClose() - // handler in wxFrameBase. To prevent this from happening we discard these - // messages but only in the case it's really the top level menu as we still - // need to clear the help string when a submenu is selected in a menu. - if ( flags == (MF_POPUP | MF_HILITE) && !m_menuDepth ) - return false; - - // sign extend to int from unsigned short we get from Windows - int item = (signed short)nItem; - - // WM_MENUSELECT is generated for both normal items and menus, including - // the top level menus of the menu bar, which can't be represented using - // any valid identifier in wxMenuEvent so use an otherwise unused value for - // them - if ( flags & (MF_POPUP | MF_SEPARATOR) ) - item = wxID_NONE; - - wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item); - event.SetEventObject(this); - - if ( HandleWindowEvent(event) ) - return true; - - // by default, i.e. if the event wasn't handled above, clear the status bar - // text when an item which can't have any associated help string in wx API - // is selected - if ( item == wxID_NONE ) - DoGiveHelp(wxEmptyString, true); - - return false; -} - -bool -wxTopLevelWindowMSW::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup) -{ - // Update the menu depth when dealing with the top level menus. - if ( !popup ) - { - if ( evtType == wxEVT_MENU_OPEN ) - { - m_menuDepth++; - } - else if ( evtType == wxEVT_MENU_CLOSE ) - { - wxASSERT_MSG( m_menuDepth > 0, wxS("No open menus?") ); - - m_menuDepth--; - } - else - { - wxFAIL_MSG( wxS("Unexpected menu event type") ); - } - } - - wxMenuEvent event(evtType, popup ? wxID_ANY : 0, menu); - event.SetEventObject(menu); - - return HandleWindowEvent(event); -} - -bool wxTopLevelWindowMSW::HandleExitMenuLoop(WXWORD isPopup) -{ - return DoSendMenuOpenCloseEvent(wxEVT_MENU_CLOSE, - isPopup ? wxCurrentPopupMenu : NULL, - isPopup != 0); -} - -bool wxTopLevelWindowMSW::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu) -{ - bool isPopup = false; - wxMenu* menu = NULL; - if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetHMenu() == hMenu ) - { - menu = wxCurrentPopupMenu; - isPopup = true; - } - else - { - menu = MSWFindMenuFromHMENU(hMenu); - } - - - return DoSendMenuOpenCloseEvent(evtType, menu, isPopup); -} - -wxMenu* wxTopLevelWindowMSW::MSWFindMenuFromHMENU(WXHMENU WXUNUSED(hMenu)) -{ - // We don't have any menus at this level. - return NULL; -} - -#endif // wxUSE_MENUS && !__WXUNIVERSAL__ - - - // the DialogProc for all wxWidgets dialogs LONG APIENTRY _EXPORT wxDlgProc(HWND hDlg, diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 72c8d1d093..12655d3c1a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2273,6 +2273,86 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) #endif // wxUSE_MENUS_NATIVE +// --------------------------------------------------------------------------- +// menu events +// --------------------------------------------------------------------------- + +#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) + +bool +wxWindowMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) +{ + // Ignore the special messages generated when the menu is closed (this is + // the only case when the flags are set to -1), in particular don't clear + // the help string in the status bar when this happens as it had just been + // restored by the base class code. + if ( !hMenu && flags == 0xffff ) + return false; + + // sign extend to int from unsigned short we get from Windows + int item = (signed short)nItem; + + // WM_MENUSELECT is generated for both normal items and menus, including + // the top level menus of the menu bar, which can't be represented using + // any valid identifier in wxMenuEvent so use an otherwise unused value for + // them + if ( flags & (MF_POPUP | MF_SEPARATOR) ) + item = wxID_NONE; + + wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item); + event.SetEventObject(this); + + if ( HandleWindowEvent(event) ) + return true; + + // by default, i.e. if the event wasn't handled above, clear the status bar + // text when an item which can't have any associated help string in wx API + // is selected + if ( item == wxID_NONE ) + { + wxFrame *frame = wxDynamicCast(wxGetTopLevelParent(this), wxFrame); + if ( frame ) + frame->DoGiveHelp(wxEmptyString, true); + } + + return false; +} + +bool +wxWindowMSW::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup) +{ + wxMenuEvent event(evtType, popup ? wxID_ANY : 0, menu); + event.SetEventObject(menu); + + return HandleWindowEvent(event); +} + +bool wxWindowMSW::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu) +{ + bool isPopup = false; + wxMenu* menu = NULL; + if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetHMenu() == hMenu ) + { + menu = wxCurrentPopupMenu; + isPopup = true; + } + else + { + menu = MSWFindMenuFromHMENU(hMenu); + } + + + return DoSendMenuOpenCloseEvent(evtType, menu, isPopup); +} + +wxMenu* wxWindowMSW::MSWFindMenuFromHMENU(WXHMENU WXUNUSED(hMenu)) +{ + // We don't have any menus at this level. + return NULL; +} + +#endif // wxUSE_MENUS && !defined(__WXUNIVERSAL__) + // =========================================================================== // pre/post message processing // =========================================================================== @@ -3470,7 +3550,7 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result, break; #endif -#if wxUSE_MENUS +#if wxUSE_MENUS && !defined(__WXUNIVERSAL__) case WM_MENUCHAR: // we're only interested in our own menus, not MF_SYSMENU if ( HIWORD(wParam) == MF_POPUP ) @@ -3484,7 +3564,27 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result, } } break; -#endif // wxUSE_MENUS + +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) + case WM_INITMENUPOPUP: + processed = HandleMenuPopup(wxEVT_MENU_OPEN, (WXHMENU)wParam); + break; + + case WM_MENUSELECT: + { + WXWORD item, flags; + WXHMENU hmenu; + UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu); + + processed = HandleMenuSelect(item, flags, hmenu); + } + break; + + case WM_UNINITMENUPOPUP: + processed = HandleMenuPopup(wxEVT_MENU_CLOSE, (WXHMENU)wParam); + break; +#endif // !__WXMICROWIN__ +#endif // wxUSE_MENUS && !defined(__WXUNIVERSAL__) #ifndef __WXWINCE__ case WM_POWERBROADCAST: