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