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 void wxMenu::Init(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
) ;
104 // The wxWindow destructor will take care of deleting the submenus.
107 // free Windows resources
110 ::DestroyMenu((HMENU
)m_hMenu
);
115 wxNode
*node
= m_menuItems
.First();
118 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
120 // Delete child menus.
121 // Beware: they must not be appended to children list!!!
122 // (because order of delete is significant)
123 if ( item
->IsSubMenu() )
124 item
->DeleteSubMenu();
126 wxNode
*next
= node
->Next();
138 // function appends a new item or submenu to the menu
139 void wxMenu::Append(wxMenuItem
*pItem
)
141 wxCHECK_RET( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
144 // check for accelerators: they are given after '\t'
145 wxString label
= pItem
->GetName();
146 int posTab
= label
.Find(wxT('\t'));
147 if ( posTab
!= wxNOT_FOUND
) {
148 // parse the accelerator string
150 int accelFlags
= wxACCEL_NORMAL
;
152 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
153 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
154 if ( current
== _("ctrl") )
155 accelFlags
|= wxACCEL_CTRL
;
156 else if ( current
== _("alt") )
157 accelFlags
|= wxACCEL_ALT
;
158 else if ( current
== _("shift") )
159 accelFlags
|= wxACCEL_SHIFT
;
161 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
168 current
+= wxTolower(label
[n
]);
172 if ( current
.IsEmpty() ) {
173 wxLogDebug(wxT("No accel key found, accel string ignored."));
176 if ( current
.Len() == 1 ) {
178 keyCode
= wxToupper(current
[0U]);
181 // is it a function key?
182 if ( current
[0U] == 'f' && isdigit(current
[1U]) &&
183 (current
.Len() == 2 ||
184 (current
.Len() == 3 && isdigit(current
[2U]))) ) {
186 wxSscanf(current
.c_str() + 1, wxT("%d"), &n
);
188 keyCode
= VK_F1
+ n
- 1;
191 // several special cases
193 if ( current
== wxT("DEL") ) {
196 else if ( current
== wxT("PGUP") ) {
199 else if ( current
== wxT("PGDN") ) {
203 wxLogDebug(wxT("Unrecognized accel key '%s', accel "
204 "string ignored."), current
.c_str());
212 m_accelKeyCodes
.Add(keyCode
);
213 m_accelFlags
.Add(accelFlags
);
214 m_accelIds
.Add(pItem
->GetId());
217 #endif // wxUSE_ACCEL
221 // if "Break" has just been called, insert a menu break before this item
222 // (and don't forget to reset the flag)
224 flags
|= MF_MENUBREAK
;
228 if ( pItem
->IsSeparator() ) {
229 flags
|= MF_SEPARATOR
;
232 // id is the numeric id for normal menu items and HMENU for submenus as
233 // required by ::AppendMenu() API
235 wxMenu
*submenu
= pItem
->GetSubMenu();
236 if ( submenu
!= NULL
) {
237 wxASSERT( submenu
->GetHMenu() != (WXHMENU
) NULL
);
239 id
= (UINT
)submenu
->GetHMenu();
240 submenu
->m_topLevelMenu
= m_topLevelMenu
;
241 submenu
->m_parent
= this;
242 submenu
->m_savehMenu
= (WXHMENU
)id
;
243 submenu
->m_hMenu
= 0;
253 #if wxUSE_OWNER_DRAWN
254 if ( pItem
->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
255 // item draws itself, pass pointer to it in data parameter
256 flags
|= MF_OWNERDRAW
;
257 pData
= (LPCTSTR
)pItem
;
262 // menu is just a normal string (passed in data parameter)
265 // Don't know what the correct cast should be, but it doesn't
266 // compile in BC++/16-bit without this cast.
267 #if !defined(__WIN32__)
268 pData
= (char*) (const char*) label
;
274 if ( !::AppendMenu(GetHmenu(), flags
, id
, pData
) )
276 wxLogLastError("AppendMenu");
281 if ( (int)id
== idMenuTitle
)
283 // visually select the menu title
285 mii
.cbSize
= sizeof(mii
);
286 mii
.fMask
= MIIM_STATE
;
287 mii
.fState
= MFS_DEFAULT
;
289 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id
, FALSE
, &mii
) )
291 wxLogLastError(wxT("SetMenuItemInfo"));
296 m_menuItems
.Append(pItem
);
301 void wxMenu::AppendSeparator()
303 Append(new wxMenuItem(this, ID_SEPARATOR
));
307 void wxMenu::Append(int id
,
308 const wxString
& label
,
310 const wxString
& helpString
)
312 Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, SubMenu
));
315 // Ordinary menu item
316 void wxMenu::Append(int id
,
317 const wxString
& label
,
318 const wxString
& helpString
,
321 // 'checkable' parameter is useless for Windows.
322 Append(new wxMenuItem(this, id
, label
, helpString
, checkable
));
326 void wxMenu::Delete(int id
)
328 wxMenuItem
*item
= NULL
;
331 for (pos
= 0, node
= m_menuItems
.First(); node
; node
= node
->Next(), pos
++)
333 item
= (wxMenuItem
*)node
->Data();
334 if ( item
->GetId() == id
)
338 wxCHECK_RET( node
, wxT("wxMenu::Delete(): item doesn't exist") );
340 HMENU menu
= GetHmenu();
342 wxMenu
*pSubMenu
= item
->GetSubMenu();
343 if ( pSubMenu
!= NULL
) {
344 RemoveMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
345 pSubMenu
->m_hMenu
= pSubMenu
->m_savehMenu
;
346 pSubMenu
->m_savehMenu
= 0;
347 pSubMenu
->m_parent
= NULL
;
348 // RemoveChild(item->subMenu);
349 pSubMenu
->m_topLevelMenu
= NULL
;
350 // TODO: Why isn't subMenu deleted here???
351 // Will put this in for now. Assuming this is supposed
352 // to delete the menu, not just remove it.
353 item
->DeleteSubMenu();
356 DeleteMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
359 m_menuItems
.DeleteNode(node
);
365 // ---------------------------------------------------------------------------
366 // accelerator helpers
367 // ---------------------------------------------------------------------------
369 // create the wxAcceleratorEntries for our accels and put them into provided
370 // array - return the number of accels we have
371 size_t wxMenu::CopyAccels(wxAcceleratorEntry
*accels
) const
373 size_t count
= GetAccelCount();
374 for ( size_t n
= 0; n
< count
; n
++ )
376 (*accels
++).Set(m_accelFlags
[n
], m_accelKeyCodes
[n
], m_accelIds
[n
]);
382 #endif // wxUSE_ACCEL
384 // ---------------------------------------------------------------------------
385 // wxMenu functions implemented in wxMenuItem
386 // ---------------------------------------------------------------------------
388 void wxMenu::Enable(int id
, bool Flag
)
390 wxMenuItem
*item
= FindItemForId(id
);
391 wxCHECK_RET( item
!= NULL
, wxT("can't enable non-existing menu item") );
396 bool wxMenu::IsEnabled(int id
) const
398 wxMenuItem
*item
= FindItemForId(id
);
399 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
401 return item
->IsEnabled();
404 void wxMenu::Check(int id
, bool Flag
)
406 wxMenuItem
*item
= FindItemForId(id
);
407 wxCHECK_RET( item
!= NULL
, wxT("can't get status of non-existing menu item") );
412 bool wxMenu::IsChecked(int id
) const
414 wxMenuItem
*item
= FindItemForId(id
);
415 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
417 return item
->IsChecked();
420 void wxMenu::SetLabel(int id
, const wxString
& label
)
422 wxMenuItem
*item
= FindItemForId(id
) ;
423 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
425 item
->SetName(label
);
428 wxString
wxMenu::GetLabel(int id
) const
431 wxMenuItem
*pItem
= FindItemForId(id
) ;
433 label
= pItem
->GetName() ;
435 wxFAIL_MSG(wxT("wxMenu::GetLabel: item doesn't exist"));
440 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
)
442 wxMenuItem
*item
= FindItemForId (itemId
);
444 item
->SetHelp(helpString
);
446 wxFAIL_MSG(wxT("wxMenu::SetHelpString: item doesn't exist"));
449 wxString
wxMenu::GetHelpString (int itemId
) const
452 wxMenuItem
*item
= FindItemForId (itemId
);
454 help
= item
->GetHelp();
456 wxFAIL_MSG(wxT("wxMenu::GetHelpString: item doesn't exist"));
461 // ---------------------------------------------------------------------------
463 // ---------------------------------------------------------------------------
465 void wxMenu::SetTitle(const wxString
& label
)
467 bool hasNoTitle
= m_title
.IsEmpty();
470 HMENU hMenu
= GetHmenu();
474 if ( !label
.IsEmpty() )
476 if ( !InsertMenu(hMenu
, 0u, MF_BYPOSITION
| MF_STRING
,
477 (unsigned)idMenuTitle
, m_title
) ||
478 !InsertMenu(hMenu
, 1u, MF_BYPOSITION
, (unsigned)-1, NULL
) )
480 wxLogLastError(wxT("InsertMenu"));
486 if ( label
.IsEmpty() )
488 // remove the title and the separator after it
489 if ( !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) ||
490 !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) )
492 wxLogLastError("RemoveMenu");
498 if ( !ModifyMenu(hMenu
, 0u,
499 MF_BYPOSITION
| MF_STRING
,
500 (unsigned)idMenuTitle
, m_title
) )
502 wxLogLastError("ModifyMenu");
508 // put the title string in bold face
509 if ( !m_title
.IsEmpty() )
512 mii
.cbSize
= sizeof(mii
);
513 mii
.fMask
= MIIM_STATE
;
514 mii
.fState
= MFS_DEFAULT
;
516 if ( !SetMenuItemInfo(hMenu
, (unsigned)idMenuTitle
, FALSE
, &mii
) )
518 wxLogLastError("SetMenuItemInfo");
524 const wxString
wxMenu::GetTitle() const
529 // ---------------------------------------------------------------------------
531 // ---------------------------------------------------------------------------
533 bool wxMenu::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD id
)
535 // ignore commands from the menu title
537 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
538 if ( id
!= (WXWORD
)idMenuTitle
)
540 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
541 event
.SetEventObject( this );
544 ProcessCommand(event
);
550 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
552 bool processed
= FALSE
;
557 (void)(*(m_callback
))(*this, event
);
561 // Try the menu's event handler
562 if ( !processed
&& GetEventHandler())
564 processed
= GetEventHandler()->ProcessEvent(event
);
567 // Try the window the menu was popped up from (and up through the
569 wxWindow
*win
= GetInvokingWindow();
570 if ( !processed
&& win
)
571 processed
= win
->GetEventHandler()->ProcessEvent(event
);
576 // ---------------------------------------------------------------------------
578 // ---------------------------------------------------------------------------
580 // Finds the item id matching the given string, -1 if not found.
581 int wxMenu::FindItem (const wxString
& itemString
) const
583 wxString itemLabel
= wxStripMenuCodes(itemString
);
584 for ( wxNode
*node
= m_menuItems
.First(); node
; node
= node
->Next() )
586 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
587 if ( item
->IsSubMenu() )
589 int ans
= item
->GetSubMenu()->FindItem(itemString
);
590 if ( ans
!= wxNOT_FOUND
)
593 else if ( !item
->IsSeparator() )
595 wxString label
= wxStripMenuCodes(item
->GetName());
596 if ( itemLabel
== label
)
597 return item
->GetId();
604 wxMenuItem
*wxMenu::FindItemForId(int itemId
, wxMenu
** itemMenu
) const
609 wxMenuItem
*item
= NULL
;
610 for ( wxNode
*node
= m_menuItems
.First(); node
&& !item
; node
= node
->Next() )
612 item
= (wxMenuItem
*)node
->Data();
614 if ( item
->GetId() == itemId
)
617 *itemMenu
= (wxMenu
*)this;
619 else if ( item
->IsSubMenu() )
621 item
= item
->GetSubMenu()->FindItemForId(itemId
, itemMenu
);
625 // don't exit the loop
633 // ---------------------------------------------------------------------------
635 // ---------------------------------------------------------------------------
637 void wxMenu::Attach(wxMenuBar
*menubar
)
639 // menu can be in at most one menubar because otherwise they would both
640 // delete the menu pointer
641 wxASSERT_MSG( !m_menuBar
, wxT("menu belongs to 2 menubars, expect a crash") );
644 m_savehMenu
= m_hMenu
;
648 void wxMenu::Detach()
650 wxASSERT_MSG( m_menuBar
, wxT("can't detach menu if it's not attached") );
652 m_hMenu
= m_savehMenu
;
656 // ---------------------------------------------------------------------------
658 // ---------------------------------------------------------------------------
660 void wxMenuBar::Init()
662 m_eventHandler
= this;
666 m_menuBarFrame
= NULL
;
670 wxMenuBar::wxMenuBar()
675 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
680 wxMenuBar::wxMenuBar(int count
, wxMenu
*menus
[], const wxString titles
[])
686 m_titles
= new wxString
[count
];
689 for ( i
= 0; i
< count
; i
++ )
690 m_titles
[i
] = titles
[i
];
692 for ( i
= 0; i
< count
; i
++ )
693 m_menus
[i
]->Attach(this);
696 wxMenuBar::~wxMenuBar()
698 for ( int i
= 0; i
< m_menuCount
; i
++ )
707 // ---------------------------------------------------------------------------
709 // ---------------------------------------------------------------------------
711 void wxMenuBar::Refresh()
713 wxCHECK_RET( m_menuBarFrame
, wxT("can't refresh a menubar withotu a frame") );
715 DrawMenuBar((HWND
)m_menuBarFrame
->GetHWND()) ;
718 WXHMENU
wxMenuBar::Create()
723 wxCHECK_MSG( !m_hMenu
, TRUE
, wxT("menubar already created") );
725 m_hMenu
= (WXHMENU
)::CreateMenu();
729 wxLogLastError("CreateMenu");
733 for ( int i
= 0; i
< m_menuCount
; i
++ )
735 if ( !::AppendMenu((HMENU
)m_hMenu
, MF_POPUP
| MF_STRING
,
736 (UINT
)m_menus
[i
]->GetHMenu(),
739 wxLogLastError("AppendMenu");
747 // ---------------------------------------------------------------------------
748 // wxMenuBar functions forwarded to wxMenuItem
749 // ---------------------------------------------------------------------------
751 // Must only be used AFTER menu has been attached to frame,
752 // otherwise use individual menus to enable/disable items
753 void wxMenuBar::Enable(int id
, bool enable
)
755 wxMenu
*itemMenu
= NULL
;
756 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
758 wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") );
760 item
->Enable(enable
);
763 void wxMenuBar::EnableTop(int pos
, bool enable
)
765 int flag
= enable
? MF_ENABLED
: MF_GRAYED
;;
767 EnableMenuItem((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
| flag
);
770 // Must only be used AFTER menu has been attached to frame,
771 // otherwise use individual menus
772 void wxMenuBar::Check(int id
, bool check
)
774 wxMenu
*itemMenu
= NULL
;
775 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
777 wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") );
778 wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") );
783 bool wxMenuBar::IsChecked(int id
) const
785 wxMenu
*itemMenu
= NULL
;
786 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
788 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsChecked(): no such item") );
790 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
);
792 return (flag
& MF_CHECKED
) != 0;
795 bool wxMenuBar::IsEnabled(int id
) const
797 wxMenu
*itemMenu
= NULL
;
798 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
800 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsEnabled(): no such item") );
802 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
) ;
804 // don't "and" with MF_ENABLED because its value is 0
805 return (flag
& MF_DISABLED
) == 0;
808 void wxMenuBar::SetLabel(int id
, const wxString
& label
)
810 wxMenu
*itemMenu
= NULL
;
811 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
813 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") );
815 item
->SetName(label
);
818 wxString
wxMenuBar::GetLabel(int id
) const
820 wxMenu
*itemMenu
= NULL
;
821 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
823 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetLabel(): no such item") );
825 return item
->GetName();
828 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
)
830 wxMenu
*itemMenu
= NULL
;
831 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
833 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") );
835 item
->SetHelp(helpString
);
838 wxString
wxMenuBar::GetHelpString (int id
) const
840 wxMenu
*itemMenu
= NULL
;
841 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
843 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetHelpString(): no such item") );
845 return item
->GetHelp();
848 // ---------------------------------------------------------------------------
849 // wxMenuBar functions to work with the top level submenus
850 // ---------------------------------------------------------------------------
852 // NB: we don't support owner drawn top level items for now, if we do these
853 // functions would have to be changed to use wxMenuItem as well
855 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
)
858 UINT flagsOld
= ::GetMenuState((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
);
859 if ( flagsOld
== 0xFFFFFFFF )
861 wxLogLastError(wxT("GetMenuState"));
866 if ( flagsOld
& MF_POPUP
)
868 // HIBYTE contains the number of items in the submenu in this case
870 id
= (UINT
)::GetSubMenu((HMENU
)m_hMenu
, pos
) ;
877 if ( ::ModifyMenu(GetHmenu(), pos
, MF_BYPOSITION
| MF_STRING
| flagsOld
,
878 id
, label
) == (int)0xFFFFFFFF )
880 wxLogLastError("ModifyMenu");
884 wxString
wxMenuBar::GetLabelTop(int pos
) const
886 int len
= ::GetMenuString((HMENU
)m_hMenu
, pos
, NULL
, 0, MF_BYCOMMAND
);
888 len
++; // for the NUL character
890 ::GetMenuString(GetHmenu(), pos
, label
.GetWriteBuf(len
), len
, MF_BYCOMMAND
);
891 label
.UngetWriteBuf();
896 // ---------------------------------------------------------------------------
897 // wxMenuBar notifications
898 // ---------------------------------------------------------------------------
900 bool wxMenuBar::OnDelete(wxMenu
*a_menu
, int pos
)
902 if ( !m_menuBarFrame
)
905 if ( ::RemoveMenu((HMENU
)m_hMenu
, (UINT
)pos
, MF_BYPOSITION
) )
907 // VZ: I'm not sure about what's going on here, so I leave an assert
908 wxASSERT_MSG( m_menus
[pos
] == a_menu
, wxT("what is this parameter for??") );
912 if ( m_menuBarFrame
)
919 wxLogLastError("RemoveMenu");
925 bool wxMenuBar::OnAppend(wxMenu
*a_menu
, const wxChar
*title
)
927 WXHMENU submenu
= a_menu
->GetHMenu();
931 if ( !m_menuBarFrame
)
934 a_menu
->Attach(this);
936 if ( !::AppendMenu(GetHmenu(), MF_POPUP
| MF_STRING
,
937 (UINT
)submenu
, title
) )
939 wxLogLastError(wxT("AppendMenu"));
947 // ---------------------------------------------------------------------------
948 // wxMenuBar construction
949 // ---------------------------------------------------------------------------
950 int wxMenuBar::FindMenu(const wxString
& title
)
952 wxString menuTitle
= wxStripMenuCodes(title
);
953 for ( int i
= 0; i
< m_menuCount
; i
++ )
955 wxString title
= wxStripMenuCodes(m_titles
[i
]);
956 if ( menuTitle
== title
)
965 void wxMenuBar::ReplaceMenu(int pos
, wxMenu
* new_menu
, const wxString
& title
)
967 if (m_menuBarFrame
) return;
969 if ( pos
>= 0 && pos
< m_menuCount
)
971 wxMenu
*old_menu
= m_menus
[pos
];
972 m_menus
[pos
] = new_menu
;
979 void wxMenuBar::Insert(int pos
, wxMenu
* menu
, const wxString
& title
)
981 if (m_menuBarFrame
) return;
982 if ( pos
< 0 && pos
>= m_menuCount
) return;
985 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
986 wxString
*new_titles
= new wxString
[m_menuCount
];
989 for (i
= 0; i
< pos
; i
++)
991 new_menus
[i
] = m_menus
[i
];
993 new_titles
[i
] = m_titles
[i
];
994 m_titles
[i
] = wxT("");
997 new_menus
[pos
] = (wxMenu
*)menu
;
998 new_titles
[i
] = title
;
1000 for (i
= pos
+1; i
< m_menuCount
; i
++)
1002 new_menus
[i
] = m_menus
[i
-1];
1003 m_menus
[i
-1] = NULL
;
1004 new_titles
[i
] = m_titles
[i
-1];
1005 m_titles
[i
-1] = wxT("");
1012 m_menus
= new_menus
;
1013 m_titles
= new_titles
;
1015 menu
->SetParent(this);
1020 void wxMenuBar::Append (wxMenu
* menu
, const wxString
& title
)
1022 if (!OnAppend(menu
, title
))
1026 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
1027 wxString
*new_titles
= new wxString
[m_menuCount
];
1030 for (i
= 0; i
< m_menuCount
- 1; i
++)
1032 new_menus
[i
] = m_menus
[i
];
1034 new_titles
[i
] = m_titles
[i
];
1035 m_titles
[i
] = wxT("");
1042 m_menus
= new_menus
;
1043 m_titles
= new_titles
;
1045 m_menus
[m_menuCount
- 1] = (wxMenu
*)menu
;
1046 m_titles
[m_menuCount
- 1] = title
;
1048 menu
->SetParent(this);
1051 void wxMenuBar::Delete(wxMenu
* menu
, int i
)
1057 for (ii
= 0; ii
< m_menuCount
; ii
++) {
1058 if (m_menus
[ii
] == menu
)
1061 if (ii
>= m_menuCount
)
1064 if (ii
< 0 || ii
>= m_menuCount
)
1069 if (!OnDelete(menu
, ii
))
1072 menu
->SetParent(NULL
);
1075 for (j
= ii
; j
< m_menuCount
; j
++) {
1076 m_menus
[j
] = m_menus
[j
+ 1];
1077 m_titles
[j
] = m_titles
[j
+ 1];
1081 void wxMenuBar::Attach(wxFrame
*frame
)
1083 wxASSERT_MSG( !m_menuBarFrame
, wxT("menubar already attached!") );
1085 m_menuBarFrame
= frame
;
1088 // create the accel table - we consider that the menubar construction is
1090 size_t nAccelCount
= 0;
1092 for ( i
= 0; i
< m_menuCount
; i
++ )
1094 nAccelCount
+= m_menus
[i
]->GetAccelCount();
1099 wxAcceleratorEntry
*accelEntries
= new wxAcceleratorEntry
[nAccelCount
];
1102 for ( i
= 0; i
< m_menuCount
; i
++ )
1104 nAccelCount
+= m_menus
[i
]->CopyAccels(&accelEntries
[nAccelCount
]);
1107 m_accelTable
= wxAcceleratorTable(nAccelCount
, accelEntries
);
1109 delete [] accelEntries
;
1111 #endif // wxUSE_ACCEL
1114 void wxMenuBar::Detach()
1116 // ::DestroyMenu((HMENU)m_hMenu);
1117 m_hMenu
= (WXHMENU
)NULL
;
1118 m_menuBarFrame
= NULL
;
1122 // ---------------------------------------------------------------------------
1123 // wxMenuBar searching for menu items
1124 // ---------------------------------------------------------------------------
1126 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1127 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1128 const wxString
& itemString
) const
1130 wxString menuLabel
= wxStripMenuCodes(menuString
);
1131 for ( int i
= 0; i
< m_menuCount
; i
++ )
1133 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1134 if ( menuString
== title
)
1135 return m_menus
[i
]->FindItem(itemString
);
1141 wxMenuItem
*wxMenuBar::FindItemForId (int id
, wxMenu
**itemMenu
) const
1146 wxMenuItem
*item
= NULL
;
1147 for ( int i
= 0; !item
&& (i
< m_menuCount
); i
++ )
1149 item
= m_menus
[i
]->FindItemForId(id
, itemMenu
);
1156 // ----------------------------------------------------------------------------
1158 // ----------------------------------------------------------------------------
1160 wxWindow
*wxMenu::GetWindow() const
1162 if ( m_pInvokingWindow
!= NULL
)
1163 return m_pInvokingWindow
;
1164 else if ( m_menuBar
!= NULL
)
1165 return m_menuBar
->GetFrame();
1170 WXHMENU
wxMenu::GetHMenu() const
1174 else if ( m_savehMenu
!= 0 )
1177 wxFAIL_MSG(wxT("wxMenu without HMENU"));
1182 // Update a menu and all submenus recursively. source is the object that has
1183 // the update event handlers defined for it. If NULL, the menu or associated
1184 // window will be used.
1185 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1187 if (!source
&& GetInvokingWindow())
1188 source
= GetInvokingWindow()->GetEventHandler();
1190 source
= GetEventHandler();
1194 wxNode
* node
= GetItems().First();
1197 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1198 if ( !item
->IsSeparator() )
1200 wxWindowID id
= item
->GetId();
1201 wxUpdateUIEvent
event(id
);
1202 event
.SetEventObject( source
);
1204 if (source
->ProcessEvent(event
))
1206 if (event
.GetSetText())
1207 SetLabel(id
, event
.GetText());
1208 if (event
.GetSetChecked())
1209 Check(id
, event
.GetChecked());
1210 if (event
.GetSetEnabled())
1211 Enable(id
, event
.GetEnabled());
1214 if (item
->GetSubMenu())
1215 item
->GetSubMenu()->UpdateUI(source
);
1217 node
= node
->Next();