]> git.saurik.com Git - wxWidgets.git/blob - src/msw/menu.cpp
Added first stab at GetBoundingRect for generic tree control
[wxWidgets.git] / src / msw / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: menu.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "menu.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/frame.h"
33 #include "wx/menu.h"
34 #include "wx/utils.h"
35 #include "wx/intl.h"
36 #include "wx/log.h"
37 #endif
38
39 #if wxUSE_OWNER_DRAWN
40 #include "wx/ownerdrw.h"
41 #endif
42
43 #include "wx/msw/private.h"
44
45 // other standard headers
46 #include <string.h>
47
48 // ----------------------------------------------------------------------------
49 // global variables
50 // ----------------------------------------------------------------------------
51
52 extern wxMenu *wxCurrentPopupMenu;
53
54 // ----------------------------------------------------------------------------
55 // constants
56 // ----------------------------------------------------------------------------
57
58 // the (popup) menu title has this special id
59 static const int idMenuTitle = -2;
60
61 // ----------------------------------------------------------------------------
62 // macros
63 // ----------------------------------------------------------------------------
64
65 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
66 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow)
67
68 // ============================================================================
69 // implementation
70 // ============================================================================
71
72 // ---------------------------------------------------------------------------
73 // wxMenu construction, adding and removing menu items
74 // ---------------------------------------------------------------------------
75
76 // Construct a menu with optional title (then use append)
77 void wxMenu::Init()
78 {
79 m_doBreak = FALSE;
80
81 // create the menu
82 m_hMenu = (WXHMENU)CreatePopupMenu();
83 if ( !m_hMenu )
84 {
85 wxLogLastError(wxT("CreatePopupMenu"));
86 }
87
88 // if we have a title, insert it in the beginning of the menu
89 if ( !!m_title )
90 {
91 Append(idMenuTitle, m_title);
92 AppendSeparator();
93 }
94 }
95
96 // The wxWindow destructor will take care of deleting the submenus.
97 wxMenu::~wxMenu()
98 {
99 // we should free Windows resources only if Windows doesn't do it for us
100 // which happens if we're attached to a menubar or a submenu of another
101 // menu
102 if ( !IsAttached() && !GetParent() )
103 {
104 if ( !::DestroyMenu(GetHmenu()) )
105 {
106 wxLogLastError(wxT("DestroyMenu"));
107 }
108 }
109
110 #if wxUSE_ACCEL
111 // delete accels
112 WX_CLEAR_ARRAY(m_accels);
113 #endif // wxUSE_ACCEL
114 }
115
116 void wxMenu::Break()
117 {
118 // this will take effect during the next call to Append()
119 m_doBreak = TRUE;
120 }
121
122 #if wxUSE_ACCEL
123
124 int wxMenu::FindAccel(int id) const
125 {
126 size_t n, count = m_accels.GetCount();
127 for ( n = 0; n < count; n++ )
128 {
129 if ( m_accels[n]->m_command == id )
130 return n;
131 }
132
133 return wxNOT_FOUND;
134 }
135
136 void wxMenu::UpdateAccel(wxMenuItem *item)
137 {
138 if ( item->IsSubMenu() )
139 {
140 wxMenu *submenu = item->GetSubMenu();
141 wxMenuItemList::Node *node = submenu->GetMenuItems().GetFirst();
142 while ( node )
143 {
144 UpdateAccel(node->GetData());
145
146 node = node->GetNext();
147 }
148 }
149 else if ( !item->IsSeparator() )
150 {
151 // find the (new) accel for this item
152 wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
153 if ( accel )
154 accel->m_command = item->GetId();
155
156 // find the old one
157 int n = FindAccel(item->GetId());
158 if ( n == wxNOT_FOUND )
159 {
160 // no old, add new if any
161 if ( accel )
162 m_accels.Add(accel);
163 else
164 return; // skipping RebuildAccelTable() below
165 }
166 else
167 {
168 // replace old with new or just remove the old one if no new
169 delete m_accels[n];
170 if ( accel )
171 m_accels[n] = accel;
172 else
173 m_accels.Remove(n);
174 }
175
176 if ( IsAttached() )
177 {
178 m_menuBar->RebuildAccelTable();
179 }
180 }
181 //else: it is a separator, they can't have accels, nothing to do
182 }
183
184 #endif // wxUSE_ACCEL
185
186 // append a new item or submenu to the menu
187 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
188 {
189 #if wxUSE_ACCEL
190 UpdateAccel(pItem);
191 #endif // wxUSE_ACCEL
192
193 UINT flags = 0;
194
195 // if "Break" has just been called, insert a menu break before this item
196 // (and don't forget to reset the flag)
197 if ( m_doBreak ) {
198 flags |= MF_MENUBREAK;
199 m_doBreak = FALSE;
200 }
201
202 if ( pItem->IsSeparator() ) {
203 flags |= MF_SEPARATOR;
204 }
205
206 // id is the numeric id for normal menu items and HMENU for submenus as
207 // required by ::AppendMenu() API
208 UINT id;
209 wxMenu *submenu = pItem->GetSubMenu();
210 if ( submenu != NULL ) {
211 wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );
212
213 submenu->SetParent(this);
214
215 id = (UINT)submenu->GetHMenu();
216
217 flags |= MF_POPUP;
218 }
219 else {
220 id = pItem->GetId();
221 }
222
223 LPCTSTR pData;
224
225 #if wxUSE_OWNER_DRAWN
226 if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
227 // item draws itself, pass pointer to it in data parameter
228 flags |= MF_OWNERDRAW;
229 pData = (LPCTSTR)pItem;
230 }
231 else
232 #endif
233 {
234 // menu is just a normal string (passed in data parameter)
235 flags |= MF_STRING;
236
237 pData = (wxChar*)pItem->GetText().c_str();
238 }
239
240 BOOL ok;
241 if ( pos == (size_t)-1 )
242 {
243 ok = ::AppendMenu(GetHmenu(), flags, id, pData);
244 }
245 else
246 {
247 ok = ::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData);
248 }
249
250 if ( !ok )
251 {
252 wxLogLastError(wxT("Insert or AppendMenu"));
253
254 return FALSE;
255 }
256 else
257 {
258 // if we just appended the title, highlight it
259 #ifdef __WIN32__
260 if ( (int)id == idMenuTitle )
261 {
262 // visually select the menu title
263 MENUITEMINFO mii;
264 mii.cbSize = sizeof(mii);
265 mii.fMask = MIIM_STATE;
266 mii.fState = MFS_DEFAULT;
267
268 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id, FALSE, &mii) )
269 {
270 wxLogLastError(wxT("SetMenuItemInfo"));
271 }
272 }
273 #endif // __WIN32__
274
275 // if we're already attached to the menubar, we must update it
276 if ( IsAttached() )
277 {
278 m_menuBar->Refresh();
279 }
280
281 return TRUE;
282 }
283 }
284
285 bool wxMenu::DoAppend(wxMenuItem *item)
286 {
287 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
288 }
289
290 bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
291 {
292 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
293 }
294
295 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
296 {
297 // we need to find the items position in the child list
298 size_t pos;
299 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
300 for ( pos = 0; node; pos++ )
301 {
302 if ( node->GetData() == item )
303 break;
304
305 node = node->GetNext();
306 }
307
308 // DoRemove() (unlike Remove) can only be called for existing item!
309 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
310
311 #if wxUSE_ACCEL
312 // remove the corresponding accel from the accel table
313 int n = FindAccel(item->GetId());
314 if ( n != wxNOT_FOUND )
315 {
316 delete m_accels[n];
317
318 m_accels.Remove(n);
319 }
320 //else: this item doesn't have an accel, nothing to do
321 #endif // wxUSE_ACCEL
322
323 // remove the item from the menu
324 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
325 {
326 wxLogLastError(wxT("RemoveMenu"));
327 }
328
329 if ( IsAttached() )
330 {
331 // otherwise, the chane won't be visible
332 m_menuBar->Refresh();
333 }
334
335 // and from internal data structures
336 return wxMenuBase::DoRemove(item);
337 }
338
339 // ---------------------------------------------------------------------------
340 // accelerator helpers
341 // ---------------------------------------------------------------------------
342
343 #if wxUSE_ACCEL
344
345 // create the wxAcceleratorEntries for our accels and put them into provided
346 // array - return the number of accels we have
347 size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
348 {
349 size_t count = GetAccelCount();
350 for ( size_t n = 0; n < count; n++ )
351 {
352 *accels++ = *m_accels[n];
353 }
354
355 return count;
356 }
357
358 #endif // wxUSE_ACCEL
359
360 // ---------------------------------------------------------------------------
361 // set wxMenu title
362 // ---------------------------------------------------------------------------
363
364 void wxMenu::SetTitle(const wxString& label)
365 {
366 bool hasNoTitle = m_title.IsEmpty();
367 m_title = label;
368
369 HMENU hMenu = GetHmenu();
370
371 if ( hasNoTitle )
372 {
373 if ( !label.IsEmpty() )
374 {
375 if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
376 (unsigned)idMenuTitle, m_title) ||
377 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
378 {
379 wxLogLastError(wxT("InsertMenu"));
380 }
381 }
382 }
383 else
384 {
385 if ( label.IsEmpty() )
386 {
387 // remove the title and the separator after it
388 if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
389 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
390 {
391 wxLogLastError(wxT("RemoveMenu"));
392 }
393 }
394 else
395 {
396 // modify the title
397 if ( !ModifyMenu(hMenu, 0u,
398 MF_BYPOSITION | MF_STRING,
399 (unsigned)idMenuTitle, m_title) )
400 {
401 wxLogLastError(wxT("ModifyMenu"));
402 }
403 }
404 }
405
406 #ifdef __WIN32__
407 // put the title string in bold face
408 if ( !m_title.IsEmpty() )
409 {
410 MENUITEMINFO mii;
411 mii.cbSize = sizeof(mii);
412 mii.fMask = MIIM_STATE;
413 mii.fState = MFS_DEFAULT;
414
415 if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) )
416 {
417 wxLogLastError(wxT("SetMenuItemInfo"));
418 }
419 }
420 #endif // Win32
421 }
422
423 // ---------------------------------------------------------------------------
424 // event processing
425 // ---------------------------------------------------------------------------
426
427 bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id)
428 {
429 // ignore commands from the menu title
430
431 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
432 if ( id != (WXWORD)idMenuTitle )
433 {
434 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
435 event.SetEventObject( this );
436 event.SetId( id );
437 event.SetInt( id );
438 ProcessCommand(event);
439 }
440
441 return TRUE;
442 }
443
444 bool wxMenu::ProcessCommand(wxCommandEvent & event)
445 {
446 bool processed = FALSE;
447
448 #if wxUSE_MENU_CALLBACK
449 // Try a callback
450 if (m_callback)
451 {
452 (void)(*(m_callback))(*this, event);
453 processed = TRUE;
454 }
455 #endif // wxUSE_MENU_CALLBACK
456
457 // Try the menu's event handler
458 if ( !processed && GetEventHandler())
459 {
460 processed = GetEventHandler()->ProcessEvent(event);
461 }
462
463 // Try the window the menu was popped up from (and up through the
464 // hierarchy)
465 wxWindow *win = GetInvokingWindow();
466 if ( !processed && win )
467 processed = win->GetEventHandler()->ProcessEvent(event);
468
469 return processed;
470 }
471
472 // ---------------------------------------------------------------------------
473 // other
474 // ---------------------------------------------------------------------------
475
476 void wxMenu::Attach(wxMenuBar *menubar)
477 {
478 // menu can be in at most one menubar because otherwise they would both
479 // delete the menu pointer
480 wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
481
482 m_menuBar = menubar;
483 }
484
485 void wxMenu::Detach()
486 {
487 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
488
489 m_menuBar = NULL;
490 }
491
492 wxWindow *wxMenu::GetWindow() const
493 {
494 if ( m_invokingWindow != NULL )
495 return m_invokingWindow;
496 else if ( m_menuBar != NULL)
497 return m_menuBar->GetFrame();
498
499 return NULL;
500 }
501
502 // ---------------------------------------------------------------------------
503 // Menu Bar
504 // ---------------------------------------------------------------------------
505
506 void wxMenuBar::Init()
507 {
508 m_eventHandler = this;
509 m_menuBarFrame = NULL;
510 m_hMenu = 0;
511 }
512
513 wxMenuBar::wxMenuBar()
514 {
515 Init();
516 }
517
518 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
519 {
520 Init();
521 }
522
523 wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
524 {
525 Init();
526
527 m_titles.Alloc(count);
528
529 for ( int i = 0; i < count; i++ )
530 {
531 m_menus.Append(menus[i]);
532 m_titles.Add(titles[i]);
533
534 menus[i]->Attach(this);
535 }
536 }
537
538 wxMenuBar::~wxMenuBar()
539 {
540 }
541
542 // ---------------------------------------------------------------------------
543 // wxMenuBar helpers
544 // ---------------------------------------------------------------------------
545
546 void wxMenuBar::Refresh()
547 {
548 wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") );
549
550 DrawMenuBar(GetHwndOf(m_menuBarFrame));
551 }
552
553 WXHMENU wxMenuBar::Create()
554 {
555 if (m_hMenu != 0 )
556 return m_hMenu;
557
558 wxCHECK_MSG( !m_hMenu, TRUE, wxT("menubar already created") );
559
560 m_hMenu = (WXHMENU)::CreateMenu();
561
562 if ( !m_hMenu )
563 {
564 wxLogLastError(wxT("CreateMenu"));
565 }
566 else
567 {
568 size_t count = GetMenuCount();
569 for ( size_t i = 0; i < count; i++ )
570 {
571 if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING,
572 (UINT)m_menus[i]->GetHMenu(),
573 m_titles[i]) )
574 {
575 wxLogLastError(wxT("AppendMenu"));
576 }
577 }
578 }
579
580 return m_hMenu;
581 }
582
583 // ---------------------------------------------------------------------------
584 // wxMenuBar functions to work with the top level submenus
585 // ---------------------------------------------------------------------------
586
587 // NB: we don't support owner drawn top level items for now, if we do these
588 // functions would have to be changed to use wxMenuItem as well
589
590 void wxMenuBar::EnableTop(size_t pos, bool enable)
591 {
592 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
593
594 int flag = enable ? MF_ENABLED : MF_GRAYED;
595
596 EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
597
598 Refresh();
599 }
600
601 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
602 {
603 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
604
605 m_titles[pos] = label;
606
607 if ( !IsAttached() )
608 {
609 return;
610 }
611 //else: have to modify the existing menu
612
613 UINT id;
614 UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
615 if ( flagsOld == 0xFFFFFFFF )
616 {
617 wxLogLastError(wxT("GetMenuState"));
618
619 return;
620 }
621
622 if ( flagsOld & MF_POPUP )
623 {
624 // HIBYTE contains the number of items in the submenu in this case
625 flagsOld &= 0xff;
626 id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos);
627 }
628 else
629 {
630 id = pos;
631 }
632
633 if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
634 id, label) == (int)0xFFFFFFFF )
635 {
636 wxLogLastError(wxT("ModifyMenu"));
637 }
638
639 Refresh();
640 }
641
642 wxString wxMenuBar::GetLabelTop(size_t pos) const
643 {
644 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
645 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
646
647 return m_titles[pos];
648 }
649
650 // ---------------------------------------------------------------------------
651 // wxMenuBar construction
652 // ---------------------------------------------------------------------------
653
654 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
655 {
656 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
657 if ( !menuOld )
658 return FALSE;
659 m_titles[pos] = title;
660
661 if ( IsAttached() )
662 {
663 // can't use ModifyMenu() because it deletes the submenu it replaces
664 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
665 {
666 wxLogLastError(wxT("RemoveMenu"));
667 }
668
669 if ( !::InsertMenu(GetHmenu(), (UINT)pos,
670 MF_BYPOSITION | MF_POPUP | MF_STRING,
671 (UINT)GetHmenuOf(menu), title) )
672 {
673 wxLogLastError(wxT("InsertMenu"));
674 }
675
676 #if wxUSE_ACCEL
677 if ( menuOld->HasAccels() || menu->HasAccels() )
678 {
679 // need to rebuild accell table
680 RebuildAccelTable();
681 }
682 #endif // wxUSE_ACCEL
683
684 Refresh();
685 }
686
687 return menuOld;
688 }
689
690 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
691 {
692 if ( !wxMenuBarBase::Insert(pos, menu, title) )
693 return FALSE;
694
695 m_titles.Insert(title, pos);
696
697 menu->Attach(this);
698
699 if ( IsAttached() )
700 {
701 if ( !::InsertMenu(GetHmenu(), pos,
702 MF_BYPOSITION | MF_POPUP | MF_STRING,
703 (UINT)GetHmenuOf(menu), title) )
704 {
705 wxLogLastError(wxT("InsertMenu"));
706 }
707
708 #if wxUSE_ACCEL
709 if ( menu->HasAccels() )
710 {
711 // need to rebuild accell table
712 RebuildAccelTable();
713 }
714 #endif // wxUSE_ACCEL
715
716 Refresh();
717 }
718
719 return TRUE;
720 }
721
722 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
723 {
724 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
725 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
726
727 if ( !wxMenuBarBase::Append(menu, title) )
728 return FALSE;
729
730 menu->Attach(this);
731
732 m_titles.Add(title);
733
734 if ( IsAttached() )
735 {
736 if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
737 (UINT)submenu, title) )
738 {
739 wxLogLastError(wxT("AppendMenu"));
740 }
741
742 #if wxUSE_ACCEL
743 if ( menu->HasAccels() )
744 {
745 // need to rebuild accell table
746 RebuildAccelTable();
747 }
748 #endif // wxUSE_ACCEL
749
750 Refresh();
751 }
752
753 return TRUE;
754 }
755
756 wxMenu *wxMenuBar::Remove(size_t pos)
757 {
758 wxMenu *menu = wxMenuBarBase::Remove(pos);
759 if ( !menu )
760 return NULL;
761
762 if ( IsAttached() )
763 {
764 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
765 {
766 wxLogLastError(wxT("RemoveMenu"));
767 }
768
769 menu->Detach();
770
771 #if wxUSE_ACCEL
772 if ( menu->HasAccels() )
773 {
774 // need to rebuild accell table
775 RebuildAccelTable();
776 }
777 #endif // wxUSE_ACCEL
778
779 Refresh();
780 }
781
782 m_titles.Remove(pos);
783
784 return menu;
785 }
786
787 #if wxUSE_ACCEL
788
789 void wxMenuBar::RebuildAccelTable()
790 {
791 // merge the accelerators of all menus into one accel table
792 size_t nAccelCount = 0;
793 size_t i, count = GetMenuCount();
794 for ( i = 0; i < count; i++ )
795 {
796 nAccelCount += m_menus[i]->GetAccelCount();
797 }
798
799 if ( nAccelCount )
800 {
801 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
802
803 nAccelCount = 0;
804 for ( i = 0; i < count; i++ )
805 {
806 nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
807 }
808
809 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
810
811 delete [] accelEntries;
812 }
813 }
814
815 #endif // wxUSE_ACCEL
816
817 void wxMenuBar::Attach(wxFrame *frame)
818 {
819 // wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
820
821 m_menuBarFrame = frame;
822
823 #if wxUSE_ACCEL
824 RebuildAccelTable();
825 #endif // wxUSE_ACCEL
826 }
827
828 void wxMenuBar::Detach()
829 {
830 // ::DestroyMenu((HMENU)m_hMenu);
831 m_hMenu = (WXHMENU)NULL;
832 m_menuBarFrame = NULL;
833 }
834
835
836 // ---------------------------------------------------------------------------
837 // wxMenuBar searching for menu items
838 // ---------------------------------------------------------------------------
839
840 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
841 int wxMenuBar::FindMenuItem(const wxString& menuString,
842 const wxString& itemString) const
843 {
844 wxString menuLabel = wxStripMenuCodes(menuString);
845 size_t count = GetMenuCount();
846 for ( size_t i = 0; i < count; i++ )
847 {
848 wxString title = wxStripMenuCodes(m_titles[i]);
849 if ( menuLabel == title )
850 return m_menus[i]->FindItem(itemString);
851 }
852
853 return wxNOT_FOUND;
854 }
855
856 wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
857 {
858 if ( itemMenu )
859 *itemMenu = NULL;
860
861 wxMenuItem *item = NULL;
862 size_t count = GetMenuCount();
863 for ( size_t i = 0; !item && (i < count); i++ )
864 {
865 item = m_menus[i]->FindItem(id, itemMenu);
866 }
867
868 return item;
869 }
870