Handle WM_*MENU* events in wxWindow.
Contrary to MSDN implications, at least some of these messages are not actually sent to the TLW for popup menus, but to the owning window or even its parent window (!). Move the handling of these events from wxTLW to wxWindow. Move menu depth tracking to wxFrame, because it only makes sense for frame's menus and move DoGiveHelp() from wxTLW to wxFrame. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76721 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
8847a9f499
commit
3821abef51
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user