]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/menu.cpp
fixed incorrect GetTextExtent for wxTELETYPE font
[wxWidgets.git] / src / msw / menu.cpp
... / ...
CommitLineData
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
52extern wxMenu *wxCurrentPopupMenu;
53
54// ----------------------------------------------------------------------------
55// constants
56// ----------------------------------------------------------------------------
57
58// the (popup) menu title has this special id
59static const int idMenuTitle = -2;
60
61// ----------------------------------------------------------------------------
62// macros
63// ----------------------------------------------------------------------------
64
65IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
66IMPLEMENT_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)
77void 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.
97wxMenu::~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
116void 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
124int 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
136void 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
187bool 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
285bool wxMenu::DoAppend(wxMenuItem *item)
286{
287 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
288}
289
290bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
291{
292 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
293}
294
295wxMenuItem *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
347size_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
364void 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
427bool 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
438 // VZ: previosuly, the command int was set to id too which was quite
439 // useless anyhow (as it could be retrieved using GetId()) and
440 // uncompatible with wxGTK, so now we use the command int instead
441 // to pass the checked status
442 event.SetInt(::GetMenuState(GetHmenu(), id, MF_BYCOMMAND) & MF_CHECKED);
443
444 ProcessCommand(event);
445 }
446
447 return TRUE;
448}
449
450bool wxMenu::ProcessCommand(wxCommandEvent & event)
451{
452 bool processed = FALSE;
453
454#if wxUSE_MENU_CALLBACK
455 // Try a callback
456 if (m_callback)
457 {
458 (void)(*(m_callback))(*this, event);
459 processed = TRUE;
460 }
461#endif // wxUSE_MENU_CALLBACK
462
463 // Try the menu's event handler
464 if ( !processed && GetEventHandler())
465 {
466 processed = GetEventHandler()->ProcessEvent(event);
467 }
468
469 // Try the window the menu was popped up from (and up through the
470 // hierarchy)
471 wxWindow *win = GetInvokingWindow();
472 if ( !processed && win )
473 processed = win->GetEventHandler()->ProcessEvent(event);
474
475 return processed;
476}
477
478// ---------------------------------------------------------------------------
479// other
480// ---------------------------------------------------------------------------
481
482void wxMenu::Attach(wxMenuBar *menubar)
483{
484 // menu can be in at most one menubar because otherwise they would both
485 // delete the menu pointer
486 wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
487
488 m_menuBar = menubar;
489}
490
491void wxMenu::Detach()
492{
493 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
494
495 m_menuBar = NULL;
496}
497
498wxWindow *wxMenu::GetWindow() const
499{
500 if ( m_invokingWindow != NULL )
501 return m_invokingWindow;
502 else if ( m_menuBar != NULL)
503 return m_menuBar->GetFrame();
504
505 return NULL;
506}
507
508// ---------------------------------------------------------------------------
509// Menu Bar
510// ---------------------------------------------------------------------------
511
512void wxMenuBar::Init()
513{
514 m_eventHandler = this;
515 m_menuBarFrame = NULL;
516 m_hMenu = 0;
517}
518
519wxMenuBar::wxMenuBar()
520{
521 Init();
522}
523
524wxMenuBar::wxMenuBar( long WXUNUSED(style) )
525{
526 Init();
527}
528
529wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
530{
531 Init();
532
533 m_titles.Alloc(count);
534
535 for ( int i = 0; i < count; i++ )
536 {
537 m_menus.Append(menus[i]);
538 m_titles.Add(titles[i]);
539
540 menus[i]->Attach(this);
541 }
542}
543
544wxMenuBar::~wxMenuBar()
545{
546}
547
548// ---------------------------------------------------------------------------
549// wxMenuBar helpers
550// ---------------------------------------------------------------------------
551
552void wxMenuBar::Refresh()
553{
554 wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") );
555
556 DrawMenuBar(GetHwndOf(m_menuBarFrame));
557}
558
559WXHMENU wxMenuBar::Create()
560{
561 if ( m_hMenu != 0 )
562 return m_hMenu;
563
564 m_hMenu = (WXHMENU)::CreateMenu();
565
566 if ( !m_hMenu )
567 {
568 wxLogLastError(wxT("CreateMenu"));
569 }
570 else
571 {
572 size_t count = GetMenuCount();
573 for ( size_t i = 0; i < count; i++ )
574 {
575 if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING,
576 (UINT)m_menus[i]->GetHMenu(),
577 m_titles[i]) )
578 {
579 wxLogLastError(wxT("AppendMenu"));
580 }
581 }
582 }
583
584 return m_hMenu;
585}
586
587// ---------------------------------------------------------------------------
588// wxMenuBar functions to work with the top level submenus
589// ---------------------------------------------------------------------------
590
591// NB: we don't support owner drawn top level items for now, if we do these
592// functions would have to be changed to use wxMenuItem as well
593
594void wxMenuBar::EnableTop(size_t pos, bool enable)
595{
596 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
597
598 int flag = enable ? MF_ENABLED : MF_GRAYED;
599
600 EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
601
602 Refresh();
603}
604
605void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
606{
607 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
608
609 m_titles[pos] = label;
610
611 if ( !IsAttached() )
612 {
613 return;
614 }
615 //else: have to modify the existing menu
616
617 UINT id;
618 UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
619 if ( flagsOld == 0xFFFFFFFF )
620 {
621 wxLogLastError(wxT("GetMenuState"));
622
623 return;
624 }
625
626 if ( flagsOld & MF_POPUP )
627 {
628 // HIBYTE contains the number of items in the submenu in this case
629 flagsOld &= 0xff;
630 id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos);
631 }
632 else
633 {
634 id = pos;
635 }
636
637 if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
638 id, label) == (int)0xFFFFFFFF )
639 {
640 wxLogLastError(wxT("ModifyMenu"));
641 }
642
643 Refresh();
644}
645
646wxString wxMenuBar::GetLabelTop(size_t pos) const
647{
648 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
649 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
650
651 return m_titles[pos];
652}
653
654// ---------------------------------------------------------------------------
655// wxMenuBar construction
656// ---------------------------------------------------------------------------
657
658wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
659{
660 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
661 if ( !menuOld )
662 return FALSE;
663 m_titles[pos] = title;
664
665 if ( IsAttached() )
666 {
667 // can't use ModifyMenu() because it deletes the submenu it replaces
668 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
669 {
670 wxLogLastError(wxT("RemoveMenu"));
671 }
672
673 if ( !::InsertMenu(GetHmenu(), (UINT)pos,
674 MF_BYPOSITION | MF_POPUP | MF_STRING,
675 (UINT)GetHmenuOf(menu), title) )
676 {
677 wxLogLastError(wxT("InsertMenu"));
678 }
679
680#if wxUSE_ACCEL
681 if ( menuOld->HasAccels() || menu->HasAccels() )
682 {
683 // need to rebuild accell table
684 RebuildAccelTable();
685 }
686#endif // wxUSE_ACCEL
687
688 Refresh();
689 }
690
691 return menuOld;
692}
693
694bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
695{
696 if ( !wxMenuBarBase::Insert(pos, menu, title) )
697 return FALSE;
698
699 m_titles.Insert(title, pos);
700
701 menu->Attach(this);
702
703 if ( IsAttached() )
704 {
705 if ( !::InsertMenu(GetHmenu(), pos,
706 MF_BYPOSITION | MF_POPUP | MF_STRING,
707 (UINT)GetHmenuOf(menu), title) )
708 {
709 wxLogLastError(wxT("InsertMenu"));
710 }
711
712#if wxUSE_ACCEL
713 if ( menu->HasAccels() )
714 {
715 // need to rebuild accell table
716 RebuildAccelTable();
717 }
718#endif // wxUSE_ACCEL
719
720 Refresh();
721 }
722
723 return TRUE;
724}
725
726bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
727{
728 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
729 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
730
731 if ( !wxMenuBarBase::Append(menu, title) )
732 return FALSE;
733
734 menu->Attach(this);
735
736 m_titles.Add(title);
737
738 if ( IsAttached() )
739 {
740 if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
741 (UINT)submenu, title) )
742 {
743 wxLogLastError(wxT("AppendMenu"));
744 }
745
746#if wxUSE_ACCEL
747 if ( menu->HasAccels() )
748 {
749 // need to rebuild accell table
750 RebuildAccelTable();
751 }
752#endif // wxUSE_ACCEL
753
754 Refresh();
755 }
756
757 return TRUE;
758}
759
760wxMenu *wxMenuBar::Remove(size_t pos)
761{
762 wxMenu *menu = wxMenuBarBase::Remove(pos);
763 if ( !menu )
764 return NULL;
765
766 if ( IsAttached() )
767 {
768 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
769 {
770 wxLogLastError(wxT("RemoveMenu"));
771 }
772
773 menu->Detach();
774
775#if wxUSE_ACCEL
776 if ( menu->HasAccels() )
777 {
778 // need to rebuild accell table
779 RebuildAccelTable();
780 }
781#endif // wxUSE_ACCEL
782
783 Refresh();
784 }
785
786 m_titles.Remove(pos);
787
788 return menu;
789}
790
791#if wxUSE_ACCEL
792
793void wxMenuBar::RebuildAccelTable()
794{
795 // merge the accelerators of all menus into one accel table
796 size_t nAccelCount = 0;
797 size_t i, count = GetMenuCount();
798 for ( i = 0; i < count; i++ )
799 {
800 nAccelCount += m_menus[i]->GetAccelCount();
801 }
802
803 if ( nAccelCount )
804 {
805 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
806
807 nAccelCount = 0;
808 for ( i = 0; i < count; i++ )
809 {
810 nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
811 }
812
813 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
814
815 delete [] accelEntries;
816 }
817}
818
819#endif // wxUSE_ACCEL
820
821void wxMenuBar::Attach(wxFrame *frame)
822{
823// wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
824
825 m_menuBarFrame = frame;
826
827#if wxUSE_ACCEL
828 RebuildAccelTable();
829#endif // wxUSE_ACCEL
830}
831
832void wxMenuBar::Detach()
833{
834// ::DestroyMenu((HMENU)m_hMenu);
835 m_hMenu = (WXHMENU)NULL;
836 m_menuBarFrame = NULL;
837}
838
839
840// ---------------------------------------------------------------------------
841// wxMenuBar searching for menu items
842// ---------------------------------------------------------------------------
843
844// Find the itemString in menuString, and return the item id or wxNOT_FOUND
845int wxMenuBar::FindMenuItem(const wxString& menuString,
846 const wxString& itemString) const
847{
848 wxString menuLabel = wxStripMenuCodes(menuString);
849 size_t count = GetMenuCount();
850 for ( size_t i = 0; i < count; i++ )
851 {
852 wxString title = wxStripMenuCodes(m_titles[i]);
853 if ( menuLabel == title )
854 return m_menus[i]->FindItem(itemString);
855 }
856
857 return wxNOT_FOUND;
858}
859
860wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
861{
862 if ( itemMenu )
863 *itemMenu = NULL;
864
865 wxMenuItem *item = NULL;
866 size_t count = GetMenuCount();
867 for ( size_t i = 0; !item && (i < count); i++ )
868 {
869 item = m_menus[i]->FindItem(id, itemMenu);
870 }
871
872 return item;
873}
874