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