/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/menu.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/menu.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (9 years, 11 months ago) by william
File size: 39382 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/menu.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin
6 // Created: 04/01/98
7 // RCS-ID: $Id: menu.cpp 54478 2008-07-03 15:42:18Z VZ $
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_MENUS
28
29 #include "wx/menu.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
33 #include "wx/frame.h"
34 #include "wx/utils.h"
35 #include "wx/intl.h"
36 #include "wx/log.h"
37 #endif
38
39 #if wxUSE_OWNER_DRAWN
40 #include "wx/ownerdrw.h"
41 #endif
42
43 #include "wx/msw/private.h"
44
45 #ifdef __WXWINCE__
46 #include <windows.h>
47 #include <windowsx.h>
48 #include <tchar.h>
49 #include <ole2.h>
50 #include <shellapi.h>
51 #if (_WIN32_WCE < 400) && !defined(__HANDHELDPC__)
52 #include <aygshell.h>
53 #endif
54
55 #include "wx/msw/wince/missing.h"
56
57 #endif
58
59 // other standard headers
60 #include <string.h>
61
62 #if wxUSE_OWNER_DRAWN && defined(MIIM_BITMAP)
63 #include "wx/dynlib.h"
64 #endif
65
66 #ifndef MNS_CHECKORBMP
67 #define MNS_CHECKORBMP 0x04000000
68 #endif
69 #ifndef MIM_STYLE
70 #define MIM_STYLE 0x00000010
71 #endif
72
73 // ----------------------------------------------------------------------------
74 // global variables
75 // ----------------------------------------------------------------------------
76
77 // ----------------------------------------------------------------------------
78 // constants
79 // ----------------------------------------------------------------------------
80
81 // the (popup) menu title has this special id
82 static const int idMenuTitle = -3;
83
84 // ----------------------------------------------------------------------------
85 // private functions
86 // ----------------------------------------------------------------------------
87
88 // make the given menu item default
89 static void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu),
90 UINT WXUNUSED_IN_WINCE(id))
91 {
92 #ifndef __WXWINCE__
93 MENUITEMINFO mii;
94 wxZeroMemory(mii);
95 mii.cbSize = sizeof(MENUITEMINFO);
96 mii.fMask = MIIM_STATE;
97 mii.fState = MFS_DEFAULT;
98
99 if ( !::SetMenuItemInfo(hmenu, id, FALSE, &mii) )
100 {
101 wxLogLastError(wxT("SetMenuItemInfo"));
102 }
103 #endif
104 }
105
106 #ifdef __WXWINCE__
107 UINT GetMenuState(HMENU hMenu, UINT id, UINT flags)
108 {
109 MENUITEMINFO info;
110 wxZeroMemory(info);
111 info.cbSize = sizeof(info);
112 info.fMask = MIIM_STATE;
113 // MF_BYCOMMAND is zero so test MF_BYPOSITION
114 if ( !::GetMenuItemInfo(hMenu, id, flags & MF_BYPOSITION ? TRUE : FALSE , & info) )
115 wxLogLastError(wxT("GetMenuItemInfo"));
116 return info.fState;
117 }
118 #endif
119
120 // ============================================================================
121 // implementation
122 // ============================================================================
123
124 #include "wx/listimpl.cpp"
125
126 WX_DEFINE_LIST( wxMenuInfoList )
127
128 #if wxUSE_EXTENDED_RTTI
129
130 WX_DEFINE_FLAGS( wxMenuStyle )
131
132 wxBEGIN_FLAGS( wxMenuStyle )
133 wxFLAGS_MEMBER(wxMENU_TEAROFF)
134 wxEND_FLAGS( wxMenuStyle )
135
136 IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler,"wx/menu.h")
137
138 wxCOLLECTION_TYPE_INFO( wxMenuItem * , wxMenuItemList ) ;
139
140 template<> void wxCollectionToVariantArray( wxMenuItemList const &theList, wxxVariantArray &value)
141 {
142 wxListCollectionToVariantArray<wxMenuItemList::compatibility_iterator>( theList , value ) ;
143 }
144
145 wxBEGIN_PROPERTIES_TABLE(wxMenu)
146 wxEVENT_PROPERTY( Select , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent)
147 wxPROPERTY( Title, wxString , SetTitle, GetTitle, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
148 wxREADONLY_PROPERTY_FLAGS( MenuStyle , wxMenuStyle , long , GetStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
149 wxPROPERTY_COLLECTION( MenuItems , wxMenuItemList , wxMenuItem* , Append , GetMenuItems , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
150 wxEND_PROPERTIES_TABLE()
151
152 wxBEGIN_HANDLERS_TABLE(wxMenu)
153 wxEND_HANDLERS_TABLE()
154
155 wxDIRECT_CONSTRUCTOR_2( wxMenu , wxString , Title , long , MenuStyle )
156
157 WX_DEFINE_FLAGS( wxMenuBarStyle )
158
159 wxBEGIN_FLAGS( wxMenuBarStyle )
160 wxFLAGS_MEMBER(wxMB_DOCKABLE)
161 wxEND_FLAGS( wxMenuBarStyle )
162
163 // the negative id would lead the window (its superclass !) to vetoe streaming out otherwise
164 bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxWriter * , wxPersister * , wxxVariantArray & )
165 {
166 return true ;
167 }
168
169 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow ,"wx/menu.h",wxMenuBarStreamingCallback)
170
171 IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfo, wxObject , "wx/menu.h" )
172
173 wxBEGIN_PROPERTIES_TABLE(wxMenuInfo)
174 wxREADONLY_PROPERTY( Menu , wxMenu* , GetMenu , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
175 wxREADONLY_PROPERTY( Title , wxString , GetTitle , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
176 wxEND_PROPERTIES_TABLE()
177
178 wxBEGIN_HANDLERS_TABLE(wxMenuInfo)
179 wxEND_HANDLERS_TABLE()
180
181 wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title )
182
183 wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ;
184
185 template<> void wxCollectionToVariantArray( wxMenuInfoList const &theList, wxxVariantArray &value)
186 {
187 wxListCollectionToVariantArray<wxMenuInfoList::compatibility_iterator>( theList , value ) ;
188 }
189
190 wxBEGIN_PROPERTIES_TABLE(wxMenuBar)
191 wxPROPERTY_COLLECTION( MenuInfos , wxMenuInfoList , wxMenuInfo* , Append , GetMenuInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
192 wxEND_PROPERTIES_TABLE()
193
194 wxBEGIN_HANDLERS_TABLE(wxMenuBar)
195 wxEND_HANDLERS_TABLE()
196
197 wxCONSTRUCTOR_DUMMY( wxMenuBar )
198
199 #else
200 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
201 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow)
202 IMPLEMENT_DYNAMIC_CLASS(wxMenuInfo, wxObject)
203 #endif
204
205 const wxMenuInfoList& wxMenuBar::GetMenuInfos() const
206 {
207 wxMenuInfoList* list = const_cast< wxMenuInfoList* >( &m_menuInfos ) ;
208 WX_CLEAR_LIST( wxMenuInfoList , *list ) ;
209 for( size_t i = 0 ; i < GetMenuCount() ; ++i )
210 {
211 wxMenuInfo* info = new wxMenuInfo() ;
212 info->Create( const_cast<wxMenuBar*>(this)->GetMenu(i) , GetLabelTop(i) ) ;
213 list->Append( info ) ;
214 }
215 return m_menuInfos ;
216 }
217
218 // ---------------------------------------------------------------------------
219 // wxMenu construction, adding and removing menu items
220 // ---------------------------------------------------------------------------
221
222 // Construct a menu with optional title (then use append)
223 void wxMenu::Init()
224 {
225 m_doBreak = false;
226 m_startRadioGroup = -1;
227
228 // create the menu
229 m_hMenu = (WXHMENU)CreatePopupMenu();
230 if ( !m_hMenu )
231 {
232 wxLogLastError(wxT("CreatePopupMenu"));
233 }
234
235 // if we have a title, insert it in the beginning of the menu
236 if ( !m_title.empty() )
237 {
238 Append(idMenuTitle, m_title);
239 AppendSeparator();
240 }
241 }
242
243 // The wxWindow destructor will take care of deleting the submenus.
244 wxMenu::~wxMenu()
245 {
246 // we should free Windows resources only if Windows doesn't do it for us
247 // which happens if we're attached to a menubar or a submenu of another
248 // menu
249 if ( !IsAttached() && !GetParent() )
250 {
251 if ( !::DestroyMenu(GetHmenu()) )
252 {
253 wxLogLastError(wxT("DestroyMenu"));
254 }
255 }
256
257 #if wxUSE_ACCEL
258 // delete accels
259 WX_CLEAR_ARRAY(m_accels);
260 #endif // wxUSE_ACCEL
261 }
262
263 void wxMenu::Break()
264 {
265 // this will take effect during the next call to Append()
266 m_doBreak = true;
267 }
268
269 void wxMenu::Attach(wxMenuBarBase *menubar)
270 {
271 wxMenuBase::Attach(menubar);
272
273 EndRadioGroup();
274 }
275
276 #if wxUSE_ACCEL
277
278 int wxMenu::FindAccel(int id) const
279 {
280 size_t n, count = m_accels.GetCount();
281 for ( n = 0; n < count; n++ )
282 {
283 if ( m_accels[n]->m_command == id )
284 return n;
285 }
286
287 return wxNOT_FOUND;
288 }
289
290 void wxMenu::UpdateAccel(wxMenuItem *item)
291 {
292 if ( item->IsSubMenu() )
293 {
294 wxMenu *submenu = item->GetSubMenu();
295 wxMenuItemList::compatibility_iterator node = submenu->GetMenuItems().GetFirst();
296 while ( node )
297 {
298 UpdateAccel(node->GetData());
299
300 node = node->GetNext();
301 }
302 }
303 else if ( !item->IsSeparator() )
304 {
305 // recurse upwards: we should only modify m_accels of the top level
306 // menus, not of the submenus as wxMenuBar doesn't look at them
307 // (alternative and arguable cleaner solution would be to recurse
308 // downwards in GetAccelCount() and CopyAccels())
309 if ( GetParent() )
310 {
311 GetParent()->UpdateAccel(item);
312 return;
313 }
314
315 // find the (new) accel for this item
316 wxAcceleratorEntry *accel = wxAcceleratorEntry::Create(item->GetText());
317 if ( accel )
318 accel->m_command = item->GetId();
319
320 // find the old one
321 int n = FindAccel(item->GetId());
322 if ( n == wxNOT_FOUND )
323 {
324 // no old, add new if any
325 if ( accel )
326 m_accels.Add(accel);
327 else
328 return; // skipping RebuildAccelTable() below
329 }
330 else
331 {
332 // replace old with new or just remove the old one if no new
333 delete m_accels[n];
334 if ( accel )
335 m_accels[n] = accel;
336 else
337 m_accels.RemoveAt(n);
338 }
339
340 if ( IsAttached() )
341 {
342 GetMenuBar()->RebuildAccelTable();
343 }
344 }
345 //else: it is a separator, they can't have accels, nothing to do
346 }
347
348 #endif // wxUSE_ACCEL
349
350 // append a new item or submenu to the menu
351 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
352 {
353 #if wxUSE_ACCEL
354 UpdateAccel(pItem);
355 #endif // wxUSE_ACCEL
356
357 // we should support disabling the item even prior to adding it to the menu
358 UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;
359
360 // if "Break" has just been called, insert a menu break before this item
361 // (and don't forget to reset the flag)
362 if ( m_doBreak ) {
363 flags |= MF_MENUBREAK;
364 m_doBreak = false;
365 }
366
367 if ( pItem->IsSeparator() ) {
368 flags |= MF_SEPARATOR;
369 }
370
371 // id is the numeric id for normal menu items and HMENU for submenus as
372 // required by ::AppendMenu() API
373 UINT id;
374 wxMenu *submenu = pItem->GetSubMenu();
375 if ( submenu != NULL ) {
376 wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );
377
378 submenu->SetParent(this);
379
380 id = (UINT)submenu->GetHMenu();
381
382 flags |= MF_POPUP;
383 }
384 else {
385 id = pItem->GetId();
386 }
387
388
389 // prepare to insert the item in the menu
390 wxString itemText = pItem->GetText();
391 LPCTSTR pData = NULL;
392 if ( pos == (size_t)-1 )
393 {
394 // append at the end (note that the item is already appended to
395 // internal data structures)
396 pos = GetMenuItemCount() - 1;
397 }
398
399 // adjust position to account for the title, if any
400 if ( !m_title.empty() )
401 pos += 2; // for the title itself and its separator
402
403 BOOL ok = false;
404
405 #if wxUSE_OWNER_DRAWN
406 // Currently, mixing owner-drawn and non-owner-drawn items results in
407 // inconsistent margins, so we force this to be owner-drawn if any other
408 // items already are. Later we might want to use a boolean in the wxMenu
409 // to avoid search. Also we might make this fix unnecessary by getting the correct
410 // margin using NONCLIENTMETRICS.
411 if ( !pItem->IsOwnerDrawn() && !pItem->IsSeparator() )
412 {
413 // Check if any other items are ownerdrawn, and make ownerdrawn if so
414 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
415 while (node)
416 {
417 if (node->GetData()->IsOwnerDrawn())
418 {
419 pItem->SetOwnerDrawn(true);
420 break;
421 }
422 node = node->GetNext();
423 }
424 }
425 #endif
426
427 // check if we have something more than a simple text item
428 #if wxUSE_OWNER_DRAWN
429 if ( pItem->IsOwnerDrawn() )
430 {
431 // is the item owner-drawn just because of the [checked] bitmap?
432 if ( (pItem->GetBitmap(false).Ok() || pItem->GetBitmap(true).Ok()) &&
433 !pItem->GetTextColour().Ok() &&
434 !pItem->GetBackgroundColour().Ok() &&
435 !pItem->GetFont().Ok() )
436 {
437 // try to use InsertMenuItem() as it's guaranteed to look correct
438 // while our owner-drawn code is not
439
440 // first compile-time check
441 // MIIM_BITMAP only works under Win98/2000+
442 #if defined(MIIM_BITMAP) && (_WIN32_WINNT >= 0x0500)
443 WinStruct<wxMENUITEMINFO_> mii;
444 if ( wxGetWinVersion() >= wxWinVersion_98 )
445 {
446 mii.fMask = MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
447 if ( pItem->IsCheckable() )
448 {
449 // need to set checked/unchecked bitmaps as otherwise our
450 // MSWOnDrawItem() item is not called
451 mii.fMask |= MIIM_CHECKMARKS;
452 }
453
454 mii.cch = itemText.length();
455 mii.dwTypeData = wx_const_cast(wxChar *, itemText.c_str());
456
457 if (flags & MF_POPUP)
458 {
459 mii.fMask |= MIIM_SUBMENU;
460 mii.hSubMenu = (HMENU)pItem->GetSubMenu()->GetHMenu();
461 }
462 else
463 {
464 mii.fMask |= MIIM_ID;
465 mii.wID = id;
466 }
467
468 // we can't pass HBITMAP directly as hbmpItem for 2 reasons:
469 // 1. we can't draw it with transparency then (this is not
470 // very important now but would be with themed menu bg)
471 // 2. worse, Windows inverts the bitmap for the selected
472 // item and this looks downright ugly
473 //
474 // so instead draw it ourselves in MSWOnDrawItem()
475 mii.dwItemData = wx_reinterpret_cast(ULONG_PTR, pItem);
476 if ( pItem->IsCheckable() )
477 {
478 mii.hbmpChecked =
479 mii.hbmpUnchecked = HBMMENU_CALLBACK;
480 }
481 mii.hbmpItem = HBMMENU_CALLBACK;
482
483 ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */,
484 (MENUITEMINFO*)&mii);
485 if ( !ok )
486 {
487 wxLogLastError(wxT("InsertMenuItem()"));
488 }
489 else // InsertMenuItem() ok
490 {
491 // we need to remove the extra indent which is reserved for
492 // the checkboxes by default as it looks ugly unless check
493 // boxes are used together with bitmaps and this is not the
494 // case in wx API
495 WinStruct<MENUINFO> mi;
496
497 // don't call SetMenuInfo() directly, this would prevent
498 // the app from starting up under Windows 95/NT 4
499 typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);
500
501 wxDynamicLibrary dllUser(_T("user32"));
502 wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
503 if ( pfnSetMenuInfo )
504 {
505 mi.fMask = MIM_STYLE;
506 mi.dwStyle = MNS_CHECKORBMP;
507 if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
508 wxLogLastError(_T("SetMenuInfo(MNS_NOCHECK)"));
509 }
510
511 // tell the item that it's not really owner-drawn but only
512 // needs to draw its bitmap, the rest is done by Windows
513 pItem->ResetOwnerDrawn();
514 }
515 }
516 #endif // defined(MIIM_BITMAP) && (_WIN32_WINNT >= 0x0500)
517 }
518
519 if ( !ok )
520 {
521 // item draws itself, pass pointer to it in data parameter
522 flags |= MF_OWNERDRAW;
523 pData = (LPCTSTR)pItem;
524 }
525 }
526 else
527 #endif // wxUSE_OWNER_DRAWN
528 {
529 // item is just a normal string (passed in data parameter)
530 flags |= MF_STRING;
531
532 #ifdef __WXWINCE__
533 itemText = wxMenuItem::GetLabelFromText(itemText);
534 #endif
535
536 pData = (wxChar*)itemText.c_str();
537 }
538
539 // item might have already been inserted by InsertMenuItem() above
540 if ( !ok )
541 {
542 if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
543 {
544 wxLogLastError(wxT("InsertMenu[Item]()"));
545
546 return false;
547 }
548 }
549
550
551 // if we just appended the title, highlight it
552 if ( (int)id == idMenuTitle )
553 {
554 // visually select the menu title
555 SetDefaultMenuItem(GetHmenu(), id);
556 }
557
558 // if we're already attached to the menubar, we must update it
559 if ( IsAttached() && GetMenuBar()->IsAttached() )
560 {
561 GetMenuBar()->Refresh();
562 }
563
564 return true;
565 }
566
567 void wxMenu::EndRadioGroup()
568 {
569 // we're not inside a radio group any longer
570 m_startRadioGroup = -1;
571 }
572
573 wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
574 {
575 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
576
577 bool check = false;
578
579 if ( item->GetKind() == wxITEM_RADIO )
580 {
581 int count = GetMenuItemCount();
582
583 if ( m_startRadioGroup == -1 )
584 {
585 // start a new radio group
586 m_startRadioGroup = count;
587
588 // for now it has just one element
589 item->SetAsRadioGroupStart();
590 item->SetRadioGroupEnd(m_startRadioGroup);
591
592 // ensure that we have a checked item in the radio group
593 check = true;
594 }
595 else // extend the current radio group
596 {
597 // we need to update its end item
598 item->SetRadioGroupStart(m_startRadioGroup);
599 wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup);
600
601 if ( node )
602 {
603 node->GetData()->SetRadioGroupEnd(count);
604 }
605 else
606 {
607 wxFAIL_MSG( _T("where is the radio group start item?") );
608 }
609 }
610 }
611 else // not a radio item
612 {
613 EndRadioGroup();
614 }
615
616 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
617 {
618 return NULL;
619 }
620
621 if ( check )
622 {
623 // check the item initially
624 item->Check(true);
625 }
626
627 return item;
628 }
629
630 wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
631 {
632 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
633 return item;
634 else
635 return NULL;
636 }
637
638 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
639 {
640 // we need to find the item's position in the child list
641 size_t pos;
642 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
643 for ( pos = 0; node; pos++ )
644 {
645 if ( node->GetData() == item )
646 break;
647
648 node = node->GetNext();
649 }
650
651 // DoRemove() (unlike Remove) can only be called for an existing item!
652 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
653
654 #if wxUSE_ACCEL
655 // remove the corresponding accel from the accel table
656 int n = FindAccel(item->GetId());
657 if ( n != wxNOT_FOUND )
658 {
659 delete m_accels[n];
660
661 m_accels.RemoveAt(n);
662 }
663 //else: this item doesn't have an accel, nothing to do
664 #endif // wxUSE_ACCEL
665
666 // remove the item from the menu
667 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
668 {
669 wxLogLastError(wxT("RemoveMenu"));
670 }
671
672 if ( IsAttached() && GetMenuBar()->IsAttached() )
673 {
674 // otherwise, the change won't be visible
675 GetMenuBar()->Refresh();
676 }
677
678 // and from internal data structures
679 return wxMenuBase::DoRemove(item);
680 }
681
682 // ---------------------------------------------------------------------------
683 // accelerator helpers
684 // ---------------------------------------------------------------------------
685
686 #if wxUSE_ACCEL
687
688 // create the wxAcceleratorEntries for our accels and put them into the provided
689 // array - return the number of accels we have
690 size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
691 {
692 size_t count = GetAccelCount();
693 for ( size_t n = 0; n < count; n++ )
694 {
695 *accels++ = *m_accels[n];
696 }
697
698 return count;
699 }
700
701 #endif // wxUSE_ACCEL
702
703 // ---------------------------------------------------------------------------
704 // set wxMenu title
705 // ---------------------------------------------------------------------------
706
707 void wxMenu::SetTitle(const wxString& label)
708 {
709 bool hasNoTitle = m_title.empty();
710 m_title = label;
711
712 HMENU hMenu = GetHmenu();
713
714 if ( hasNoTitle )
715 {
716 if ( !label.empty() )
717 {
718 if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
719 (unsigned)idMenuTitle, m_title) ||
720 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
721 {
722 wxLogLastError(wxT("InsertMenu"));
723 }
724 }
725 }
726 else
727 {
728 if ( label.empty() )
729 {
730 // remove the title and the separator after it
731 if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
732 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
733 {
734 wxLogLastError(wxT("RemoveMenu"));
735 }
736 }
737 else
738 {
739 // modify the title
740 #ifdef __WXWINCE__
741 MENUITEMINFO info;
742 wxZeroMemory(info);
743 info.cbSize = sizeof(info);
744 info.fMask = MIIM_TYPE;
745 info.fType = MFT_STRING;
746 info.cch = m_title.length();
747 info.dwTypeData = (LPTSTR) m_title.c_str();
748 if ( !SetMenuItemInfo(hMenu, 0, TRUE, & info) )
749 {
750 wxLogLastError(wxT("SetMenuItemInfo"));
751 }
752 #else
753 if ( !ModifyMenu(hMenu, 0u,
754 MF_BYPOSITION | MF_STRING,
755 (unsigned)idMenuTitle, m_title) )
756 {
757 wxLogLastError(wxT("ModifyMenu"));
758 }
759 #endif
760 }
761 }
762
763 #ifdef __WIN32__
764 // put the title string in bold face
765 if ( !m_title.empty() )
766 {
767 SetDefaultMenuItem(GetHmenu(), (UINT)idMenuTitle);
768 }
769 #endif // Win32
770 }
771
772 // ---------------------------------------------------------------------------
773 // event processing
774 // ---------------------------------------------------------------------------
775
776 bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id)
777 {
778 // ignore commands from the menu title
779 if ( id != (WXWORD)idMenuTitle )
780 {
781 // update the check item when it's clicked
782 wxMenuItem * const item = FindItem(id);
783 if ( item && item->IsCheckable() )
784 item->Toggle();
785
786 // get the status of the menu item: note that it has been just changed
787 // by Toggle() above so here we already get the new state of the item
788 UINT menuState = ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND);
789 SendEvent(id, menuState & MF_CHECKED);
790 }
791
792 return true;
793 }
794
795 // ---------------------------------------------------------------------------
796 // other
797 // ---------------------------------------------------------------------------
798
799 wxWindow *wxMenu::GetWindow() const
800 {
801 if ( m_invokingWindow != NULL )
802 return m_invokingWindow;
803 else if ( GetMenuBar() != NULL)
804 return GetMenuBar()->GetFrame();
805
806 return NULL;
807 }
808
809 // ---------------------------------------------------------------------------
810 // Menu Bar
811 // ---------------------------------------------------------------------------
812
813 void wxMenuBar::Init()
814 {
815 m_eventHandler = this;
816 m_hMenu = 0;
817 #if wxUSE_TOOLBAR && defined(__WXWINCE__)
818 m_toolBar = NULL;
819 #endif
820 // Not using a combined wxToolBar/wxMenuBar? then use
821 // a commandbar in WinCE .NET just to implement the
822 // menubar.
823 #if defined(WINCE_WITH_COMMANDBAR)
824 m_commandBar = NULL;
825 m_adornmentsAdded = false;
826 #endif
827 }
828
829 wxMenuBar::wxMenuBar()
830 {
831 Init();
832 }
833
834 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
835 {
836 Init();
837 }
838
839 wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
840 {
841 Init();
842
843 m_titles.Alloc(count);
844
845 for ( size_t i = 0; i < count; i++ )
846 {
847 m_menus.Append(menus[i]);
848 m_titles.Add(titles[i]);
849
850 menus[i]->Attach(this);
851 }
852 }
853
854 wxMenuBar::~wxMenuBar()
855 {
856 // In Windows CE (not .NET), the menubar is always associated
857 // with a toolbar, which destroys the menu implicitly.
858 #if defined(WINCE_WITHOUT_COMMANDBAR) && defined(__POCKETPC__)
859 if (GetToolBar())
860 {
861 wxToolMenuBar* toolMenuBar = wxDynamicCast(GetToolBar(), wxToolMenuBar);
862 if (toolMenuBar)
863 toolMenuBar->SetMenuBar(NULL);
864 }
865 #else
866 // we should free Windows resources only if Windows doesn't do it for us
867 // which happens if we're attached to a frame
868 if (m_hMenu && !IsAttached())
869 {
870 #if defined(WINCE_WITH_COMMANDBAR)
871 ::DestroyWindow((HWND) m_commandBar);
872 m_commandBar = (WXHWND) NULL;
873 #else
874 ::DestroyMenu((HMENU)m_hMenu);
875 #endif
876 m_hMenu = (WXHMENU)NULL;
877 }
878 #endif
879 }
880
881 // ---------------------------------------------------------------------------
882 // wxMenuBar helpers
883 // ---------------------------------------------------------------------------
884
885 void wxMenuBar::Refresh()
886 {
887 if ( IsFrozen() )
888 return;
889
890 wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") );
891
892 #if defined(WINCE_WITHOUT_COMMANDBAR)
893 if (GetToolBar())
894 {
895 CommandBar_DrawMenuBar((HWND) GetToolBar()->GetHWND(), 0);
896 }
897 #elif defined(WINCE_WITH_COMMANDBAR)
898 if (m_commandBar)
899 DrawMenuBar((HWND) m_commandBar);
900 #else
901 DrawMenuBar(GetHwndOf(GetFrame()));
902 #endif
903 }
904
905 WXHMENU wxMenuBar::Create()
906 {
907 // Note: this doesn't work at all on Smartphone,
908 // since you have to use resources.
909 // We'll have to find another way to add a menu
910 // by changing/adding menu items to an existing menu.
911 #if defined(WINCE_WITHOUT_COMMANDBAR)
912 if ( m_hMenu != 0 )
913 return m_hMenu;
914
915 if (!GetToolBar())
916 return 0;
917
918 HWND hCommandBar = (HWND) GetToolBar()->GetHWND();
919 HMENU hMenu = (HMENU)::SendMessage(hCommandBar, SHCMBM_GETMENU, (WPARAM)0, (LPARAM)0);
920
921 // hMenu may be zero on Windows Mobile 5. So add the menus anyway.
922 if (1) // (hMenu)
923 {
924 TBBUTTON tbButton;
925 memset(&tbButton, 0, sizeof(TBBUTTON));
926 tbButton.iBitmap = I_IMAGENONE;
927 tbButton.fsState = TBSTATE_ENABLED;
928 tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;
929
930 size_t i;
931 for (i = 0; i < GetMenuCount(); i++)
932 {
933 HMENU hPopupMenu = (HMENU) GetMenu(i)->GetHMenu() ;
934 tbButton.dwData = (DWORD)hPopupMenu;
935 wxString label = wxStripMenuCodes(GetLabelTop(i));
936 tbButton.iString = (int) label.c_str();
937
938 int position = i;
939
940 tbButton.idCommand = NewControlId();
941 if (!::SendMessage(hCommandBar, TB_INSERTBUTTON, position, (LPARAM)&tbButton))
942 {
943 wxLogLastError(wxT("TB_INSERTBUTTON"));
944 }
945 }
946 }
947 m_hMenu = (WXHMENU) hMenu;
948 return m_hMenu;
949 #else
950 if ( m_hMenu != 0 )
951 return m_hMenu;
952
953 m_hMenu = (WXHMENU)::CreateMenu();
954
955 if ( !m_hMenu )
956 {
957 wxLogLastError(wxT("CreateMenu"));
958 }
959 else
960 {
961 size_t count = GetMenuCount(), i;
962 wxMenuList::iterator it;
963 for ( i = 0, it = m_menus.begin(); i < count; i++, it++ )
964 {
965 if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING,
966 (UINT)(*it)->GetHMenu(),
967 m_titles[i]) )
968 {
969 wxLogLastError(wxT("AppendMenu"));
970 }
971 }
972 }
973
974 return m_hMenu;
975 #endif
976 }
977
978 int wxMenuBar::MSWPositionForWxMenu(wxMenu *menu, int wxpos)
979 {
980 wxASSERT(menu);
981 wxASSERT(menu->GetHMenu());
982 wxASSERT(m_hMenu);
983
984 #if defined(__WXWINCE__)
985 int totalMSWItems = GetMenuCount();
986 #else
987 int totalMSWItems = GetMenuItemCount((HMENU)m_hMenu);
988 #endif
989
990 int i; // For old C++ compatibility
991 for(i=wxpos; i<totalMSWItems; i++)
992 {
993 if(GetSubMenu((HMENU)m_hMenu,i)==(HMENU)menu->GetHMenu())
994 return i;
995 }
996 for(i=0; i<wxpos; i++)
997 {
998 if(GetSubMenu((HMENU)m_hMenu,i)==(HMENU)menu->GetHMenu())
999 return i;
1000 }
1001 wxFAIL;
1002 return -1;
1003 }
1004
1005 // ---------------------------------------------------------------------------
1006 // wxMenuBar functions to work with the top level submenus
1007 // ---------------------------------------------------------------------------
1008
1009 // NB: we don't support owner drawn top level items for now, if we do these
1010 // functions would have to be changed to use wxMenuItem as well
1011
1012 void wxMenuBar::EnableTop(size_t pos, bool enable)
1013 {
1014 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
1015 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
1016
1017 int flag = enable ? MF_ENABLED : MF_GRAYED;
1018
1019 EnableMenuItem((HMENU)m_hMenu, MSWPositionForWxMenu(GetMenu(pos),pos), MF_BYPOSITION | flag);
1020
1021 Refresh();
1022 }
1023
1024 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
1025 {
1026 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
1027
1028 m_titles[pos] = label;
1029
1030 if ( !IsAttached() )
1031 {
1032 return;
1033 }
1034 //else: have to modify the existing menu
1035
1036 int mswpos = MSWPositionForWxMenu(GetMenu(pos),pos);
1037
1038 UINT id;
1039 UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, mswpos, MF_BYPOSITION);
1040 if ( flagsOld == 0xFFFFFFFF )
1041 {
1042 wxLogLastError(wxT("GetMenuState"));
1043
1044 return;
1045 }
1046
1047 if ( flagsOld & MF_POPUP )
1048 {
1049 // HIBYTE contains the number of items in the submenu in this case
1050 flagsOld &= 0xff;
1051 id = (UINT)::GetSubMenu((HMENU)m_hMenu, mswpos);
1052 }
1053 else
1054 {
1055 id = pos;
1056 }
1057
1058 #ifdef __WXWINCE__
1059 MENUITEMINFO info;
1060 wxZeroMemory(info);
1061 info.cbSize = sizeof(info);
1062 info.fMask = MIIM_TYPE;
1063 info.fType = MFT_STRING;
1064 info.cch = label.length();
1065 info.dwTypeData = (LPTSTR) label.c_str();
1066 if ( !SetMenuItemInfo(GetHmenu(), id, TRUE, & info) )
1067 {
1068 wxLogLastError(wxT("SetMenuItemInfo"));
1069 }
1070
1071 #else
1072 if ( ::ModifyMenu(GetHmenu(), mswpos, MF_BYPOSITION | MF_STRING | flagsOld,
1073 id, label) == (int)0xFFFFFFFF )
1074 {
1075 wxLogLastError(wxT("ModifyMenu"));
1076 }
1077 #endif
1078
1079 Refresh();
1080 }
1081
1082 wxString wxMenuBar::GetLabelTop(size_t pos) const
1083 {
1084 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
1085 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
1086
1087 return wxMenuItem::GetLabelFromText(m_titles[pos]);
1088 }
1089
1090 // Gets the original label at the top-level of the menubar
1091 wxString wxMenuBar::GetMenuLabel(size_t pos) const
1092 {
1093 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
1094 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
1095
1096 return m_titles[pos];
1097 }
1098
1099 // ---------------------------------------------------------------------------
1100 // wxMenuBar construction
1101 // ---------------------------------------------------------------------------
1102
1103 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
1104 {
1105 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
1106 if ( !menuOld )
1107 return NULL;
1108
1109 m_titles[pos] = title;
1110
1111 #if defined(WINCE_WITHOUT_COMMANDBAR)
1112 if (IsAttached())
1113 #else
1114 if (GetHmenu())
1115 #endif
1116 {
1117 int mswpos = MSWPositionForWxMenu(menuOld,pos);
1118
1119 // can't use ModifyMenu() because it deletes the submenu it replaces
1120 if ( !::RemoveMenu(GetHmenu(), (UINT)mswpos, MF_BYPOSITION) )
1121 {
1122 wxLogLastError(wxT("RemoveMenu"));
1123 }
1124
1125 if ( !::InsertMenu(GetHmenu(), (UINT)mswpos,
1126 MF_BYPOSITION | MF_POPUP | MF_STRING,
1127 (UINT)GetHmenuOf(menu), title) )
1128 {
1129 wxLogLastError(wxT("InsertMenu"));
1130 }
1131
1132 #if wxUSE_ACCEL
1133 if ( menuOld->HasAccels() || menu->HasAccels() )
1134 {
1135 // need to rebuild accell table
1136 RebuildAccelTable();
1137 }
1138 #endif // wxUSE_ACCEL
1139
1140 if (IsAttached())
1141 Refresh();
1142 }
1143
1144 return menuOld;
1145 }
1146
1147 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
1148 {
1149 // Find out which MSW item before which we'll be inserting before
1150 // wxMenuBarBase::Insert is called and GetMenu(pos) is the new menu.
1151 // If IsAttached() is false this won't be used anyway
1152 bool isAttached =
1153 #if defined(WINCE_WITHOUT_COMMANDBAR)
1154 IsAttached();
1155 #else
1156 (GetHmenu() != 0);
1157 #endif
1158
1159 int mswpos = (!isAttached || (pos == m_menus.GetCount()))
1160 ? -1 // append the menu
1161 : MSWPositionForWxMenu(GetMenu(pos),pos);
1162
1163 if ( !wxMenuBarBase::Insert(pos, menu, title) )
1164 return false;
1165
1166 m_titles.Insert(title, pos);
1167
1168 if ( isAttached )
1169 {
1170 #if defined(WINCE_WITHOUT_COMMANDBAR)
1171 if (!GetToolBar())
1172 return false;
1173 TBBUTTON tbButton;
1174 memset(&tbButton, 0, sizeof(TBBUTTON));
1175 tbButton.iBitmap = I_IMAGENONE;
1176 tbButton.fsState = TBSTATE_ENABLED;
1177 tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;
1178
1179 HMENU hPopupMenu = (HMENU) menu->GetHMenu() ;
1180 tbButton.dwData = (DWORD)hPopupMenu;
1181 wxString label = wxStripMenuCodes(title);
1182 tbButton.iString = (int) label.c_str();
1183
1184 tbButton.idCommand = NewControlId();
1185 if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton))
1186 {
1187 wxLogLastError(wxT("TB_INSERTBUTTON"));
1188 return false;
1189 }
1190 wxUnusedVar(mswpos);
1191 #else
1192 if ( !::InsertMenu(GetHmenu(), mswpos,
1193 MF_BYPOSITION | MF_POPUP | MF_STRING,
1194 (UINT)GetHmenuOf(menu), title) )
1195 {
1196 wxLogLastError(wxT("InsertMenu"));
1197 }
1198 #endif
1199 #if wxUSE_ACCEL
1200 if ( menu->HasAccels() )
1201 {
1202 // need to rebuild accell table
1203 RebuildAccelTable();
1204 }
1205 #endif // wxUSE_ACCEL
1206
1207 if (IsAttached())
1208 Refresh();
1209 }
1210
1211 return true;
1212 }
1213
1214 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
1215 {
1216 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
1217 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
1218
1219 if ( !wxMenuBarBase::Append(menu, title) )
1220 return false;
1221
1222 m_titles.Add(title);
1223
1224 #if defined(WINCE_WITHOUT_COMMANDBAR)
1225 if (IsAttached())
1226 #else
1227 if (GetHmenu())
1228 #endif
1229 {
1230 #if defined(WINCE_WITHOUT_COMMANDBAR)
1231 if (!GetToolBar())
1232 return false;
1233 TBBUTTON tbButton;
1234 memset(&tbButton, 0, sizeof(TBBUTTON));
1235 tbButton.iBitmap = I_IMAGENONE;
1236 tbButton.fsState = TBSTATE_ENABLED;
1237 tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;
1238
1239 size_t pos = GetMenuCount();
1240 HMENU hPopupMenu = (HMENU) menu->GetHMenu() ;
1241 tbButton.dwData = (DWORD)hPopupMenu;
1242 wxString label = wxStripMenuCodes(title);
1243 tbButton.iString = (int) label.c_str();
1244
1245 tbButton.idCommand = NewControlId();
1246 if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton))
1247 {
1248 wxLogLastError(wxT("TB_INSERTBUTTON"));
1249 return false;
1250 }
1251 #else
1252 if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
1253 (UINT)submenu, title) )
1254 {
1255 wxLogLastError(wxT("AppendMenu"));
1256 }
1257 #endif
1258
1259 #if wxUSE_ACCEL
1260 if ( menu->HasAccels() )
1261 {
1262 // need to rebuild accelerator table
1263 RebuildAccelTable();
1264 }
1265 #endif // wxUSE_ACCEL
1266
1267 if (IsAttached())
1268 Refresh();
1269 }
1270
1271 return true;
1272 }
1273
1274 wxMenu *wxMenuBar::Remove(size_t pos)
1275 {
1276 wxMenu *menu = wxMenuBarBase::Remove(pos);
1277 if ( !menu )
1278 return NULL;
1279
1280 #if defined(WINCE_WITHOUT_COMMANDBAR)
1281 if (IsAttached())
1282 #else
1283 if (GetHmenu())
1284 #endif
1285 {
1286 #if defined(WINCE_WITHOUT_COMMANDBAR)
1287 if (GetToolBar())
1288 {
1289 if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_DELETEBUTTON, (UINT) pos, (LPARAM) 0))
1290 {
1291 wxLogLastError(wxT("TB_DELETEBUTTON"));
1292 }
1293 }
1294 #else
1295 if ( !::RemoveMenu(GetHmenu(), (UINT)MSWPositionForWxMenu(menu,pos), MF_BYPOSITION) )
1296 {
1297 wxLogLastError(wxT("RemoveMenu"));
1298 }
1299 #endif
1300
1301 #if wxUSE_ACCEL
1302 if ( menu->HasAccels() )
1303 {
1304 // need to rebuild accell table
1305 RebuildAccelTable();
1306 }
1307 #endif // wxUSE_ACCEL
1308
1309 if (IsAttached())
1310 Refresh();
1311 }
1312
1313 m_titles.RemoveAt(pos);
1314
1315 return menu;
1316 }
1317
1318 #if wxUSE_ACCEL
1319
1320 void wxMenuBar::RebuildAccelTable()
1321 {
1322 // merge the accelerators of all menus into one accel table
1323 size_t nAccelCount = 0;
1324 size_t i, count = GetMenuCount();
1325 wxMenuList::iterator it;
1326 for ( i = 0, it = m_menus.begin(); i < count; i++, it++ )
1327 {
1328 nAccelCount += (*it)->GetAccelCount();
1329 }
1330
1331 if ( nAccelCount )
1332 {
1333 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
1334
1335 nAccelCount = 0;
1336 for ( i = 0, it = m_menus.begin(); i < count; i++, it++ )
1337 {
1338 nAccelCount += (*it)->CopyAccels(&accelEntries[nAccelCount]);
1339 }
1340
1341 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
1342
1343 delete [] accelEntries;
1344 }
1345 }
1346
1347 #endif // wxUSE_ACCEL
1348
1349 void wxMenuBar::Attach(wxFrame *frame)
1350 {
1351 wxMenuBarBase::Attach(frame);
1352
1353 #if defined(WINCE_WITH_COMMANDBAR)
1354 if (!m_hMenu)
1355 this->Create();
1356 if (!m_commandBar)
1357 m_commandBar = (WXHWND) CommandBar_Create(wxGetInstance(), (HWND) frame->GetHWND(), NewControlId());
1358 if (m_commandBar)
1359 {
1360 if (m_hMenu)
1361 {
1362 if (!CommandBar_InsertMenubarEx((HWND) m_commandBar, NULL, (LPTSTR) m_hMenu, 0))
1363 {
1364 wxLogLastError(wxT("CommandBar_InsertMenubarEx"));
1365 }
1366 }
1367 }
1368 #endif
1369
1370 #if wxUSE_ACCEL
1371 RebuildAccelTable();
1372 #endif // wxUSE_ACCEL
1373 }
1374
1375 #if defined(WINCE_WITH_COMMANDBAR)
1376 bool wxMenuBar::AddAdornments(long style)
1377 {
1378 if (m_adornmentsAdded || !m_commandBar)
1379 return false;
1380
1381 if (style & wxCLOSE_BOX)
1382 {
1383 if (!CommandBar_AddAdornments((HWND) m_commandBar, 0, 0))
1384 wxLogLastError(wxT("CommandBar_AddAdornments"));
1385 else
1386 return true;
1387 }
1388 return false;
1389 }
1390 #endif
1391
1392 void wxMenuBar::Detach()
1393 {
1394 wxMenuBarBase::Detach();
1395 }
1396
1397 #endif // wxUSE_MENUS

  ViewVC Help
Powered by ViewVC 1.1.22