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 wxAcceleratorEntry
*accel
= wxGetAccelFromString(pItem
->GetText());
148 #endif // wxUSE_ACCEL
152 // if "Break" has just been called, insert a menu break before this item
153 // (and don't forget to reset the flag)
155 flags
|= MF_MENUBREAK
;
159 if ( pItem
->IsSeparator() ) {
160 flags
|= MF_SEPARATOR
;
163 // id is the numeric id for normal menu items and HMENU for submenus as
164 // required by ::AppendMenu() API
166 wxMenu
*submenu
= pItem
->GetSubMenu();
167 if ( submenu
!= NULL
) {
168 wxASSERT( submenu
->GetHMenu() != (WXHMENU
) NULL
);
170 id
= (UINT
)submenu
->GetHMenu();
171 submenu
->m_topLevelMenu
= m_topLevelMenu
;
172 submenu
->m_parent
= this;
173 submenu
->m_savehMenu
= (WXHMENU
)id
;
174 submenu
->m_hMenu
= 0;
184 #if wxUSE_OWNER_DRAWN
185 if ( pItem
->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
186 // item draws itself, pass pointer to it in data parameter
187 flags
|= MF_OWNERDRAW
;
188 pData
= (LPCTSTR
)pItem
;
193 // menu is just a normal string (passed in data parameter)
196 pData
= (char*)pItem
->GetText().c_str();
199 if ( !::AppendMenu(GetHmenu(), flags
, id
, pData
) )
201 wxLogLastError("AppendMenu");
206 if ( (int)id
== idMenuTitle
)
208 // visually select the menu title
210 mii
.cbSize
= sizeof(mii
);
211 mii
.fMask
= MIIM_STATE
;
212 mii
.fState
= MFS_DEFAULT
;
214 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id
, FALSE
, &mii
) )
216 wxLogLastError(wxT("SetMenuItemInfo"));
221 m_menuItems
.Append(pItem
);
226 void wxMenu::AppendSeparator()
228 Append(new wxMenuItem(this, ID_SEPARATOR
));
232 void wxMenu::Append(int id
,
233 const wxString
& label
,
235 const wxString
& helpString
)
237 Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, SubMenu
));
240 // Ordinary menu item
241 void wxMenu::Append(int id
,
242 const wxString
& label
,
243 const wxString
& helpString
,
246 // 'checkable' parameter is useless for Windows.
247 Append(new wxMenuItem(this, id
, label
, helpString
, checkable
));
251 void wxMenu::Delete(int id
)
253 wxMenuItem
*item
= NULL
;
256 for (pos
= 0, node
= m_menuItems
.First(); node
; node
= node
->Next(), pos
++)
258 item
= (wxMenuItem
*)node
->Data();
259 if ( item
->GetId() == id
)
263 wxCHECK_RET( node
, wxT("wxMenu::Delete(): item doesn't exist") );
265 HMENU menu
= GetHmenu();
267 wxMenu
*pSubMenu
= item
->GetSubMenu();
268 if ( pSubMenu
!= NULL
) {
269 RemoveMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
270 pSubMenu
->m_hMenu
= pSubMenu
->m_savehMenu
;
271 pSubMenu
->m_savehMenu
= 0;
272 pSubMenu
->m_parent
= NULL
;
273 // RemoveChild(item->subMenu);
274 pSubMenu
->m_topLevelMenu
= NULL
;
275 // TODO: Why isn't subMenu deleted here???
276 // Will put this in for now. Assuming this is supposed
277 // to delete the menu, not just remove it.
278 item
->DeleteSubMenu();
281 DeleteMenu(menu
, (UINT
)pos
, MF_BYPOSITION
);
284 m_menuItems
.DeleteNode(node
);
290 // ---------------------------------------------------------------------------
291 // accelerator helpers
292 // ---------------------------------------------------------------------------
294 // create the wxAcceleratorEntries for our accels and put them into provided
295 // array - return the number of accels we have
296 size_t wxMenu::CopyAccels(wxAcceleratorEntry
*accels
) const
298 size_t count
= GetAccelCount();
299 for ( size_t n
= 0; n
< count
; n
++ )
301 *accels
++ = *m_accels
[n
];
307 #endif // wxUSE_ACCEL
309 // ---------------------------------------------------------------------------
310 // wxMenu functions implemented in wxMenuItem
311 // ---------------------------------------------------------------------------
313 void wxMenu::Enable(int id
, bool Flag
)
315 wxMenuItem
*item
= FindItemForId(id
);
316 wxCHECK_RET( item
!= NULL
, wxT("can't enable non-existing menu item") );
321 bool wxMenu::IsEnabled(int id
) const
323 wxMenuItem
*item
= FindItemForId(id
);
324 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
326 return item
->IsEnabled();
329 void wxMenu::Check(int id
, bool Flag
)
331 wxMenuItem
*item
= FindItemForId(id
);
332 wxCHECK_RET( item
!= NULL
, wxT("can't get status of non-existing menu item") );
337 bool wxMenu::IsChecked(int id
) const
339 wxMenuItem
*item
= FindItemForId(id
);
340 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
342 return item
->IsChecked();
345 void wxMenu::SetLabel(int id
, const wxString
& label
)
347 wxMenuItem
*item
= FindItemForId(id
) ;
348 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
350 item
->SetText(label
);
353 wxString
wxMenu::GetLabel(int id
) const
356 wxMenuItem
*pItem
= FindItemForId(id
) ;
358 label
= pItem
->GetText() ;
360 wxFAIL_MSG(wxT("wxMenu::GetLabel: item doesn't exist"));
365 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
)
367 wxMenuItem
*item
= FindItemForId (itemId
);
369 item
->SetHelp(helpString
);
371 wxFAIL_MSG(wxT("wxMenu::SetHelpString: item doesn't exist"));
374 wxString
wxMenu::GetHelpString (int itemId
) const
377 wxMenuItem
*item
= FindItemForId (itemId
);
379 help
= item
->GetHelp();
381 wxFAIL_MSG(wxT("wxMenu::GetHelpString: item doesn't exist"));
386 // ---------------------------------------------------------------------------
388 // ---------------------------------------------------------------------------
390 void wxMenu::SetTitle(const wxString
& label
)
392 bool hasNoTitle
= m_title
.IsEmpty();
395 HMENU hMenu
= GetHmenu();
399 if ( !label
.IsEmpty() )
401 if ( !InsertMenu(hMenu
, 0u, MF_BYPOSITION
| MF_STRING
,
402 (unsigned)idMenuTitle
, m_title
) ||
403 !InsertMenu(hMenu
, 1u, MF_BYPOSITION
, (unsigned)-1, NULL
) )
405 wxLogLastError(wxT("InsertMenu"));
411 if ( label
.IsEmpty() )
413 // remove the title and the separator after it
414 if ( !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) ||
415 !RemoveMenu(hMenu
, 0, MF_BYPOSITION
) )
417 wxLogLastError("RemoveMenu");
423 if ( !ModifyMenu(hMenu
, 0u,
424 MF_BYPOSITION
| MF_STRING
,
425 (unsigned)idMenuTitle
, m_title
) )
427 wxLogLastError("ModifyMenu");
433 // put the title string in bold face
434 if ( !m_title
.IsEmpty() )
437 mii
.cbSize
= sizeof(mii
);
438 mii
.fMask
= MIIM_STATE
;
439 mii
.fState
= MFS_DEFAULT
;
441 if ( !SetMenuItemInfo(hMenu
, (unsigned)idMenuTitle
, FALSE
, &mii
) )
443 wxLogLastError("SetMenuItemInfo");
449 const wxString
wxMenu::GetTitle() const
454 // ---------------------------------------------------------------------------
456 // ---------------------------------------------------------------------------
458 bool wxMenu::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD id
)
460 // ignore commands from the menu title
462 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
463 if ( id
!= (WXWORD
)idMenuTitle
)
465 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
466 event
.SetEventObject( this );
469 ProcessCommand(event
);
475 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
477 bool processed
= FALSE
;
482 (void)(*(m_callback
))(*this, event
);
486 // Try the menu's event handler
487 if ( !processed
&& GetEventHandler())
489 processed
= GetEventHandler()->ProcessEvent(event
);
492 // Try the window the menu was popped up from (and up through the
494 wxWindow
*win
= GetInvokingWindow();
495 if ( !processed
&& win
)
496 processed
= win
->GetEventHandler()->ProcessEvent(event
);
501 // ---------------------------------------------------------------------------
503 // ---------------------------------------------------------------------------
505 // Finds the item id matching the given string, -1 if not found.
506 int wxMenu::FindItem (const wxString
& itemString
) const
508 wxString itemLabel
= wxStripMenuCodes(itemString
);
509 for ( wxNode
*node
= m_menuItems
.First(); node
; node
= node
->Next() )
511 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
512 if ( item
->IsSubMenu() )
514 int ans
= item
->GetSubMenu()->FindItem(itemString
);
515 if ( ans
!= wxNOT_FOUND
)
518 else if ( !item
->IsSeparator() )
520 wxString label
= wxStripMenuCodes(item
->GetText());
521 if ( itemLabel
== label
)
522 return item
->GetId();
529 wxMenuItem
*wxMenu::FindItemForId(int itemId
, wxMenu
** itemMenu
) const
534 wxMenuItem
*item
= NULL
;
535 for ( wxNode
*node
= m_menuItems
.First(); node
&& !item
; node
= node
->Next() )
537 item
= (wxMenuItem
*)node
->Data();
539 if ( item
->GetId() == itemId
)
542 *itemMenu
= (wxMenu
*)this;
544 else if ( item
->IsSubMenu() )
546 item
= item
->GetSubMenu()->FindItemForId(itemId
, itemMenu
);
550 // don't exit the loop
558 // ---------------------------------------------------------------------------
560 // ---------------------------------------------------------------------------
562 void wxMenu::Attach(wxMenuBar
*menubar
)
564 // menu can be in at most one menubar because otherwise they would both
565 // delete the menu pointer
566 wxASSERT_MSG( !m_menuBar
, wxT("menu belongs to 2 menubars, expect a crash") );
569 m_savehMenu
= m_hMenu
;
573 void wxMenu::Detach()
575 wxASSERT_MSG( m_menuBar
, wxT("can't detach menu if it's not attached") );
577 m_hMenu
= m_savehMenu
;
581 // ---------------------------------------------------------------------------
583 // ---------------------------------------------------------------------------
585 void wxMenuBar::Init()
587 m_eventHandler
= this;
591 m_menuBarFrame
= NULL
;
595 wxMenuBar::wxMenuBar()
600 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
605 wxMenuBar::wxMenuBar(int count
, wxMenu
*menus
[], const wxString titles
[])
611 m_titles
= new wxString
[count
];
614 for ( i
= 0; i
< count
; i
++ )
615 m_titles
[i
] = titles
[i
];
617 for ( i
= 0; i
< count
; i
++ )
618 m_menus
[i
]->Attach(this);
621 wxMenuBar::~wxMenuBar()
623 for ( int i
= 0; i
< m_menuCount
; i
++ )
632 // ---------------------------------------------------------------------------
634 // ---------------------------------------------------------------------------
636 void wxMenuBar::Refresh()
638 wxCHECK_RET( m_menuBarFrame
, wxT("can't refresh a menubar withotu a frame") );
640 DrawMenuBar((HWND
)m_menuBarFrame
->GetHWND()) ;
643 WXHMENU
wxMenuBar::Create()
648 wxCHECK_MSG( !m_hMenu
, TRUE
, wxT("menubar already created") );
650 m_hMenu
= (WXHMENU
)::CreateMenu();
654 wxLogLastError("CreateMenu");
658 for ( int i
= 0; i
< m_menuCount
; i
++ )
660 if ( !::AppendMenu((HMENU
)m_hMenu
, MF_POPUP
| MF_STRING
,
661 (UINT
)m_menus
[i
]->GetHMenu(),
664 wxLogLastError("AppendMenu");
672 // ---------------------------------------------------------------------------
673 // wxMenuBar functions forwarded to wxMenuItem
674 // ---------------------------------------------------------------------------
676 // Must only be used AFTER menu has been attached to frame,
677 // otherwise use individual menus to enable/disable items
678 void wxMenuBar::Enable(int id
, bool enable
)
680 wxMenu
*itemMenu
= NULL
;
681 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
683 wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") );
685 item
->Enable(enable
);
688 void wxMenuBar::EnableTop(int pos
, bool enable
)
690 int flag
= enable
? MF_ENABLED
: MF_GRAYED
;;
692 EnableMenuItem((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
| flag
);
695 // Must only be used AFTER menu has been attached to frame,
696 // otherwise use individual menus
697 void wxMenuBar::Check(int id
, bool check
)
699 wxMenu
*itemMenu
= NULL
;
700 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
702 wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") );
703 wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") );
708 bool wxMenuBar::IsChecked(int id
) const
710 wxMenu
*itemMenu
= NULL
;
711 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
713 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsChecked(): no such item") );
715 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
);
717 return (flag
& MF_CHECKED
) != 0;
720 bool wxMenuBar::IsEnabled(int id
) const
722 wxMenu
*itemMenu
= NULL
;
723 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
725 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsEnabled(): no such item") );
727 int flag
= ::GetMenuState(GetHmenuOf(itemMenu
), id
, MF_BYCOMMAND
) ;
729 // don't "and" with MF_ENABLED because its value is 0
730 return (flag
& MF_DISABLED
) == 0;
733 void wxMenuBar::SetLabel(int id
, const wxString
& label
)
735 wxMenu
*itemMenu
= NULL
;
736 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
738 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") );
740 item
->SetText(label
);
743 wxString
wxMenuBar::GetLabel(int id
) const
745 wxMenu
*itemMenu
= NULL
;
746 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
748 wxCHECK_MSG( item
, wxEmptyString
,
749 wxT("wxMenuBar::GetLabel(): no such item") );
751 return item
->GetText();
754 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
)
756 wxMenu
*itemMenu
= NULL
;
757 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
759 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") );
761 item
->SetHelp(helpString
);
764 wxString
wxMenuBar::GetHelpString (int id
) const
766 wxMenu
*itemMenu
= NULL
;
767 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
769 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetHelpString(): no such item") );
771 return item
->GetHelp();
774 // ---------------------------------------------------------------------------
775 // wxMenuBar functions to work with the top level submenus
776 // ---------------------------------------------------------------------------
778 // NB: we don't support owner drawn top level items for now, if we do these
779 // functions would have to be changed to use wxMenuItem as well
781 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
)
784 UINT flagsOld
= ::GetMenuState((HMENU
)m_hMenu
, pos
, MF_BYPOSITION
);
785 if ( flagsOld
== 0xFFFFFFFF )
787 wxLogLastError(wxT("GetMenuState"));
792 if ( flagsOld
& MF_POPUP
)
794 // HIBYTE contains the number of items in the submenu in this case
796 id
= (UINT
)::GetSubMenu((HMENU
)m_hMenu
, pos
) ;
803 if ( ::ModifyMenu(GetHmenu(), pos
, MF_BYPOSITION
| MF_STRING
| flagsOld
,
804 id
, label
) == (int)0xFFFFFFFF )
806 wxLogLastError("ModifyMenu");
810 wxString
wxMenuBar::GetLabelTop(int pos
) const
812 int len
= ::GetMenuString((HMENU
)m_hMenu
, pos
, NULL
, 0, MF_BYCOMMAND
);
814 len
++; // for the NUL character
816 ::GetMenuString(GetHmenu(), pos
, label
.GetWriteBuf(len
), len
, MF_BYCOMMAND
);
817 label
.UngetWriteBuf();
822 // ---------------------------------------------------------------------------
823 // wxMenuBar notifications
824 // ---------------------------------------------------------------------------
826 bool wxMenuBar::OnDelete(wxMenu
*a_menu
, int pos
)
828 if ( !m_menuBarFrame
)
831 if ( ::RemoveMenu((HMENU
)m_hMenu
, (UINT
)pos
, MF_BYPOSITION
) )
833 // VZ: I'm not sure about what's going on here, so I leave an assert
834 wxASSERT_MSG( m_menus
[pos
] == a_menu
, wxT("what is this parameter for??") );
838 if ( m_menuBarFrame
)
845 wxLogLastError("RemoveMenu");
851 bool wxMenuBar::OnAppend(wxMenu
*a_menu
, const wxChar
*title
)
853 WXHMENU submenu
= a_menu
->GetHMenu();
857 if ( !m_menuBarFrame
)
860 a_menu
->Attach(this);
862 if ( !::AppendMenu(GetHmenu(), MF_POPUP
| MF_STRING
,
863 (UINT
)submenu
, title
) )
865 wxLogLastError(wxT("AppendMenu"));
873 // ---------------------------------------------------------------------------
874 // wxMenuBar construction
875 // ---------------------------------------------------------------------------
876 int wxMenuBar::FindMenu(const wxString
& title
)
878 wxString menuTitle
= wxStripMenuCodes(title
);
879 for ( int i
= 0; i
< m_menuCount
; i
++ )
881 wxString title
= wxStripMenuCodes(m_titles
[i
]);
882 if ( menuTitle
== title
)
891 void wxMenuBar::ReplaceMenu(int pos
, wxMenu
* new_menu
, const wxString
& title
)
893 if (m_menuBarFrame
) return;
895 if ( pos
>= 0 && pos
< m_menuCount
)
897 wxMenu
*old_menu
= m_menus
[pos
];
898 m_menus
[pos
] = new_menu
;
905 void wxMenuBar::Insert(int pos
, wxMenu
* menu
, const wxString
& title
)
907 if (m_menuBarFrame
) return;
908 if ( pos
< 0 && pos
>= m_menuCount
) return;
911 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
912 wxString
*new_titles
= new wxString
[m_menuCount
];
915 for (i
= 0; i
< pos
; i
++)
917 new_menus
[i
] = m_menus
[i
];
919 new_titles
[i
] = m_titles
[i
];
920 m_titles
[i
] = wxT("");
923 new_menus
[pos
] = (wxMenu
*)menu
;
924 new_titles
[i
] = title
;
926 for (i
= pos
+1; i
< m_menuCount
; i
++)
928 new_menus
[i
] = m_menus
[i
-1];
930 new_titles
[i
] = m_titles
[i
-1];
931 m_titles
[i
-1] = wxT("");
939 m_titles
= new_titles
;
941 menu
->SetParent(this);
946 void wxMenuBar::Append (wxMenu
* menu
, const wxString
& title
)
948 if (!OnAppend(menu
, title
))
952 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
953 wxString
*new_titles
= new wxString
[m_menuCount
];
956 for (i
= 0; i
< m_menuCount
- 1; i
++)
958 new_menus
[i
] = m_menus
[i
];
960 new_titles
[i
] = m_titles
[i
];
961 m_titles
[i
] = wxT("");
969 m_titles
= new_titles
;
971 m_menus
[m_menuCount
- 1] = (wxMenu
*)menu
;
972 m_titles
[m_menuCount
- 1] = title
;
974 menu
->SetParent(this);
977 void wxMenuBar::Delete(wxMenu
* menu
, int i
)
983 for (ii
= 0; ii
< m_menuCount
; ii
++) {
984 if (m_menus
[ii
] == menu
)
987 if (ii
>= m_menuCount
)
990 if (ii
< 0 || ii
>= m_menuCount
)
995 if (!OnDelete(menu
, ii
))
998 menu
->SetParent(NULL
);
1001 for (j
= ii
; j
< m_menuCount
; j
++) {
1002 m_menus
[j
] = m_menus
[j
+ 1];
1003 m_titles
[j
] = m_titles
[j
+ 1];
1007 void wxMenuBar::Attach(wxFrame
*frame
)
1009 wxASSERT_MSG( !m_menuBarFrame
, wxT("menubar already attached!") );
1011 m_menuBarFrame
= frame
;
1014 // create the accel table - we consider that the menubar construction is
1016 size_t nAccelCount
= 0;
1018 for ( i
= 0; i
< m_menuCount
; i
++ )
1020 nAccelCount
+= m_menus
[i
]->GetAccelCount();
1025 wxAcceleratorEntry
*accelEntries
= new wxAcceleratorEntry
[nAccelCount
];
1028 for ( i
= 0; i
< m_menuCount
; i
++ )
1030 nAccelCount
+= m_menus
[i
]->CopyAccels(&accelEntries
[nAccelCount
]);
1033 m_accelTable
= wxAcceleratorTable(nAccelCount
, accelEntries
);
1035 delete [] accelEntries
;
1037 #endif // wxUSE_ACCEL
1040 void wxMenuBar::Detach()
1042 // ::DestroyMenu((HMENU)m_hMenu);
1043 m_hMenu
= (WXHMENU
)NULL
;
1044 m_menuBarFrame
= NULL
;
1048 // ---------------------------------------------------------------------------
1049 // wxMenuBar searching for menu items
1050 // ---------------------------------------------------------------------------
1052 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1053 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1054 const wxString
& itemString
) const
1056 wxString menuLabel
= wxStripMenuCodes(menuString
);
1057 for ( int i
= 0; i
< m_menuCount
; i
++ )
1059 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1060 if ( menuString
== title
)
1061 return m_menus
[i
]->FindItem(itemString
);
1067 wxMenuItem
*wxMenuBar::FindItemForId (int id
, wxMenu
**itemMenu
) const
1072 wxMenuItem
*item
= NULL
;
1073 for ( int i
= 0; !item
&& (i
< m_menuCount
); i
++ )
1075 item
= m_menus
[i
]->FindItemForId(id
, itemMenu
);
1082 // ----------------------------------------------------------------------------
1084 // ----------------------------------------------------------------------------
1086 wxWindow
*wxMenu::GetWindow() const
1088 if ( m_pInvokingWindow
!= NULL
)
1089 return m_pInvokingWindow
;
1090 else if ( m_menuBar
!= NULL
)
1091 return m_menuBar
->GetFrame();
1096 WXHMENU
wxMenu::GetHMenu() const
1100 else if ( m_savehMenu
!= 0 )
1103 wxFAIL_MSG(wxT("wxMenu without HMENU"));
1108 // Update a menu and all submenus recursively. source is the object that has
1109 // the update event handlers defined for it. If NULL, the menu or associated
1110 // window will be used.
1111 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1113 if (!source
&& GetInvokingWindow())
1114 source
= GetInvokingWindow()->GetEventHandler();
1116 source
= GetEventHandler();
1120 wxNode
* node
= GetItems().First();
1123 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1124 if ( !item
->IsSeparator() )
1126 wxWindowID id
= item
->GetId();
1127 wxUpdateUIEvent
event(id
);
1128 event
.SetEventObject( source
);
1130 if (source
->ProcessEvent(event
))
1132 if (event
.GetSetText())
1133 SetLabel(id
, event
.GetText());
1134 if (event
.GetSetChecked())
1135 Check(id
, event
.GetChecked());
1136 if (event
.GetSetEnabled())
1137 Enable(id
, event
.GetEnabled());
1140 if (item
->GetSubMenu())
1141 item
->GetSubMenu()->UpdateUI(source
);
1143 node
= node
->Next();