1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "menu.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
38 #include "wx/ownerdrw.h"
41 #include "wx/msw/private.h"
42 #include "wx/msw/menu.h"
43 #include "wx/menuitem.h"
46 // other standard headers
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 extern wxMenu
*wxCurrentPopupMenu
;
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // the (popup) menu title has this special id
60 static const int idMenuTitle
= -2;
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 #if !USE_SHARED_LIBRARY
67 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
68 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
72 #define GetHMENU() ((HMENU)GetHMenu())
73 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
75 // ============================================================================
77 // ============================================================================
79 // ---------------------------------------------------------------------------
80 // wxMenu construction, adding and removing menu items
81 // ---------------------------------------------------------------------------
83 // Construct a menu with optional title (then use append)
84 wxMenu::wxMenu(const wxString
& title
, const wxFunction func
)
88 m_eventHandler
= this;
89 m_pInvokingWindow
= NULL
;
93 m_hMenu
= (WXHMENU
) CreatePopupMenu();
95 m_topLevelMenu
= this;
96 m_clientData
= (void*) NULL
;
100 Append(idMenuTitle
, m_title
) ;
104 #if WXWIN_COMPATIBILITY
109 // The wxWindow destructor will take care of deleting the submenus.
112 // free Windows resources
115 ::DestroyMenu((HMENU
)m_hMenu
);
120 wxNode
*node
= m_menuItems
.First();
123 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
125 // Delete child menus.
126 // Beware: they must not be appended to children list!!!
127 // (because order of delete is significant)
128 if ( item
->IsSubMenu() )
129 item
->DeleteSubMenu();
131 wxNode
*next
= node
->Next();
143 // function appends a new item or submenu to the menu
144 void wxMenu::Append(wxMenuItem
*pItem
)
146 wxCHECK_RET( pItem
!= NULL
, "can't append NULL item to the menu" );
148 // check for accelerators: they are given after '\t'
149 wxString label
= pItem
->GetName();
150 int posTab
= label
.Find('\t');
151 if ( posTab
!= wxNOT_FOUND
) {
152 // parse the accelerator string
154 int accelFlags
= wxACCEL_NORMAL
;
156 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
157 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
158 if ( current
== _("ctrl") )
159 accelFlags
|= wxACCEL_CTRL
;
160 else if ( current
== _("alt") )
161 accelFlags
|= wxACCEL_ALT
;
162 else if ( current
== _("shift") )
163 accelFlags
|= wxACCEL_SHIFT
;
165 wxLogDebug(_T("Unknown accel modifier: '%s'"),
172 current
+= wxTolower(label
[n
]);
176 if ( current
.IsEmpty() ) {
177 wxLogDebug(_T("No accel key found, accel string ignored."));
180 if ( current
.Len() == 1 ) {
182 keyCode
= wxToupper(current
[0]);
185 // it should be a function key
186 if ( current
[0] == 'f' && isdigit(current
[1]) &&
187 (current
.Len() == 2 ||
188 (current
.Len() == 3 && isdigit(current
[2]))) ) {
190 sscanf(current
.c_str() + 1, "%d", &n
);
192 keyCode
= VK_F1
+ n
- 1;
195 wxLogDebug(_T("Unreckognized accel key '%s', accel "
196 "string ignored."), current
.c_str());
203 m_accelKeyCodes
.Add(keyCode
);
204 m_accelFlags
.Add(accelFlags
);
205 m_accelIds
.Add(pItem
->GetId());
211 // if "Break" has just been called, insert a menu break before this item
212 // (and don't forget to reset the flag)
214 flags
|= MF_MENUBREAK
;
218 if ( pItem
->IsSeparator() ) {
219 flags
|= MF_SEPARATOR
;
222 // id is the numeric id for normal menu items and HMENU for submenus as
223 // required by ::AppendMenu() API
225 wxMenu
*submenu
= pItem
->GetSubMenu();
226 if ( submenu
!= NULL
) {
227 wxASSERT( submenu
->GetHMenu() != (WXHMENU
) NULL
);
229 id
= (UINT
)submenu
->GetHMenu();
230 submenu
->m_topLevelMenu
= m_topLevelMenu
;
231 submenu
->m_parent
= this;
232 submenu
->m_savehMenu
= (WXHMENU
)id
;
233 submenu
->m_hMenu
= 0;
243 #if wxUSE_OWNER_DRAWN
244 if ( pItem
->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
245 // item draws itself, pass pointer to it in data parameter
246 flags
|= MF_OWNERDRAW
;
247 pData
= (LPCSTR
)pItem
;
252 // menu is just a normal string (passed in data parameter)
257 if ( !::AppendMenu(GetHMENU(), flags
, id
, pData
) )
259 wxLogLastError("AppendMenu");
264 if ( id
== idMenuTitle
)
266 // visually select the menu title
268 mii
.cbSize
= sizeof(mii
);
269 mii
.fMask
= MIIM_STATE
;
270 mii
.fState
= MFS_DEFAULT
;
272 if ( !SetMenuItemInfo(GetHMENU(), (unsigned)id
, FALSE
, &mii
) )
274 wxLogLastError("SetMenuItemInfo");
279 m_menuItems
.Append(pItem
);
284 void wxMenu::AppendSeparator()
286 Append(new wxMenuItem(this, ID_SEPARATOR
));
290 void wxMenu::Append(int id
,
291 const wxString
& label
,
293 const wxString
& helpString
)
295 Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, SubMenu
));
298 // Ordinary menu item
299 void wxMenu::Append(int id
,
300 const wxString
& label
,
301 const wxString
& helpString
,
304 // 'checkable' parameter is useless for Windows.
305 Append(new wxMenuItem(this, id
, label
, helpString
, checkable
));
309 void wxMenu::Delete(int id
)
311 wxMenuItem
*item
= NULL
;
314 for (pos
= 0, node
= m_menuItems
.First(); node
; node
= node
->Next(), pos
++)
316 item
= (wxMenuItem
*)node
->Data();
317 if ( item
->GetId() == id
)
321 wxCHECK_RET( node
, "wxMenu::Delete(): item doesn't exist" );
323 HMENU menu
= GetHMENU();
325 wxMenu
*pSubMenu
= item
->GetSubMenu();
326 if ( pSubMenu
!= NULL
) {
327 RemoveMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
328 pSubMenu
->m_hMenu
= pSubMenu
->m_savehMenu
;
329 pSubMenu
->m_savehMenu
= 0;
330 pSubMenu
->m_parent
= NULL
;
331 // RemoveChild(item->subMenu);
332 pSubMenu
->m_topLevelMenu
= NULL
;
333 // TODO: Why isn't subMenu deleted here???
334 // Will put this in for now. Assuming this is supposed
335 // to delete the menu, not just remove it.
336 item
->DeleteSubMenu();
339 DeleteMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
342 m_menuItems
.DeleteNode(node
);
346 // ---------------------------------------------------------------------------
347 // accelerator helpers
348 // ---------------------------------------------------------------------------
350 // create the wxAcceleratorEntries for our accels and put them into provided
351 // array - return the number of accels we have
352 size_t wxMenu::CopyAccels(wxAcceleratorEntry
*accels
) const
354 size_t count
= GetAccelCount();
355 for ( size_t n
= 0; n
< count
; n
++ )
357 (*accels
++).Set(m_accelFlags
[n
], m_accelKeyCodes
[n
], m_accelIds
[n
]);
363 // ---------------------------------------------------------------------------
364 // wxMenu functions implemented in wxMenuItem
365 // ---------------------------------------------------------------------------
367 void wxMenu::Enable(int id
, bool Flag
)
369 wxMenuItem
*item
= FindItemForId(id
);
370 wxCHECK_RET( item
!= NULL
, "can't enable non-existing menu item" );
375 bool wxMenu::IsEnabled(int id
) const
377 wxMenuItem
*item
= FindItemForId(id
);
378 wxCHECK_MSG( item
!= NULL
, FALSE
, "invalid item id" );
380 return item
->IsEnabled();
383 void wxMenu::Check(int id
, bool Flag
)
385 wxMenuItem
*item
= FindItemForId(id
);
386 wxCHECK_RET( item
!= NULL
, "can't get status of non-existing menu item" );
391 bool wxMenu::IsChecked(int id
) const
393 wxMenuItem
*item
= FindItemForId(id
);
394 wxCHECK_MSG( item
!= NULL
, FALSE
, "invalid item id" );
396 return item
->IsChecked();
399 void wxMenu::SetLabel(int id
, const wxString
& label
)
401 wxMenuItem
*item
= FindItemForId(id
) ;
402 wxCHECK_RET( item
, "wxMenu::SetLabel: no such item" );
404 item
->SetName(label
);
407 wxString
wxMenu::GetLabel(int id
) const
410 wxMenuItem
*pItem
= FindItemForId(id
) ;
412 label
= pItem
->GetName() ;
414 wxFAIL_MSG("wxMenu::GetLabel: item doesn't exist");
419 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
)
421 wxMenuItem
*item
= FindItemForId (itemId
);
423 item
->SetHelp(helpString
);
425 wxFAIL_MSG("wxMenu::SetHelpString: item doesn't exist");
428 wxString
wxMenu::GetHelpString (int itemId
) const
431 wxMenuItem
*item
= FindItemForId (itemId
);
433 help
= item
->GetHelp();
435 wxFAIL_MSG("wxMenu::GetHelpString: item doesn't exist");
440 // ---------------------------------------------------------------------------
442 // ---------------------------------------------------------------------------
444 void wxMenu::SetTitle(const wxString
& label
)
446 bool hasNoTitle
= m_title
.IsEmpty();
449 HMENU hMenu
= GetHMENU();
453 if ( !label
.IsEmpty() )
455 if ( !InsertMenu(hMenu
, 0u, MF_BYPOSITION
| MF_STRING
,
456 (unsigned)idMenuTitle
, m_title
) ||
457 !InsertMenu(hMenu
, 1u, MF_BYPOSITION
, (unsigned)-1, NULL
) )
459 wxLogLastError("InsertMenu");
465 if ( label
.IsEmpty() )
467 // remove the title and the separator after it
468 if ( !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) ||
469 !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) )
471 wxLogLastError("RemoveMenu");
477 if ( !ModifyMenu(hMenu
, 0u,
478 MF_BYPOSITION
| MF_STRING
,
479 (unsigned)idMenuTitle
, m_title
) )
481 wxLogLastError("ModifyMenu");
487 // put the title string in bold face
488 if ( !m_title
.IsEmpty() )
491 mii
.cbSize
= sizeof(mii
);
492 mii
.fMask
= MIIM_STATE
;
493 mii
.fState
= MFS_DEFAULT
;
495 if ( !SetMenuItemInfo(hMenu
, (unsigned)idMenuTitle
, FALSE
, &mii
) )
497 wxLogLastError("SetMenuItemInfo");
503 const wxString
wxMenu::GetTitle() const
508 // ---------------------------------------------------------------------------
510 // ---------------------------------------------------------------------------
512 bool wxMenu::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD id
)
514 // ignore commands from the menu title
516 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
517 if ( id
!= (WXWORD
)idMenuTitle
)
519 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
520 event
.SetEventObject( this );
523 ProcessCommand(event
);
529 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
531 bool processed
= FALSE
;
533 #if WXWIN_COMPATIBILITY
537 (void)(*(m_callback
))(*this, event
);
540 #endif // WXWIN_COMPATIBILITY
542 // Try the menu's event handler
543 if ( !processed
&& GetEventHandler())
545 processed
= GetEventHandler()->ProcessEvent(event
);
548 // Try the window the menu was popped up from (and up through the
550 wxWindow
*win
= GetInvokingWindow();
551 if ( !processed
&& win
)
552 processed
= win
->GetEventHandler()->ProcessEvent(event
);
557 // ---------------------------------------------------------------------------
559 // ---------------------------------------------------------------------------
561 // Finds the item id matching the given string, -1 if not found.
562 int wxMenu::FindItem (const wxString
& itemString
) const
564 wxString itemLabel
= wxStripMenuCodes(itemString
);
565 for ( wxNode
*node
= m_menuItems
.First(); node
; node
= node
->Next() )
567 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
568 if ( item
->IsSubMenu() )
570 int ans
= item
->GetSubMenu()->FindItem(itemString
);
571 if ( ans
!= wxNOT_FOUND
)
574 else if ( !item
->IsSeparator() )
576 wxString label
= wxStripMenuCodes(item
->GetName());
577 if ( itemLabel
== label
)
578 return item
->GetId();
585 wxMenuItem
*wxMenu::FindItemForId(int itemId
, wxMenu
** itemMenu
) const
590 wxMenuItem
*item
= NULL
;
591 for ( wxNode
*node
= m_menuItems
.First(); node
&& !item
; node
= node
->Next() )
593 item
= (wxMenuItem
*)node
->Data();
595 if ( item
->GetId() == itemId
)
598 *itemMenu
= (wxMenu
*)this;
600 else if ( item
->IsSubMenu() )
602 item
= item
->GetSubMenu()->FindItemForId(itemId
, itemMenu
);
606 // don't exit the loop
614 // ---------------------------------------------------------------------------
616 // ---------------------------------------------------------------------------
618 bool wxWindow::PopupMenu(wxMenu
*menu
, int x
, int y
)
620 menu
->SetInvokingWindow(this);
623 HWND hWnd
= (HWND
) GetHWND();
624 HMENU hMenu
= (HMENU
)menu
->GetHMenu();
628 ::ClientToScreen(hWnd
, &point
);
629 wxCurrentPopupMenu
= menu
;
630 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
632 wxCurrentPopupMenu
= NULL
;
634 menu
->SetInvokingWindow(NULL
);
639 void wxMenu::Attach(wxMenuBar
*menubar
)
641 // menu can be in at most one menubar because otherwise they would both
642 // delete the menu pointer
643 wxASSERT_MSG( !m_menuBar
, "menu belongs to 2 menubars, expect a crash" );
646 m_savehMenu
= m_hMenu
;
650 void wxMenu::Detach()
652 wxASSERT_MSG( m_menuBar
, "can't detach menu if it's not attached" );
654 m_hMenu
= m_savehMenu
;
658 // ---------------------------------------------------------------------------
660 // ---------------------------------------------------------------------------
662 void wxMenuBar::Init()
664 m_eventHandler
= this;
668 m_menuBarFrame
= NULL
;
672 wxMenuBar::wxMenuBar()
677 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
682 wxMenuBar::wxMenuBar(int count
, wxMenu
*menus
[], const wxString titles
[])
688 m_titles
= new wxString
[count
];
691 for ( i
= 0; i
< count
; i
++ )
692 m_titles
[i
] = titles
[i
];
694 for ( i
= 0; i
< count
; i
++ )
695 m_menus
[i
]->Attach(this);
698 wxMenuBar::~wxMenuBar()
700 for ( int i
= 0; i
< m_menuCount
; i
++ )
709 // ---------------------------------------------------------------------------
711 // ---------------------------------------------------------------------------
713 void wxMenuBar::Refresh()
715 wxCHECK_RET( m_menuBarFrame
, "can't refresh a menubar withotu a frame" );
717 DrawMenuBar((HWND
)m_menuBarFrame
->GetHWND()) ;
720 WXHMENU
wxMenuBar::Create()
722 wxCHECK_MSG( !m_hMenu
, TRUE
, "menubar already created" );
724 m_hMenu
= (WXHMENU
)::CreateMenu();
728 wxLogLastError("CreateMenu");
732 for ( int i
= 0; i
< m_menuCount
; i
++ )
734 if ( !::AppendMenu((HMENU
)m_hMenu
, MF_POPUP
| MF_STRING
,
735 (UINT
)m_menus
[i
]->GetHMenu(),
738 wxLogLastError("AppendMenu");
746 // ---------------------------------------------------------------------------
747 // wxMenuBar functions forwarded to wxMenuItem
748 // ---------------------------------------------------------------------------
750 // Must only be used AFTER menu has been attached to frame,
751 // otherwise use individual menus to enable/disable items
752 void wxMenuBar::Enable(int id
, bool enable
)
754 wxMenu
*itemMenu
= NULL
;
755 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
757 wxCHECK_RET( item
, "attempt to enable an item which doesn't exist" );
759 item
->Enable(enable
);
762 void wxMenuBar::EnableTop(int pos
, bool enable
)
764 int flag
= enable
? MF_ENABLED
: MF_GRAYED
;;
766 EnableMenuItem((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
| flag
);
769 // Must only be used AFTER menu has been attached to frame,
770 // otherwise use individual menus
771 void wxMenuBar::Check(int id
, bool check
)
773 wxMenu
*itemMenu
= NULL
;
774 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
776 wxCHECK_RET( item
, "attempt to check an item which doesn't exist" );
777 wxCHECK_RET( item
->IsCheckable(), "attempt to check an uncheckable item" );
782 bool wxMenuBar::IsChecked(int id
) const
784 wxMenu
*itemMenu
= NULL
;
785 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
787 wxCHECK_MSG( item
, FALSE
, "wxMenuBar::IsChecked(): no such item" );
789 int flag
= ::GetMenuState(GetHMenuOf(itemMenu
), id
, MF_BYCOMMAND
);
791 return (flag
& MF_CHECKED
) != 0;
794 bool wxMenuBar::IsEnabled(int id
) const
796 wxMenu
*itemMenu
= NULL
;
797 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
799 wxCHECK_MSG( item
, FALSE
, "wxMenuBar::IsEnabled(): no such item" );
801 int flag
= ::GetMenuState(GetHMenuOf(itemMenu
), id
, MF_BYCOMMAND
) ;
803 return (flag
& MF_ENABLED
) != 0;
806 void wxMenuBar::SetLabel(int id
, const wxString
& label
)
808 wxMenu
*itemMenu
= NULL
;
809 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
811 wxCHECK_RET( item
, "wxMenuBar::SetLabel(): no such item" );
813 item
->SetName(label
);
816 wxString
wxMenuBar::GetLabel(int id
) const
818 wxMenu
*itemMenu
= NULL
;
819 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
821 wxCHECK_MSG( item
, "", "wxMenuBar::GetLabel(): no such item" );
823 return item
->GetName();
826 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
)
828 wxMenu
*itemMenu
= NULL
;
829 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
831 wxCHECK_RET( item
, "wxMenuBar::SetHelpString(): no such item" );
833 item
->SetHelp(helpString
);
836 wxString
wxMenuBar::GetHelpString (int id
) const
838 wxMenu
*itemMenu
= NULL
;
839 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
841 wxCHECK_MSG( item
, "", "wxMenuBar::GetHelpString(): no such item" );
843 return item
->GetHelp();
846 // ---------------------------------------------------------------------------
847 // wxMenuBar functions to work with the top level submenus
848 // ---------------------------------------------------------------------------
850 // NB: we don't support owner drawn top level items for now, if we do these
851 // functions would have to be changed to use wxMenuItem as well
853 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
)
856 UINT flagsOld
= ::GetMenuState((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
);
857 if ( flagsOld
== 0xFFFFFFFF )
859 wxLogLastError("GetMenuState");
864 if ( flagsOld
& MF_POPUP
)
866 // HIBYTE contains the number of items in the submenu in this case
868 id
= (UINT
)::GetSubMenu((HMENU
)m_hMenu
, pos
) ;
875 if ( ::ModifyMenu(GetHMENU(), pos
, MF_BYPOSITION
| MF_STRING
| flagsOld
,
876 id
, label
) == 0xFFFFFFFF )
878 wxLogLastError("ModifyMenu");
882 wxString
wxMenuBar::GetLabelTop(int pos
) const
884 int len
= ::GetMenuString((HMENU
)m_hMenu
, pos
, NULL
, 0, MF_BYCOMMAND
);
886 len
++; // for the NUL character
888 ::GetMenuString(GetHMENU(), pos
, label
.GetWriteBuf(len
), len
, MF_BYCOMMAND
);
889 label
.UngetWriteBuf();
894 // ---------------------------------------------------------------------------
895 // wxMenuBar notifications
896 // ---------------------------------------------------------------------------
898 bool wxMenuBar::OnDelete(wxMenu
*a_menu
, int pos
)
900 if ( !m_menuBarFrame
)
903 if ( ::RemoveMenu((HMENU
)m_hMenu
, (UINT
)pos
, MF_BYPOSITION
) )
905 // VZ: I'm not sure about what's going on here, so I leave an assert
906 wxASSERT_MSG( m_menus
[pos
] == a_menu
, "what is this parameter for??" );
910 if ( m_menuBarFrame
)
917 wxLogLastError("RemoveMenu");
923 bool wxMenuBar::OnAppend(wxMenu
*a_menu
, const char *title
)
925 WXHMENU submenu
= a_menu
->GetHMenu();
929 if ( !m_menuBarFrame
)
932 a_menu
->Attach(this);
934 if ( !::AppendMenu(GetHMENU(), MF_POPUP
| MF_STRING
,
935 (UINT
)submenu
, title
) )
937 wxLogLastError("AppendMenu");
945 // ---------------------------------------------------------------------------
946 // wxMenuBar construction
947 // ---------------------------------------------------------------------------
949 void wxMenuBar::Append (wxMenu
* menu
, const wxString
& title
)
951 if (!OnAppend(menu
, title
))
955 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
956 wxString
*new_titles
= new wxString
[m_menuCount
];
959 for (i
= 0; i
< m_menuCount
- 1; i
++)
961 new_menus
[i
] = m_menus
[i
];
963 new_titles
[i
] = m_titles
[i
];
972 m_titles
= new_titles
;
974 m_menus
[m_menuCount
- 1] = (wxMenu
*)menu
;
975 m_titles
[m_menuCount
- 1] = title
;
977 menu
->SetParent(this);
980 void wxMenuBar::Delete(wxMenu
* menu
, int i
)
986 for (ii
= 0; ii
< m_menuCount
; ii
++) {
987 if (m_menus
[ii
] == menu
)
990 if (ii
>= m_menuCount
)
993 if (ii
< 0 || ii
>= m_menuCount
)
998 if (!OnDelete(menu
, ii
))
1001 menu
->SetParent(NULL
);
1004 for (j
= ii
; j
< m_menuCount
; j
++) {
1005 m_menus
[j
] = m_menus
[j
+ 1];
1006 m_titles
[j
] = m_titles
[j
+ 1];
1010 void wxMenuBar::Attach(wxFrame
*frame
)
1012 wxASSERT_MSG( !m_menuBarFrame
, _T("menubar already attached!") );
1014 m_menuBarFrame
= frame
;
1016 // create the accel table - we consider that the toolbar construction is
1018 size_t nAccelCount
= 0;
1020 for ( i
= 0; i
< m_menuCount
; i
++ )
1022 nAccelCount
+= m_menus
[i
]->GetAccelCount();
1025 wxAcceleratorEntry
*accelEntries
= new wxAcceleratorEntry
[nAccelCount
];
1028 for ( i
= 0; i
< m_menuCount
; i
++ )
1030 nAccelCount
+= m_menus
[i
]->CopyAccels(&accelEntries
[nAccelCount
]);
1033 m_accelTable
= wxAcceleratorTable(nAccelCount
, accelEntries
);
1035 delete [] accelEntries
;
1038 // ---------------------------------------------------------------------------
1039 // wxMenuBar searching for menu items
1040 // ---------------------------------------------------------------------------
1042 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1043 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1044 const wxString
& itemString
) const
1046 wxString menuLabel
= wxStripMenuCodes(menuString
);
1047 for ( int i
= 0; i
< m_menuCount
; i
++ )
1049 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1050 if ( menuString
== title
)
1051 return m_menus
[i
]->FindItem(itemString
);
1057 wxMenuItem
*wxMenuBar::FindItemForId (int id
, wxMenu
**itemMenu
) const
1062 wxMenuItem
*item
= NULL
;
1063 for ( int i
= 0; !item
&& (i
< m_menuCount
); i
++ )
1065 item
= m_menus
[i
]->FindItemForId(id
, itemMenu
);
1072 // ----------------------------------------------------------------------------
1074 // ----------------------------------------------------------------------------
1076 wxWindow
*wxMenu::GetWindow() const
1078 if ( m_pInvokingWindow
!= NULL
)
1079 return m_pInvokingWindow
;
1080 else if ( m_menuBar
!= NULL
)
1081 return m_menuBar
->GetFrame();
1086 WXHMENU
wxMenu::GetHMenu() const
1090 else if ( m_savehMenu
!= 0 )
1093 wxFAIL_MSG("wxMenu without HMENU");
1098 // Update a menu and all submenus recursively. source is the object that has
1099 // the update event handlers defined for it. If NULL, the menu or associated
1100 // window will be used.
1101 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1103 if (!source
&& GetInvokingWindow())
1104 source
= GetInvokingWindow()->GetEventHandler();
1106 source
= GetEventHandler();
1110 wxNode
* node
= GetItems().First();
1113 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1114 if ( !item
->IsSeparator() )
1116 wxWindowID id
= item
->GetId();
1117 wxUpdateUIEvent
event(id
);
1118 event
.SetEventObject( source
);
1120 if (source
->ProcessEvent(event
))
1122 if (event
.GetSetText())
1123 SetLabel(id
, event
.GetText());
1124 if (event
.GetSetChecked())
1125 Check(id
, event
.GetChecked());
1126 if (event
.GetSetEnabled())
1127 Enable(id
, event
.GetEnabled());
1130 if (item
->GetSubMenu())
1131 item
->GetSubMenu()->UpdateUI(source
);
1133 node
= node
->Next();