1///////////////////////////////////////////////////////////////////////////// 2// Name: src/palmos/menu.cpp 3// Purpose: wxMenu, wxMenuBar, wxMenuItem 4// Author: William Osborne - minimal working wxPalmOS port 5// Modified by: 6// Created: 10/12/04 7// RCS-ID: $Id: menu.cpp 48053 2007-08-13 17:07:01Z JS $ 8// Copyright: (c) William Osborne 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/frame.h" 33 #include "wx/utils.h" 34 #include "wx/intl.h" 35 #include "wx/log.h" 36#endif 37 38#if wxUSE_OWNER_DRAWN 39 #include "wx/ownerdrw.h" 40#endif 41 42#include <Loader.h> 43#include <Form.h> 44#include <Menu.h> 45 46// ---------------------------------------------------------------------------- 47// global variables 48// ---------------------------------------------------------------------------- 49 50extern wxMenu *wxCurrentPopupMenu; 51 52// ---------------------------------------------------------------------------- 53// constants 54// ---------------------------------------------------------------------------- 55 56// the (popup) menu title has this special id 57static const int idMenuTitle = -3; 58 59// ---------------------------------------------------------------------------- 60// private functions 61// ---------------------------------------------------------------------------- 62 63// ============================================================================ 64// implementation 65// ============================================================================ 66 67#include "wx/listimpl.cpp" 68 69WX_DEFINE_LIST( wxMenuInfoList ) 70 71#if wxUSE_EXTENDED_RTTI 72 73WX_DEFINE_FLAGS( wxMenuStyle ) 74 75wxBEGIN_FLAGS( wxMenuStyle ) 76 wxFLAGS_MEMBER(wxMENU_TEAROFF) 77wxEND_FLAGS( wxMenuStyle ) 78 79IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler,"wx/menu.h") 80 81wxCOLLECTION_TYPE_INFO( wxMenuItem * , wxMenuItemList ) ; 82 83template<> void wxCollectionToVariantArray( wxMenuItemList const &theList, wxxVariantArray &value) 84{ 85 wxListCollectionToVariantArray<wxMenuItemList::compatibility_iterator>( theList , value ) ; 86} 87 88wxBEGIN_PROPERTIES_TABLE(wxMenu) 89 wxEVENT_PROPERTY( Select , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent) 90 wxPROPERTY( Title, wxString , SetTitle, GetTitle, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 91 wxREADONLY_PROPERTY_FLAGS( MenuStyle , wxMenuStyle , long , GetStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 92 wxPROPERTY_COLLECTION( MenuItems , wxMenuItemList , wxMenuItem* , Append , GetMenuItems , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 93wxEND_PROPERTIES_TABLE() 94 95wxBEGIN_HANDLERS_TABLE(wxMenu) 96wxEND_HANDLERS_TABLE() 97 98wxDIRECT_CONSTRUCTOR_2( wxMenu , wxString , Title , long , MenuStyle ) 99 100WX_DEFINE_FLAGS( wxMenuBarStyle ) 101 102wxBEGIN_FLAGS( wxMenuBarStyle ) 103 wxFLAGS_MEMBER(wxMB_DOCKABLE) 104wxEND_FLAGS( wxMenuBarStyle ) 105 106// the negative id would lead the window (its superclass !) to vetoe streaming out otherwise 107bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxWriter * , wxPersister * , wxxVariantArray & ) 108{ 109 return true ; 110} 111 112IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow ,"wx/menu.h",wxMenuBarStreamingCallback) 113 114IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfo, wxObject , "wx/menu.h" ) 115 116wxBEGIN_PROPERTIES_TABLE(wxMenuInfo) 117 wxREADONLY_PROPERTY( Menu , wxMenu* , GetMenu , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 118 wxREADONLY_PROPERTY( Title , wxString , GetTitle , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 119wxEND_PROPERTIES_TABLE() 120 121wxBEGIN_HANDLERS_TABLE(wxMenuInfo) 122wxEND_HANDLERS_TABLE() 123 124wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title ) 125 126wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ; 127 128template<> void wxCollectionToVariantArray( wxMenuInfoList const &theList, wxxVariantArray &value) 129{ 130 wxListCollectionToVariantArray<wxMenuInfoList::compatibility_iterator>( theList , value ) ; 131} 132 133wxBEGIN_PROPERTIES_TABLE(wxMenuBar) 134 wxPROPERTY_COLLECTION( MenuInfos , wxMenuInfoList , wxMenuInfo* , Append , GetMenuInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 135wxEND_PROPERTIES_TABLE() 136 137wxBEGIN_HANDLERS_TABLE(wxMenuBar) 138wxEND_HANDLERS_TABLE() 139 140wxCONSTRUCTOR_DUMMY( wxMenuBar ) 141 142#else 143IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) 144IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow) 145IMPLEMENT_DYNAMIC_CLASS(wxMenuInfo, wxObject) 146#endif 147 148const wxMenuInfoList& wxMenuBar::GetMenuInfos() const 149{ 150 wxMenuInfoList* list = const_cast< wxMenuInfoList* >( &m_menuInfos ) ; 151 WX_CLEAR_LIST( wxMenuInfoList , *list ) ; 152 for( size_t i = 0 ; i < GetMenuCount() ; ++i ) 153 { 154 wxMenuInfo* info = new wxMenuInfo() ; 155 info->Create( const_cast<wxMenuBar*>(this)->GetMenu(i) , GetLabelTop(i) ) ; 156 list->Append( info ) ; 157 } 158 return m_menuInfos ; 159} 160 161// --------------------------------------------------------------------------- 162// wxMenu construction, adding and removing menu items 163// --------------------------------------------------------------------------- 164 165// Construct a menu with optional title (then use append) 166void wxMenu::Init() 167{ 168} 169 170// The wxWindow destructor will take care of deleting the submenus. 171wxMenu::~wxMenu() 172{ 173} 174 175void wxMenu::Break() 176{ 177} 178 179void wxMenu::Attach(wxMenuBarBase *menubar) 180{ 181 wxMenuBase::Attach(menubar); 182} 183 184#if wxUSE_ACCEL 185 186int wxMenu::FindAccel(int id) const 187{ 188 return wxNOT_FOUND; 189} 190 191void wxMenu::UpdateAccel(wxMenuItem *item) 192{ 193} 194 195#endif // wxUSE_ACCEL 196 197// append a new item or submenu to the menu 198bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) 199{ 200 if ( IsAttached() && GetMenuBar()->IsAttached() ) 201 { 202 // Regenerate the menu resource 203 GetMenuBar()->Refresh(); 204 } 205 206 return true; 207} 208 209void wxMenu::EndRadioGroup() 210{ 211} 212 213wxMenuItem* wxMenu::DoAppend(wxMenuItem *item) 214{ 215 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") ); 216 217 if(!wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item)) 218 { 219 return NULL; 220 } 221 else if(IsAttached() && GetMenuBar()->IsAttached()) 222 { 223 // Regenerate the menu resource 224 GetMenuBar()->Refresh(); 225 } 226 227 return item; 228} 229 230wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item) 231{ 232 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos)) 233 return item; 234 else 235 return NULL; 236} 237 238wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) 239{ 240 // we need to find the items position in the child list 241 size_t pos; 242 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst(); 243 for ( pos = 0; node; pos++ ) 244 { 245 if ( node->GetData() == item ) 246 break; 247 248 node = node->GetNext(); 249 } 250 251 // DoRemove() (unlike Remove) can only be called for existing item! 252 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") ); 253 254 // remove the item from the menu 255 wxMenuItem *ret=wxMenuBase::DoRemove(item); 256 257 if ( IsAttached() && GetMenuBar()->IsAttached() ) 258 { 259 // Regenerate the menu resource 260 GetMenuBar()->Refresh(); 261 } 262 263 return ret; 264} 265 266// --------------------------------------------------------------------------- 267// accelerator helpers 268// --------------------------------------------------------------------------- 269 270#if wxUSE_ACCEL 271 272// create the wxAcceleratorEntries for our accels and put them into provided 273// array - return the number of accels we have 274size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const 275{ 276 size_t count = GetAccelCount(); 277 for ( size_t n = 0; n < count; n++ ) 278 { 279 *accels++ = *m_accels[n]; 280 } 281 282 return count; 283} 284 285#endif // wxUSE_ACCEL 286 287// --------------------------------------------------------------------------- 288// set wxMenu title 289// --------------------------------------------------------------------------- 290 291void wxMenu::SetTitle(const wxString& label) 292{ 293 m_title = label; 294 295 if ( IsAttached() && GetMenuBar()->IsAttached() ) 296 { 297 // Regenerate the menu resource 298 GetMenuBar()->Refresh(); 299 } 300} 301 302// --------------------------------------------------------------------------- 303// event processing 304// --------------------------------------------------------------------------- 305 306bool wxMenu::PalmCommand(WXUINT WXUNUSED(param), WXWORD id) 307{ 308 return false; 309} 310 311// --------------------------------------------------------------------------- 312// other 313// --------------------------------------------------------------------------- 314 315wxWindow *wxMenu::GetWindow() const 316{ 317 return NULL; 318} 319 320// --------------------------------------------------------------------------- 321// Menu Bar 322// --------------------------------------------------------------------------- 323 324void wxMenuBar::Init() 325{ 326} 327 328wxMenuBar::wxMenuBar() 329{ 330} 331 332wxMenuBar::wxMenuBar( long WXUNUSED(style) ) 333{ 334} 335 336wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style)) 337{ 338} 339 340wxMenuBar::~wxMenuBar() 341{ 342} 343 344// --------------------------------------------------------------------------- 345// wxMenuBar helpers 346// --------------------------------------------------------------------------- 347 348void wxMenuBar::Refresh() 349{ 350 wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") ); 351 352 // Regenerate the menu resource 353 LoadMenu(); 354} 355 356WXHMENU wxMenuBar::Create() 357{ 358 return NULL; 359} 360 361int wxMenuBar::PalmPositionForWxMenu(wxMenu *menu, int wxpos) 362{ 363 return -1; 364} 365 366// --------------------------------------------------------------------------- 367// wxMenuBar functions to work with the top level submenus 368// --------------------------------------------------------------------------- 369 370void wxMenuBar::EnableTop(size_t pos, bool enable) 371{ 372 // Palm OS does not have support for grayed or disabled items 373} 374 375void wxMenuBar::SetLabelTop(size_t pos, const wxString& label) 376{ 377 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") ); 378 379 m_titles[pos]=wxStripMenuCodes(label); 380 381 if ( !IsAttached() ) 382 { 383 return; 384 } 385 386 // Regenerate the menu resource 387 Refresh(); 388} 389 390wxString wxMenuBar::GetLabelTop(size_t pos) const 391{ 392 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString, 393 wxT("invalid menu index in wxMenuBar::GetLabelTop") ); 394 395 return wxMenuItem::GetLabelFromText(m_titles[pos]); 396} 397 398// Gets the original label at the top-level of the menubar 399wxString wxMenuBar::GetMenuLabel(size_t pos) const 400{ 401 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString, 402 wxT("invalid menu index in wxMenuBar::GetMenuLabel") ); 403 404 return m_titles[pos]; 405} 406 407// --------------------------------------------------------------------------- 408// wxMenuBar construction 409// --------------------------------------------------------------------------- 410 411wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) 412{ 413 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title); 414 if ( !menuOld ) 415 return NULL; 416 417 m_titles[pos]=wxStripMenuCodes(title); 418 419 if ( IsAttached() ) 420 { 421 // Regenerate the menu resource 422 Refresh(); 423 } 424 425 return menuOld; 426} 427 428bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) 429{ 430 if ( !wxMenuBarBase::Insert(pos, menu, title) ) 431 return false; 432 433 m_titles.Insert(wxStripMenuCodes(title), pos); 434 435 if ( IsAttached() ) 436 { 437 // Regenerate the menu resource 438 Refresh(); 439 } 440 441 return true; 442} 443 444bool wxMenuBar::Append(wxMenu *menu, const wxString& title) 445{ 446 if ( !wxMenuBarBase::Append(menu, title) ) 447 return false; 448 449 m_titles.Add(wxStripMenuCodes(title)); 450 451 if(IsAttached()) 452 { 453 // Regenerate the menu resource 454 Refresh(); 455 } 456 457 return true; 458} 459 460wxMenu *wxMenuBar::Remove(size_t pos) 461{ 462 wxMenu *menu = wxMenuBarBase::Remove(pos); 463 if ( !menu ) 464 return NULL; 465 466 m_titles.RemoveAt(pos); 467 468 if (IsAttached()) 469 { 470 // Regenerate the menu resource 471 Refresh(); 472 } 473 474 return menu; 475} 476 477#if wxUSE_ACCEL 478 479void wxMenuBar::RebuildAccelTable() 480{ 481} 482 483#endif // wxUSE_ACCEL 484 485int wxMenuBar::ProcessCommand(int ItemID) 486{ 487 if(!IsAttached()) 488 return -1; 489 490 int MenuNum=(ItemID/1000)-1; 491 int ItemNum=(ItemID-(1000*(MenuNum+1))); 492 493 // Should never happen, but it doesn't hurt to check anyway. 494 if(MenuNum>GetMenuCount()) 495 return -1; 496 497 // Get the menu 498 wxMenu *ActiveMenu=GetMenu(MenuNum); 499 500 // Make sure this is a valid item. 501 if(ItemNum>ActiveMenu->GetMenuItemCount()) 502 return -1; 503 504 // Get the item 505 wxMenuItem *ActiveItem=ActiveMenu->FindItemByPosition(ItemNum); 506 int ActiveID=ActiveItem->GetId(); 507 508 return ActiveID; 509} 510 511/* Palm OS does not have good dynamic menu support. About all you can do with 512 * the standard API calls is to add new items to an existing drop-down menu and 513 * hide/show items in a drop-down menu. It is impossible to add, hide, or 514 * change the label on a drop-down menu. 515 * 516 * The easiest and simplest way around this limitation is to modify the Palm OS 517 * MenuBarType structure directly. This gives limited ability to change the 518 * label on a drop-down menu. I have not been able to find a safe way to add, 519 * delete, or resize drop-down menus in OS 6. 520 * 521 * The following routine attempt to work around these limitations present in the 522 * Palm OS API to provide limited dynamic menu support. This solution is far 523 * from perfect, but the only other option is to wait for PalmSource to add full 524 * dynamic menu support, or to recreate the Palm OS menu system from scratch. 525 * 526 * This system is limited in that no more than 4 drop-down menus are allowed per 527 * menu bar, and the label for each drop-down menu is limited to 8 characters of 528 * text. However, this menu system should work for most applications. 529 * 530 * Basically the menu routines select one of four menu bars, depending on 531 * whether or not the requested menu bar has one, two, three, or four drop-down 532 * menus. 533 * 534 * These four "template" menu bars contain one, two, three, or four drop-down 535 * menus. Each menu has a dummy menu item attached to it to allow the Palm OS 536 * MenuAddItem function to add the real items. 537 * 538 * The labels on the drop-down menus are then replaced with the labels of the 539 * real menus. 540 * 541 * The menu is then attached to the active window and the MenuAddItem API 542 * function is called to add the items to each drop-down menu. Finally, 543 * MenuHideItem is called to remove the dummy items from each drop-down menu. 544 */ 545void wxMenuBar::LoadMenu() 546{ 547 int i=0; 548 int j=0; 549 550 // Handle to the currently running application database 551 DmOpenRef AppDB; 552 553 // Get app database reference - needed for some Palm OS Menu API calls. 554 SysGetModuleDatabase(SysGetRefNum(), NULL, &AppDB); 555 556 // Get the number of menus 557 int NumMenus=GetMenuCount(); 558 559 // Set up the pointers and handles 560 char *PalmOSMenuBarPtr; 561 MemHandle PalmOSMenuBar; 562 563 // Load the menu template and set up the menu pointers 564 if(NumMenus==1) 565 { 566 PalmOSMenuBar=DmGetResource(AppDB,'MBAR',1000); 567 PalmOSMenuBarPtr=(char *)MemHandleLock(PalmOSMenuBar); 568 569 PalmOSMenuBarPtr+=74; 570 } 571 else if(NumMenus==2) 572 { 573 PalmOSMenuBar=DmGetResource(AppDB,'MBAR',2000); 574 PalmOSMenuBarPtr=(char *)MemHandleLock(PalmOSMenuBar); 575 576 PalmOSMenuBarPtr+=116; 577 } 578 else if(NumMenus==3) 579 { 580 PalmOSMenuBar=DmGetResource(AppDB,'MBAR',3000); 581 PalmOSMenuBarPtr=(char *)MemHandleLock(PalmOSMenuBar); 582 583 PalmOSMenuBarPtr+=158; 584 } 585 else 586 { 587 // We support a maximum of 4 menus, so make sure that do not create 588 // more than we can handle. 589 NumMenus=4; 590 591 PalmOSMenuBar=DmGetResource(AppDB,'MBAR',4000); 592 PalmOSMenuBarPtr=(char *)MemHandleLock(PalmOSMenuBar); 593 594 PalmOSMenuBarPtr+=200; 595 } 596 597 // Set the proper names for the drop-down triggers. 598 for(i=0;i<NumMenus;i++) 599 { 600 // Clear out the old label 601 char buffer[8]={' ',' ',' ',' ',' ',' ',' ',' '}; 602 MemMove(PalmOSMenuBarPtr,buffer,8); 603 604 wxString MenuTitle=m_titles.Item(i); 605 606 // Make sure we don't copy more than 8 bytes for the label 607 int LengthToCopy=MenuTitle.length(); 608 if(LengthToCopy>8) 609 LengthToCopy=8; 610 611 MemMove(PalmOSMenuBarPtr,MenuTitle,LengthToCopy); 612 PalmOSMenuBarPtr+=11; 613 } 614 615 // We are done with the menu pointer. 616 MemHandleUnlock(PalmOSMenuBar); 617 DmReleaseResource(PalmOSMenuBar); 618 619 // We must make the menu active before we can add items to the drop-down 620 // triggers. 621 FrmSetMenu(FrmGetActiveForm(),AppDB,NumMenus*1000); 622 623 /* Add the menu items to the drop-down triggers. This must be done after 624 * setting the triggers, because setting the names of drop-down triggers 625 * that have a variable number of items requires carefull calculation of 626 * the offsets in the MenuBarType structure. Setting the triggers first 627 * avoids this. 628 */ 629 for(i=0;i<NumMenus;i++) 630 { 631 wxMenu *CurrentMenu=GetMenu(i); 632 633 for(j=0;j<CurrentMenu->GetMenuItemCount();j++) 634 { 635 wxMenuItem *CurrentItem=CurrentMenu->FindItemByPosition(j); 636 wxString ItemLabel=CurrentItem->GetLabel(); 637 638 if(CurrentItem->IsSeparator()==true) 639 { 640 char Separator=MenuSeparatorChar; 641 if(j==0) 642 MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,&Separator); 643 else 644 MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,&Separator); 645 } 646 else 647 { 648 if(j==0) 649 MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,ItemLabel); 650 else 651 MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,ItemLabel); 652 } 653 } 654 655 // Hide the dummy menu item, since we don't need it anymore. 656 MenuHideItem(9000+i); 657 } 658} 659 660void wxMenuBar::Attach(wxFrame *frame) 661{ 662 // before attaching preprocess menus to not include wxID_EXIT item 663 // as PalmOS guidelines suggest 664 665 wxMenuItem *item; 666 wxMenu *menu; 667 int i; 668 669 while( item = FindItem(wxID_EXIT) ) 670 { 671 menu = item->GetMenu(); 672 if( !menu ) break; // something broken ? 673 674 size_t count = menu->GetMenuItemCount(); 675 if( count == 0 ) break; // something broken ? 676 677 // if EXIT is last item in menu 678 if( menu->FindItemByPosition( count - 1 ) == item ) 679 { 680 menu->Destroy( item ); 681 682 // was more than one item? 683 // was previous separator ? 684 if( count > 2 ) 685 { 686 item = menu->FindItemByPosition( count - 2 ); 687 if(item && item->IsSeparator()) 688 menu->Destroy( item ); 689 } 690 } 691 692 // if EXIT is first item in menu 693 else if( menu->FindItemByPosition( 0 ) == item ) 694 { 695 menu->Destroy( item ); 696 697 // was more than one item? 698 // was previous separator ? 699 if( count > 2 ) 700 { 701 item = menu->FindItemByPosition( 0 ); 702 if(item && item->IsSeparator()) 703 menu->Destroy( item ); 704 } 705 } 706 707 // if EXIT is in the middle but before and after are selectors 708 else 709 { 710 i = 1; // 0 case already done 711 while ( (i < count) && (menu->FindItemByPosition( 0 ) != item) ) 712 { 713 i++; 714 } 715 716 if (i >= count) break; 717 if (menu->FindItemByPosition( i ) != item) break; 718 menu->Destroy( item ); 719 item = menu->FindItemByPosition( i ); 720 if ( item && 721 item->IsSeparator() && 722 menu->FindItemByPosition( i-1 )->IsSeparator() ) 723 { 724 // noe need for two neighbouring separators 725 menu->Destroy( item ); 726 } 727 } 728 } 729 730 // check if we received any empty menu! 731 i = 0; 732 while(i < GetMenuCount()) 733 { 734 menu = GetMenu(i); 735 736 if( menu && (menu->GetMenuItemCount()==0) ) 737 { 738 menu = Remove( i ); 739 delete menu; 740 } 741 else 742 i++; 743 } 744 745 wxMenuBarBase::Attach(frame); 746 747 LoadMenu(); 748} 749 750void wxMenuBar::Detach() 751{ 752 wxMenuBarBase::Detach(); 753} 754 755#endif // wxUSE_MENUS 756