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"
39 #include "wx/ownerdrw.h"
42 #include "wx/msw/private.h"
43 #include "wx/msw/menu.h"
44 #include "wx/menuitem.h"
47 // other standard headers
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 extern wxMenu
*wxCurrentPopupMenu
;
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 // the (popup) menu title has this special id
61 static const int idMenuTitle
= -2;
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #if !USE_SHARED_LIBRARY
68 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
69 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
72 // ============================================================================
74 // ============================================================================
76 // ---------------------------------------------------------------------------
77 // wxMenu construction, adding and removing menu items
78 // ---------------------------------------------------------------------------
80 // Construct a menu with optional title (then use append)
81 wxMenu::wxMenu(const wxString
& title
, const wxFunction func
)
85 m_eventHandler
= this;
86 m_pInvokingWindow
= NULL
;
90 m_hMenu
= (WXHMENU
) CreatePopupMenu();
92 m_topLevelMenu
= this;
93 m_clientData
= (void*) NULL
;
97 Append(idMenuTitle
, m_title
) ;
101 #if WXWIN_COMPATIBILITY
106 // The wxWindow destructor will take care of deleting the submenus.
109 // free Windows resources
112 ::DestroyMenu((HMENU
)m_hMenu
);
117 wxNode
*node
= m_menuItems
.First();
120 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
122 // Delete child menus.
123 // Beware: they must not be appended to children list!!!
124 // (because order of delete is significant)
125 if ( item
->IsSubMenu() )
126 item
->DeleteSubMenu();
128 wxNode
*next
= node
->Next();
140 // function appends a new item or submenu to the menu
141 void wxMenu::Append(wxMenuItem
*pItem
)
143 wxCHECK_RET( pItem
!= NULL
, _T("can't append NULL item to the menu") );
146 // check for accelerators: they are given after '\t'
147 wxString label
= pItem
->GetName();
148 int posTab
= label
.Find(_T('\t'));
149 if ( posTab
!= wxNOT_FOUND
) {
150 // parse the accelerator string
152 int accelFlags
= wxACCEL_NORMAL
;
154 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
155 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
156 if ( current
== _("ctrl") )
157 accelFlags
|= wxACCEL_CTRL
;
158 else if ( current
== _("alt") )
159 accelFlags
|= wxACCEL_ALT
;
160 else if ( current
== _("shift") )
161 accelFlags
|= wxACCEL_SHIFT
;
163 wxLogDebug(_T("Unknown accel modifier: '%s'"),
170 current
+= wxTolower(label
[n
]);
174 if ( current
.IsEmpty() ) {
175 wxLogDebug(_T("No accel key found, accel string ignored."));
178 if ( current
.Len() == 1 ) {
180 keyCode
= wxToupper(current
[0U]);
183 // it should be a function key
184 if ( current
[0U] == 'f' && isdigit(current
[1U]) &&
185 (current
.Len() == 2 ||
186 (current
.Len() == 3 && isdigit(current
[2U]))) ) {
188 wxSscanf(current
.c_str() + 1, _T("%d"), &n
);
190 keyCode
= VK_F1
+ n
- 1;
193 wxLogDebug(_T("Unrecognized accel key '%s', accel "
194 "string ignored."), current
.c_str());
201 m_accelKeyCodes
.Add(keyCode
);
202 m_accelFlags
.Add(accelFlags
);
203 m_accelIds
.Add(pItem
->GetId());
206 #endif // wxUSE_ACCEL
210 // if "Break" has just been called, insert a menu break before this item
211 // (and don't forget to reset the flag)
213 flags
|= MF_MENUBREAK
;
217 if ( pItem
->IsSeparator() ) {
218 flags
|= MF_SEPARATOR
;
221 // id is the numeric id for normal menu items and HMENU for submenus as
222 // required by ::AppendMenu() API
224 wxMenu
*submenu
= pItem
->GetSubMenu();
225 if ( submenu
!= NULL
) {
226 wxASSERT( submenu
->GetHMenu() != (WXHMENU
) NULL
);
228 id
= (UINT
)submenu
->GetHMenu();
229 submenu
->m_topLevelMenu
= m_topLevelMenu
;
230 submenu
->m_parent
= this;
231 submenu
->m_savehMenu
= (WXHMENU
)id
;
232 submenu
->m_hMenu
= 0;
242 #if wxUSE_OWNER_DRAWN
243 if ( pItem
->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
244 // item draws itself, pass pointer to it in data parameter
245 flags
|= MF_OWNERDRAW
;
246 pData
= (LPCTSTR
)pItem
;
251 // menu is just a normal string (passed in data parameter)
256 if ( !::AppendMenu(GetHmenu(), flags
, id
, pData
) )
258 wxLogLastError("AppendMenu");
263 if ( id
== idMenuTitle
)
265 // visually select the menu title
267 mii
.cbSize
= sizeof(mii
);
268 mii
.fMask
= MIIM_STATE
;
269 mii
.fState
= MFS_DEFAULT
;
271 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id
, FALSE
, &mii
) )
273 wxLogLastError(_T("SetMenuItemInfo"));
278 m_menuItems
.Append(pItem
);
283 void wxMenu::AppendSeparator()
285 Append(new wxMenuItem(this, ID_SEPARATOR
));
289 void wxMenu::Append(int id
,
290 const wxString
& label
,
292 const wxString
& helpString
)
294 Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, SubMenu
));
297 // Ordinary menu item
298 void wxMenu::Append(int id
,
299 const wxString
& label
,
300 const wxString
& helpString
,
303 // 'checkable' parameter is useless for Windows.
304 Append(new wxMenuItem(this, id
, label
, helpString
, checkable
));
308 void wxMenu::Delete(int id
)
310 wxMenuItem
*item
= NULL
;
313 for (pos
= 0, node
= m_menuItems
.First(); node
; node
= node
->Next(), pos
++)
315 item
= (wxMenuItem
*)node
->Data();
316 if ( item
->GetId() == id
)
320 wxCHECK_RET( node
, _T("wxMenu::Delete(): item doesn't exist") );
322 HMENU menu
= GetHmenu();
324 wxMenu
*pSubMenu
= item
->GetSubMenu();
325 if ( pSubMenu
!= NULL
) {
326 RemoveMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
327 pSubMenu
->m_hMenu
= pSubMenu
->m_savehMenu
;
328 pSubMenu
->m_savehMenu
= 0;
329 pSubMenu
->m_parent
= NULL
;
330 // RemoveChild(item->subMenu);
331 pSubMenu
->m_topLevelMenu
= NULL
;
332 // TODO: Why isn't subMenu deleted here???
333 // Will put this in for now. Assuming this is supposed
334 // to delete the menu, not just remove it.
335 item
->DeleteSubMenu();
338 DeleteMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
341 m_menuItems
.DeleteNode(node
);
347 // ---------------------------------------------------------------------------
348 // accelerator helpers
349 // ---------------------------------------------------------------------------
351 // create the wxAcceleratorEntries for our accels and put them into provided
352 // array - return the number of accels we have
353 size_t wxMenu::CopyAccels(wxAcceleratorEntry
*accels
) const
355 size_t count
= GetAccelCount();
356 for ( size_t n
= 0; n
< count
; n
++ )
358 (*accels
++).Set(m_accelFlags
[n
], m_accelKeyCodes
[n
], m_accelIds
[n
]);
364 #endif // wxUSE_ACCEL
366 // ---------------------------------------------------------------------------
367 // wxMenu functions implemented in wxMenuItem
368 // ---------------------------------------------------------------------------
370 void wxMenu::Enable(int id
, bool Flag
)
372 wxMenuItem
*item
= FindItemForId(id
);
373 wxCHECK_RET( item
!= NULL
, _T("can't enable non-existing menu item") );
378 bool wxMenu::IsEnabled(int id
) const
380 wxMenuItem
*item
= FindItemForId(id
);
381 wxCHECK_MSG( item
!= NULL
, FALSE
, _T("invalid item id") );
383 return item
->IsEnabled();
386 void wxMenu::Check(int id
, bool Flag
)
388 wxMenuItem
*item
= FindItemForId(id
);
389 wxCHECK_RET( item
!= NULL
, _T("can't get status of non-existing menu item") );
394 bool wxMenu::IsChecked(int id
) const
396 wxMenuItem
*item
= FindItemForId(id
);
397 wxCHECK_MSG( item
!= NULL
, FALSE
, _T("invalid item id") );
399 return item
->IsChecked();
402 void wxMenu::SetLabel(int id
, const wxString
& label
)
404 wxMenuItem
*item
= FindItemForId(id
) ;
405 wxCHECK_RET( item
, _T("wxMenu::SetLabel: no such item") );
407 item
->SetName(label
);
410 wxString
wxMenu::GetLabel(int id
) const
413 wxMenuItem
*pItem
= FindItemForId(id
) ;
415 label
= pItem
->GetName() ;
417 wxFAIL_MSG(_T("wxMenu::GetLabel: item doesn't exist"));
422 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
)
424 wxMenuItem
*item
= FindItemForId (itemId
);
426 item
->SetHelp(helpString
);
428 wxFAIL_MSG(_T("wxMenu::SetHelpString: item doesn't exist"));
431 wxString
wxMenu::GetHelpString (int itemId
) const
434 wxMenuItem
*item
= FindItemForId (itemId
);
436 help
= item
->GetHelp();
438 wxFAIL_MSG(_T("wxMenu::GetHelpString: item doesn't exist"));
443 // ---------------------------------------------------------------------------
445 // ---------------------------------------------------------------------------
447 void wxMenu::SetTitle(const wxString
& label
)
449 bool hasNoTitle
= m_title
.IsEmpty();
452 HMENU hMenu
= GetHmenu();
456 if ( !label
.IsEmpty() )
458 if ( !InsertMenu(hMenu
, 0u, MF_BYPOSITION
| MF_STRING
,
459 (unsigned)idMenuTitle
, m_title
) ||
460 !InsertMenu(hMenu
, 1u, MF_BYPOSITION
, (unsigned)-1, NULL
) )
462 wxLogLastError(_T("InsertMenu"));
468 if ( label
.IsEmpty() )
470 // remove the title and the separator after it
471 if ( !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) ||
472 !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) )
474 wxLogLastError("RemoveMenu");
480 if ( !ModifyMenu(hMenu
, 0u,
481 MF_BYPOSITION
| MF_STRING
,
482 (unsigned)idMenuTitle
, m_title
) )
484 wxLogLastError("ModifyMenu");
490 // put the title string in bold face
491 if ( !m_title
.IsEmpty() )
494 mii
.cbSize
= sizeof(mii
);
495 mii
.fMask
= MIIM_STATE
;
496 mii
.fState
= MFS_DEFAULT
;
498 if ( !SetMenuItemInfo(hMenu
, (unsigned)idMenuTitle
, FALSE
, &mii
) )
500 wxLogLastError("SetMenuItemInfo");
506 const wxString
wxMenu::GetTitle() const
511 // ---------------------------------------------------------------------------
513 // ---------------------------------------------------------------------------
515 bool wxMenu::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD id
)
517 // ignore commands from the menu title
519 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
520 if ( id
!= (WXWORD
)idMenuTitle
)
522 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
523 event
.SetEventObject( this );
526 ProcessCommand(event
);
532 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
534 bool processed
= FALSE
;
536 #if WXWIN_COMPATIBILITY
540 (void)(*(m_callback
))(*this, event
);
543 #endif // WXWIN_COMPATIBILITY
545 // Try the menu's event handler
546 if ( !processed
&& GetEventHandler())
548 processed
= GetEventHandler()->ProcessEvent(event
);
551 // Try the window the menu was popped up from (and up through the
553 wxWindow
*win
= GetInvokingWindow();
554 if ( !processed
&& win
)
555 processed
= win
->GetEventHandler()->ProcessEvent(event
);
560 // ---------------------------------------------------------------------------
562 // ---------------------------------------------------------------------------
564 // Finds the item id matching the given string, -1 if not found.
565 int wxMenu::FindItem (const wxString
& itemString
) const
567 wxString itemLabel
= wxStripMenuCodes(itemString
);
568 for ( wxNode
*node
= m_menuItems
.First(); node
; node
= node
->Next() )
570 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
571 if ( item
->IsSubMenu() )
573 int ans
= item
->GetSubMenu()->FindItem(itemString
);
574 if ( ans
!= wxNOT_FOUND
)
577 else if ( !item
->IsSeparator() )
579 wxString label
= wxStripMenuCodes(item
->GetName());
580 if ( itemLabel
== label
)
581 return item
->GetId();
588 wxMenuItem
*wxMenu::FindItemForId(int itemId
, wxMenu
** itemMenu
) const
593 wxMenuItem
*item
= NULL
;
594 for ( wxNode
*node
= m_menuItems
.First(); node
&& !item
; node
= node
->Next() )
596 item
= (wxMenuItem
*)node
->Data();
598 if ( item
->GetId() == itemId
)
601 *itemMenu
= (wxMenu
*)this;
603 else if ( item
->IsSubMenu() )
605 item
= item
->GetSubMenu()->FindItemForId(itemId
, itemMenu
);
609 // don't exit the loop
617 // ---------------------------------------------------------------------------
619 // ---------------------------------------------------------------------------
621 void wxMenu::Attach(wxMenuBar
*menubar
)
623 // menu can be in at most one menubar because otherwise they would both
624 // delete the menu pointer
625 wxASSERT_MSG( !m_menuBar
, _T("menu belongs to 2 menubars, expect a crash") );
628 m_savehMenu
= m_hMenu
;
632 void wxMenu::Detach()
634 wxASSERT_MSG( m_menuBar
, _T("can't detach menu if it's not attached") );
636 m_hMenu
= m_savehMenu
;
640 // ---------------------------------------------------------------------------
642 // ---------------------------------------------------------------------------
644 void wxMenuBar::Init()
646 m_eventHandler
= this;
650 m_menuBarFrame
= NULL
;
654 wxMenuBar::wxMenuBar()
659 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
664 wxMenuBar::wxMenuBar(int count
, wxMenu
*menus
[], const wxString titles
[])
670 m_titles
= new wxString
[count
];
673 for ( i
= 0; i
< count
; i
++ )
674 m_titles
[i
] = titles
[i
];
676 for ( i
= 0; i
< count
; i
++ )
677 m_menus
[i
]->Attach(this);
680 wxMenuBar::~wxMenuBar()
682 for ( int i
= 0; i
< m_menuCount
; i
++ )
691 // ---------------------------------------------------------------------------
693 // ---------------------------------------------------------------------------
695 void wxMenuBar::Refresh()
697 wxCHECK_RET( m_menuBarFrame
, _T("can't refresh a menubar withotu a frame") );
699 DrawMenuBar((HWND
)m_menuBarFrame
->GetHWND()) ;
702 WXHMENU
wxMenuBar::Create()
704 wxCHECK_MSG( !m_hMenu
, TRUE
, _T("menubar already created") );
706 m_hMenu
= (WXHMENU
)::CreateMenu();
710 wxLogLastError("CreateMenu");
714 for ( int i
= 0; i
< m_menuCount
; i
++ )
716 if ( !::AppendMenu((HMENU
)m_hMenu
, MF_POPUP
| MF_STRING
,
717 (UINT
)m_menus
[i
]->GetHMenu(),
720 wxLogLastError("AppendMenu");
728 // ---------------------------------------------------------------------------
729 // wxMenuBar functions forwarded to wxMenuItem
730 // ---------------------------------------------------------------------------
732 // Must only be used AFTER menu has been attached to frame,
733 // otherwise use individual menus to enable/disable items
734 void wxMenuBar::Enable(int id
, bool enable
)
736 wxMenu
*itemMenu
= NULL
;
737 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
739 wxCHECK_RET( item
, _T("attempt to enable an item which doesn't exist") );
741 item
->Enable(enable
);
744 void wxMenuBar::EnableTop(int pos
, bool enable
)
746 int flag
= enable
? MF_ENABLED
: MF_GRAYED
;;
748 EnableMenuItem((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
| flag
);
751 // Must only be used AFTER menu has been attached to frame,
752 // otherwise use individual menus
753 void wxMenuBar::Check(int id
, bool check
)
755 wxMenu
*itemMenu
= NULL
;
756 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
758 wxCHECK_RET( item
, _T("attempt to check an item which doesn't exist") );
759 wxCHECK_RET( item
->IsCheckable(), _T("attempt to check an uncheckable item") );
764 bool wxMenuBar::IsChecked(int id
) const
766 wxMenu
*itemMenu
= NULL
;
767 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
769 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsChecked(): no such item") );
771 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
);
773 return (flag
& MF_CHECKED
) != 0;
776 bool wxMenuBar::IsEnabled(int id
) const
778 wxMenu
*itemMenu
= NULL
;
779 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
781 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsEnabled(): no such item") );
783 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
) ;
785 return (flag
& MF_ENABLED
) != 0;
788 void wxMenuBar::SetLabel(int id
, const wxString
& label
)
790 wxMenu
*itemMenu
= NULL
;
791 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
793 wxCHECK_RET( item
, _T("wxMenuBar::SetLabel(): no such item") );
795 item
->SetName(label
);
798 wxString
wxMenuBar::GetLabel(int id
) const
800 wxMenu
*itemMenu
= NULL
;
801 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
803 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetLabel(): no such item") );
805 return item
->GetName();
808 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
)
810 wxMenu
*itemMenu
= NULL
;
811 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
813 wxCHECK_RET( item
, _T("wxMenuBar::SetHelpString(): no such item") );
815 item
->SetHelp(helpString
);
818 wxString
wxMenuBar::GetHelpString (int id
) const
820 wxMenu
*itemMenu
= NULL
;
821 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
823 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetHelpString(): no such item") );
825 return item
->GetHelp();
828 // ---------------------------------------------------------------------------
829 // wxMenuBar functions to work with the top level submenus
830 // ---------------------------------------------------------------------------
832 // NB: we don't support owner drawn top level items for now, if we do these
833 // functions would have to be changed to use wxMenuItem as well
835 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
)
838 UINT flagsOld
= ::GetMenuState((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
);
839 if ( flagsOld
== 0xFFFFFFFF )
841 wxLogLastError(_T("GetMenuState"));
846 if ( flagsOld
& MF_POPUP
)
848 // HIBYTE contains the number of items in the submenu in this case
850 id
= (UINT
)::GetSubMenu((HMENU
)m_hMenu
, pos
) ;
857 if ( ::ModifyMenu(GetHmenu(), pos
, MF_BYPOSITION
| MF_STRING
| flagsOld
,
858 id
, label
) == 0xFFFFFFFF )
860 wxLogLastError("ModifyMenu");
864 wxString
wxMenuBar::GetLabelTop(int pos
) const
866 int len
= ::GetMenuString((HMENU
)m_hMenu
, pos
, NULL
, 0, MF_BYCOMMAND
);
868 len
++; // for the NUL character
870 ::GetMenuString(GetHmenu(), pos
, label
.GetWriteBuf(len
), len
, MF_BYCOMMAND
);
871 label
.UngetWriteBuf();
876 // ---------------------------------------------------------------------------
877 // wxMenuBar notifications
878 // ---------------------------------------------------------------------------
880 bool wxMenuBar::OnDelete(wxMenu
*a_menu
, int pos
)
882 if ( !m_menuBarFrame
)
885 if ( ::RemoveMenu((HMENU
)m_hMenu
, (UINT
)pos
, MF_BYPOSITION
) )
887 // VZ: I'm not sure about what's going on here, so I leave an assert
888 wxASSERT_MSG( m_menus
[pos
] == a_menu
, _T("what is this parameter for??") );
892 if ( m_menuBarFrame
)
899 wxLogLastError("RemoveMenu");
905 bool wxMenuBar::OnAppend(wxMenu
*a_menu
, const wxChar
*title
)
907 WXHMENU submenu
= a_menu
->GetHMenu();
911 if ( !m_menuBarFrame
)
914 a_menu
->Attach(this);
916 if ( !::AppendMenu(GetHmenu(), MF_POPUP
| MF_STRING
,
917 (UINT
)submenu
, title
) )
919 wxLogLastError(_T("AppendMenu"));
927 // ---------------------------------------------------------------------------
928 // wxMenuBar construction
929 // ---------------------------------------------------------------------------
931 void wxMenuBar::Append (wxMenu
* menu
, const wxString
& title
)
933 if (!OnAppend(menu
, title
))
937 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
938 wxString
*new_titles
= new wxString
[m_menuCount
];
941 for (i
= 0; i
< m_menuCount
- 1; i
++)
943 new_menus
[i
] = m_menus
[i
];
945 new_titles
[i
] = m_titles
[i
];
946 m_titles
[i
] = _T("");
954 m_titles
= new_titles
;
956 m_menus
[m_menuCount
- 1] = (wxMenu
*)menu
;
957 m_titles
[m_menuCount
- 1] = title
;
959 menu
->SetParent(this);
962 void wxMenuBar::Delete(wxMenu
* menu
, int i
)
968 for (ii
= 0; ii
< m_menuCount
; ii
++) {
969 if (m_menus
[ii
] == menu
)
972 if (ii
>= m_menuCount
)
975 if (ii
< 0 || ii
>= m_menuCount
)
980 if (!OnDelete(menu
, ii
))
983 menu
->SetParent(NULL
);
986 for (j
= ii
; j
< m_menuCount
; j
++) {
987 m_menus
[j
] = m_menus
[j
+ 1];
988 m_titles
[j
] = m_titles
[j
+ 1];
992 void wxMenuBar::Attach(wxFrame
*frame
)
994 wxASSERT_MSG( !m_menuBarFrame
, _T("menubar already attached!") );
996 m_menuBarFrame
= frame
;
999 // create the accel table - we consider that the menubar construction is
1001 size_t nAccelCount
= 0;
1003 for ( i
= 0; i
< m_menuCount
; i
++ )
1005 nAccelCount
+= m_menus
[i
]->GetAccelCount();
1010 wxAcceleratorEntry
*accelEntries
= new wxAcceleratorEntry
[nAccelCount
];
1013 for ( i
= 0; i
< m_menuCount
; i
++ )
1015 nAccelCount
+= m_menus
[i
]->CopyAccels(&accelEntries
[nAccelCount
]);
1018 m_accelTable
= wxAcceleratorTable(nAccelCount
, accelEntries
);
1020 delete [] accelEntries
;
1022 #endif // wxUSE_ACCEL
1025 // ---------------------------------------------------------------------------
1026 // wxMenuBar searching for menu items
1027 // ---------------------------------------------------------------------------
1029 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1030 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1031 const wxString
& itemString
) const
1033 wxString menuLabel
= wxStripMenuCodes(menuString
);
1034 for ( int i
= 0; i
< m_menuCount
; i
++ )
1036 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1037 if ( menuString
== title
)
1038 return m_menus
[i
]->FindItem(itemString
);
1044 wxMenuItem
*wxMenuBar::FindItemForId (int id
, wxMenu
**itemMenu
) const
1049 wxMenuItem
*item
= NULL
;
1050 for ( int i
= 0; !item
&& (i
< m_menuCount
); i
++ )
1052 item
= m_menus
[i
]->FindItemForId(id
, itemMenu
);
1059 // ----------------------------------------------------------------------------
1061 // ----------------------------------------------------------------------------
1063 wxWindow
*wxMenu::GetWindow() const
1065 if ( m_pInvokingWindow
!= NULL
)
1066 return m_pInvokingWindow
;
1067 else if ( m_menuBar
!= NULL
)
1068 return m_menuBar
->GetFrame();
1073 WXHMENU
wxMenu::GetHMenu() const
1077 else if ( m_savehMenu
!= 0 )
1080 wxFAIL_MSG(_T("wxMenu without HMENU"));
1085 // Update a menu and all submenus recursively. source is the object that has
1086 // the update event handlers defined for it. If NULL, the menu or associated
1087 // window will be used.
1088 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1090 if (!source
&& GetInvokingWindow())
1091 source
= GetInvokingWindow()->GetEventHandler();
1093 source
= GetEventHandler();
1097 wxNode
* node
= GetItems().First();
1100 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1101 if ( !item
->IsSeparator() )
1103 wxWindowID id
= item
->GetId();
1104 wxUpdateUIEvent
event(id
);
1105 event
.SetEventObject( source
);
1107 if (source
->ProcessEvent(event
))
1109 if (event
.GetSetText())
1110 SetLabel(id
, event
.GetText());
1111 if (event
.GetSetChecked())
1112 Check(id
, event
.GetChecked());
1113 if (event
.GetSetEnabled())
1114 Enable(id
, event
.GetEnabled());
1117 if (item
->GetSubMenu())
1118 item
->GetSubMenu()->UpdateUI(source
);
1120 node
= node
->Next();