X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1311c7a9bbaefda6b68eee5c32c3309f163a8861..0492c5a094d1baac126331385d66d2f66aa5db52:/src/msw/menu.cpp diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index d3dcc65044..77923bb06a 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -9,14 +9,6 @@ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// - -// ============================================================================ -// headers & declarations -// ============================================================================ - -// wxWindows headers -// ----------------- - #ifdef __GNUG__ #pragma implementation "menu.h" #endif @@ -34,8 +26,8 @@ #include "wx/utils.h" #endif -#if USE_OWNER_DRAWN -#include "wx/ownerdrw.h" +#if wxUSE_OWNER_DRAWN + #include "wx/ownerdrw.h" #endif #include "wx/msw/private.h" @@ -47,9 +39,19 @@ // ---------------------- #include +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the (popup) menu title has this special id +static const int idMenuTitle = -2; + +// ---------------------------------------------------------------------------- +// wxWindows macros +// ---------------------------------------------------------------------------- #if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxWindow) -IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow) + IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) + IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler) #endif // ============================================================================ @@ -71,9 +73,11 @@ wxMenu::wxMenu(const wxString& Title, const wxFunction func) m_hMenu = (WXHMENU) CreatePopupMenu(); m_savehMenu = 0 ; m_topLevelMenu = this; + m_clientData = (void*) NULL; + if (m_title != "") { - Append(-2, m_title) ; + Append(idMenuTitle, m_title) ; AppendSeparator() ; } @@ -81,7 +85,7 @@ wxMenu::wxMenu(const wxString& Title, const wxFunction func) } // The wxWindow destructor will take care of deleting the submenus. -wxMenu::~wxMenu(void) +wxMenu::~wxMenu() { if (m_hMenu) DestroyMenu((HMENU) m_hMenu); @@ -131,7 +135,7 @@ wxMenu::~wxMenu(void) */ } -void wxMenu::Break(void) +void wxMenu::Break() { m_doBreak = TRUE ; } @@ -158,7 +162,7 @@ void wxMenu::Append(wxMenuItem *pItem) UINT id; wxMenu *SubMenu = pItem->GetSubMenu(); if ( SubMenu != NULL ) { - wxASSERT( SubMenu->m_hMenu != NULL ); + wxASSERT( SubMenu->m_hMenu != (WXHMENU) NULL ); id = (UINT)SubMenu->m_hMenu; @@ -174,9 +178,8 @@ void wxMenu::Append(wxMenuItem *pItem) } LPCSTR pData; - wxString name(""); -#if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages? // item draws itself, pass pointer to it in data parameter flags |= MF_OWNERDRAW; @@ -187,27 +190,25 @@ void wxMenu::Append(wxMenuItem *pItem) { // menu is just a normal string (passed in data parameter) flags |= MF_STRING; - name = pItem->GetName(); - pData = (const char*) name; + pData = pItem->GetName(); } - // VZ: what does this magic -2 mean? I just copied the code but have no idea - // about what it does... ### - if ( pItem->GetId() == -2 ) { - flags |= MF_DISABLED | MF_GRAYED; + // visually select the menu title + if ( id == idMenuTitle ) + { + // TODO use SetMenuItemInfo(MFS_DEFAULT) to put it in bold face } HMENU hMenu = (HMENU)((m_hMenu == 0) ? m_savehMenu : m_hMenu); - if ( !AppendMenu(hMenu, flags, id, pData) ) { - // wxLogLastError("AppendMenu"); + wxLogLastError("AppendMenu"); } m_noItems++; } -void wxMenu::AppendSeparator(void) +void wxMenu::AppendSeparator() { Append(new wxMenuItem(this, ID_SEPARATOR)); } @@ -230,10 +231,10 @@ void wxMenu::Append(int Id, const wxString& label, void wxMenu::Delete(int id) { wxNode *node; - wxMenuItem *item; int pos; HMENU menu; + wxMenuItem *item = NULL; for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) { item = (wxMenuItem *)node->Data(); if (item->GetId() == id) @@ -300,18 +301,64 @@ bool wxMenu::Checked(int Id) const void wxMenu::SetTitle(const wxString& label) { - m_title = label ; - if (m_hMenu) - ModifyMenu((HMENU)m_hMenu, 0, - MF_BYPOSITION | MF_STRING | MF_DISABLED, - (UINT)-2, (const char *)m_title); - else if (m_savehMenu) - ModifyMenu((HMENU)m_savehMenu, 0, - MF_BYPOSITION | MF_STRING | MF_DISABLED, - (UINT)-2, (const char *)m_title); + bool hasNoTitle = m_title.IsEmpty(); + m_title = label; + + HMENU hMenu = (HMENU)((m_hMenu == 0) ? m_savehMenu : m_hMenu); + + if ( hasNoTitle ) + { + if ( !label.IsEmpty() ) + { + if ( !InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, + (unsigned)idMenuTitle, m_title) || + !InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) ) + { + wxLogLastError("InsertMenu"); + } + } + } + else + { + if ( label.IsEmpty() ) + { + // remove the title and the separator after it + if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) || + !RemoveMenu(hMenu, 0, MF_BYPOSITION) ) + { + wxLogLastError("RemoveMenu"); + } + } + else + { + // modify the title + if ( !ModifyMenu(hMenu, 0u, + MF_BYPOSITION | MF_STRING, + (unsigned)idMenuTitle, m_title) ) + { + wxLogLastError("ModifyMenu"); + } + } + } + +#ifndef __WIN16__ + // put the title string in bold face + if ( !m_title.IsEmpty() ) + { + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DEFAULT; + + if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) ) + { + wxLogLastError("SetMenuItemInfo"); + } + } +#endif } -const wxString& wxMenu::GetTitle() const +const wxString wxMenu::GetTitle() const { return m_title; } @@ -356,8 +403,9 @@ void wxMenu::SetLabel(int Id, const wxString& label) item->SetName(label); } -wxString wxMenu::GetLabel(int Id) const +wxString wxMenu::GetLabel(int id) const { +/* static char tmp[128] ; int len; if (m_hMenu) @@ -368,16 +416,30 @@ wxString wxMenu::GetLabel(int Id) const len = 0 ; tmp[len] = '\0' ; return wxString(tmp) ; + +*/ + wxMenuItem *pItem = FindItemForId(id) ; + if (pItem) + return pItem->GetName() ; + else + return wxEmptyString; } -bool wxMenu::MSWCommand(const WXUINT WXUNUSED(param), const WXWORD id) +bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id) { - wxCommandEvent event(wxEVENT_TYPE_MENU_COMMAND); - event.SetEventObject( this ); - event.SetId( id ); - event.SetInt( id ); - ProcessCommand(event); - return TRUE; + // ignore commands from the menu title + + // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!! + if ( id != (WXWORD)idMenuTitle ) + { + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED); + event.SetEventObject( this ); + event.SetId( id ); + event.SetInt( id ); + ProcessCommand(event); + } + + return TRUE; } // Finds the item id matching the given string, -1 if not found. @@ -407,7 +469,7 @@ int wxMenu::FindItem (const wxString& itemString) const return -1; } -wxMenuItem *wxMenu::FindItemForId(const int itemId, wxMenu ** itemMenu) const +wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const { if (itemMenu) *itemMenu = NULL; @@ -435,18 +497,20 @@ wxMenuItem *wxMenu::FindItemForId(const int itemId, wxMenu ** itemMenu) const return NULL; } -void wxMenu::SetHelpString(const int itemId, const wxString& helpString) +void wxMenu::SetHelpString(int itemId, const wxString& helpString) { wxMenuItem *item = FindItemForId (itemId); if (item) item->SetHelp(helpString); } -wxString wxMenu::GetHelpString (const int itemId) const +wxString wxMenu::GetHelpString (int itemId) const { wxMenuItem *item = FindItemForId (itemId); - wxString str(""); - return (item == NULL) ? str : item->GetHelp(); + if (item) + return item->GetHelp(); + else + return wxEmptyString; } void wxMenu::ProcessCommand(wxCommandEvent & event) @@ -456,7 +520,7 @@ void wxMenu::ProcessCommand(wxCommandEvent & event) // Try a callback if (m_callback) { - (void) (*(m_callback)) (*this, event); + (void)(*(m_callback))(*this, event); processed = TRUE; } @@ -469,13 +533,14 @@ void wxMenu::ProcessCommand(wxCommandEvent & event) // Try the window the menu was popped up from (and up // through the hierarchy) if ( !processed && GetInvokingWindow()) - processed = GetInvokingWindow()->ProcessEvent(event); + processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event); } extern wxMenu *wxCurrentPopupMenu; -bool wxWindow::PopupMenu(wxMenu *menu, const int x, const int y) +bool wxWindow::PopupMenu(wxMenu *menu, int x, int y) { menu->SetInvokingWindow(this); + menu->UpdateUI(); HWND hWnd = (HWND) GetHWND(); HMENU hMenu = (HMENU)menu->m_hMenu; @@ -494,10 +559,19 @@ bool wxWindow::PopupMenu(wxMenu *menu, const int x, const int y) } // Menu Bar -wxMenuBar::wxMenuBar(void) +wxMenuBar::wxMenuBar() { m_eventHandler = this; + m_menuCount = 0; + m_menus = NULL; + m_titles = NULL; + m_menuBarFrame = NULL; + m_hMenu = 0; +} +wxMenuBar::wxMenuBar( long WXUNUSED(style) ) +{ + m_eventHandler = this; m_menuCount = 0; m_menus = NULL; m_titles = NULL; @@ -505,7 +579,7 @@ wxMenuBar::wxMenuBar(void) m_hMenu = 0; } -wxMenuBar::wxMenuBar(const int N, wxMenu *Menus[], const wxString Titles[]) +wxMenuBar::wxMenuBar(int N, wxMenu *Menus[], const wxString Titles[]) { m_eventHandler = this; m_menuCount = N; @@ -521,7 +595,7 @@ wxMenuBar::wxMenuBar(const int N, wxMenu *Menus[], const wxString Titles[]) m_hMenu = 0; } -wxMenuBar::~wxMenuBar(void) +wxMenuBar::~wxMenuBar() { // In fact, don't want menu to be destroyed before MDI // shuffling has taken place. Let it be destroyed @@ -562,7 +636,7 @@ wxMenuBar::~wxMenuBar(void) // Must only be used AFTER menu has been attached to frame, // otherwise use individual menus to enable/disable items -void wxMenuBar::Enable(const int Id, const bool Flag) +void wxMenuBar::Enable(int Id, bool Flag) { int ms_flag; if (Flag) @@ -582,7 +656,7 @@ void wxMenuBar::Enable(const int Id, const bool Flag) } -void wxMenuBar::EnableTop(const int pos, const bool flag) +void wxMenuBar::EnableTop(int pos, bool flag) { int ms_flag; if (flag) @@ -596,7 +670,7 @@ void wxMenuBar::EnableTop(const int pos, const bool flag) // Must only be used AFTER menu has been attached to frame, // otherwise use individual menus -void wxMenuBar::Check(const int Id, const bool Flag) +void wxMenuBar::Check(int Id, bool Flag) { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(Id, &itemMenu) ; @@ -619,14 +693,14 @@ void wxMenuBar::Check(const int Id, const bool Flag) // CheckMenuItem((HMENU)m_hMenu, Id, MF_BYCOMMAND | ms_flag); } -bool wxMenuBar::Checked(const int Id) const +bool wxMenuBar::Checked(int Id) const { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(Id, &itemMenu) ; if (!item) return FALSE; - int Flag ; + int Flag = 0; if (itemMenu->m_hMenu) Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ; @@ -641,7 +715,7 @@ bool wxMenuBar::Checked(const int Id) const return FALSE ; } -bool wxMenuBar::Enabled(const int Id) const +bool wxMenuBar::Enabled(int Id) const { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(Id, &itemMenu) ; @@ -662,7 +736,7 @@ bool wxMenuBar::Enabled(const int Id) const } -void wxMenuBar::SetLabel(const int Id, const wxString& label) +void wxMenuBar::SetLabel(int Id, const wxString& label) { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(Id, &itemMenu) ; @@ -682,7 +756,7 @@ void wxMenuBar::SetLabel(const int Id, const wxString& label) } } -wxString wxMenuBar::GetLabel(const int Id) const +wxString wxMenuBar::GetLabel(int Id) const { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(Id, &itemMenu) ; @@ -706,7 +780,7 @@ wxString wxMenuBar::GetLabel(const int Id) const return wxString(tmp) ; } -void wxMenuBar::SetLabelTop(const int pos, const wxString& label) +void wxMenuBar::SetLabelTop(int pos, const wxString& label) { UINT was_flag = GetMenuState((HMENU)m_hMenu,pos,MF_BYPOSITION) ; if (was_flag&MF_POPUP) @@ -719,7 +793,7 @@ void wxMenuBar::SetLabelTop(const int pos, const wxString& label) ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,pos,(const char *)label) ; } -wxString wxMenuBar::GetLabelTop(const int pos) const +wxString wxMenuBar::GetLabelTop(int pos) const { static char tmp[128] ; int len = GetMenuString((HMENU)m_hMenu,pos,tmp,127,MF_BYPOSITION) ; @@ -727,7 +801,7 @@ wxString wxMenuBar::GetLabelTop(const int pos) const return wxString(tmp); } -bool wxMenuBar::OnDelete(wxMenu *a_menu, const int pos) +bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos) { if (!m_menuBarFrame) return TRUE; @@ -796,7 +870,7 @@ void wxMenuBar::Append (wxMenu * menu, const wxString& title) ((wxMenu *)menu)->SetParent(this); } -void wxMenuBar::Delete(wxMenu * menu, const int i) +void wxMenuBar::Delete(wxMenu * menu, int i) { int j; int ii = (int) i; @@ -843,7 +917,7 @@ int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemStr return -1; } -wxMenuItem *wxMenuBar::FindItemForId (const int Id, wxMenu ** itemMenu) const +wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const { if (itemMenu) *itemMenu = NULL; @@ -851,12 +925,15 @@ wxMenuItem *wxMenuBar::FindItemForId (const int Id, wxMenu ** itemMenu) const wxMenuItem *item = NULL; int i; for (i = 0; i < m_menuCount; i++) - if ((item = m_menus[i]->FindItemForId (Id, itemMenu))) + { + item = m_menus[i]->FindItemForId (Id, itemMenu); + if (item) return item; + } return NULL; } -void wxMenuBar::SetHelpString (const int Id, const wxString& helpString) +void wxMenuBar::SetHelpString (int Id, const wxString& helpString) { int i; for (i = 0; i < m_menuCount; i++) @@ -869,7 +946,7 @@ void wxMenuBar::SetHelpString (const int Id, const wxString& helpString) } } -wxString wxMenuBar::GetHelpString (const int Id) const +wxString wxMenuBar::GetHelpString (int Id) const { int i; for (i = 0; i < m_menuCount; i++) @@ -899,3 +976,42 @@ WXHMENU wxMenu::GetHMenu() const return 0; } +// Update a menu and all submenus recursively. +// source is the object that has the update event handlers +// defined for it. If NULL, the menu or associated window +// will be used. +void wxMenu::UpdateUI(wxEvtHandler* source) +{ + if (!source && GetInvokingWindow()) + source = GetInvokingWindow()->GetEventHandler(); + if (!source) + source = GetEventHandler(); + if (!source) + source = this; + + wxNode* node = GetItems().First(); + while (node) + { + wxMenuItem* item = (wxMenuItem*) node->Data(); + if ( !item->IsSeparator() ) + { + wxWindowID id = item->GetId(); + wxUpdateUIEvent event(id); + event.SetEventObject( source ); + + if (source->ProcessEvent(event)) + { + if (event.GetSetText()) + SetLabel(id, event.GetText()); + if (event.GetSetChecked()) + Check(id, event.GetChecked()); + if (event.GetSetEnabled()) + Enable(id, event.GetEnabled()); + } + + if (item->GetSubMenu()) + item->GetSubMenu()->UpdateUI(source); + } + node = node->Next(); + } +}