📄 menu.cpp
字号:
Secondly there is no mac api for changing a menubar that is not the currentmenubar, so we have to wait for preparing the actual menubar until thewxMenubar is to be usedWe can in subsequent versions use MacInstallMenuBar to provide some sort ofauto-merge for MDI in case this will be necessary*/wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;bool wxMenuBar::s_macAutoWindowMenu = true ;WXHMENU wxMenuBar::s_macWindowMenuHandle = NULL ;void wxMenuBar::Init(){ m_eventHandler = this; m_menuBarFrame = NULL; m_invokingWindow = (wxWindow*) NULL;}wxMenuBar::wxMenuBar(){ Init();}wxMenuBar::wxMenuBar( long WXUNUSED(style) ){ Init();}wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style)){ Init(); m_titles.Alloc(count); for ( size_t i = 0; i < count; i++ ) { m_menus.Append(menus[i]); m_titles.Add(titles[i]); menus[i]->Attach(this); }}wxMenuBar::~wxMenuBar(){ if (s_macCommonMenuBar == this) s_macCommonMenuBar = NULL; if (s_macInstalledMenuBar == this) { ::ClearMenuBar(); s_macInstalledMenuBar = NULL; }}void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect)){ wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") ); DrawMenuBar();}void wxMenuBar::MacInstallMenuBar(){ if ( s_macInstalledMenuBar == this ) return ; MenuBarHandle menubar = NULL ;#if TARGET_API_MAC_OSX menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;#else menubar = NewHandleClear( 12 ) ; (*menubar)[3] = 0x0a ;#endif ::SetMenuBar( menubar ) ; DisposeMenuBar( menubar ) ; MenuHandle appleMenu = NULL ; verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ; verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) ); // Add About/Preferences separator only on OS X // KH/RN: Separator is always present on 10.3 but not on 10.2 // However, the change from 10.2 to 10.3 suggests it is preferred#if TARGET_API_MAC_OSX InsertMenuItemTextWithCFString( appleMenu, CFSTR(""), 0, kMenuItemAttrSeparator, 0); #endif InsertMenuItemTextWithCFString( appleMenu, CFSTR("About..."), 0, 0, 0); MacInsertMenu( appleMenu , 0 ) ; // clean-up the help menu before adding new items static MenuHandle mh = NULL ; if ( mh != NULL ) { MenuItemIndex firstUserHelpMenuItem ; if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr ) { for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i ) DeleteMenuItem( mh , i ) ; } else { mh = NULL ; } }#if TARGET_CARBON if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId) { wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ; if ( item == NULL || !(item->IsEnabled()) ) DisableMenuCommand( NULL , kHICommandPreferences ) ; else EnableMenuCommand( NULL , kHICommandPreferences ) ; } // Unlike preferences which may or may not exist, the Quit item should be always // enabled unless it is added by the application and then disabled, otherwise // a program would be required to add an item with wxID_EXIT in order to get the // Quit menu item to be enabled, which seems a bit burdensome. if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId) { wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ; if ( item != NULL && !(item->IsEnabled()) ) DisableMenuCommand( NULL , kHICommandQuit ) ; else EnableMenuCommand( NULL , kHICommandQuit ) ; }#endif wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst(); for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext()) { wxMenuItemList::compatibility_iterator node; wxMenuItem *item; wxMenu* menu = menuIter->GetData() , *subMenu = NULL ; if ( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName ) { for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext()) { item = (wxMenuItem *)node->GetData(); subMenu = item->GetSubMenu() ; if (subMenu) { // we don't support hierarchical menus in the help menu yet } else { if ( item->GetId() != wxApp::s_macAboutMenuItemId ) { if ( mh == NULL ) { MenuItemIndex firstUserHelpMenuItem ; if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) != noErr ) { mh = NULL ; break ; } } } if ( item->IsSeparator() ) { if ( mh ) AppendMenuItemTextWithCFString( mh, CFSTR(""), kMenuItemAttrSeparator, 0,NULL); } else { wxAcceleratorEntry* entry = wxAcceleratorEntry::Create( item->GetText() ) ; if ( item->GetId() == wxApp::s_macAboutMenuItemId ) { // this will be taken care of below } else { if ( mh ) { UMAAppendMenuItem(mh, wxStripMenuCodes(item->GetText()) , wxFont::GetDefaultEncoding(), entry); SetMenuItemCommandID( mh , CountMenuItems(mh) , wxIdToMacCommand ( item->GetId() ) ) ; SetMenuItemRefCon( mh , CountMenuItems(mh) , (URefCon) item ) ; } } delete entry ; } } } } else { UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ; menu->MacBeforeDisplay(false) ; ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus, i)->GetHMenu()), 0); } } // take care of the about menu item wherever it is { wxMenu* aboutMenu ; wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ; if ( aboutMenuItem ) { wxAcceleratorEntry* entry = wxAcceleratorEntry::Create( aboutMenuItem->GetText() ) ; UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetText() ) , wxFont::GetDefaultEncoding() ); UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true ); SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ; SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ; UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ; } } if ( GetAutoWindowMenu() ) { if ( MacGetWindowMenuHMenu() == NULL ) CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ; InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ; } ::DrawMenuBar() ; s_macInstalledMenuBar = this;}void wxMenuBar::EnableTop(size_t pos, bool enable){ wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") ); _wxMenuAt(m_menus, pos)->MacEnableMenu( enable ) ; Refresh();}bool wxMenuBar::Enable(bool enable){ wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") ); size_t i; for (i = 0; i < GetMenuCount(); i++) EnableTop(i, enable); return true;}void wxMenuBar::SetLabelTop(size_t pos, const wxString& label){ wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") ); m_titles[pos] = label; if ( !IsAttached() ) return; _wxMenuAt(m_menus, pos)->SetTitle( label ) ; if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ? { ::SetMenuBar( GetMenuBar() ) ; ::InvalMenuBar() ; }}wxString wxMenuBar::GetLabelTop(size_t pos) const{ wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString, wxT("invalid menu index in wxMenuBar::GetLabelTop") ); return m_titles[pos];}int wxMenuBar::FindMenu(const wxString& title){ wxString menuTitle = wxStripMenuCodes(title); size_t count = GetMenuCount(); for ( size_t i = 0; i < count; i++ ) { wxString title = wxStripMenuCodes(m_titles[i]); if ( menuTitle == title ) return i; } return wxNOT_FOUND;}// ---------------------------------------------------------------------------// wxMenuBar construction// ---------------------------------------------------------------------------wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title){ wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title); if ( !menuOld ) return NULL; m_titles[pos] = title; if ( IsAttached() ) { if (s_macInstalledMenuBar == this) { menuOld->MacAfterDisplay( false ) ; ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; menu->MacBeforeDisplay( false ) ; UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ; if ( pos == m_menus.GetCount() - 1) ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ; else ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos + 1)->MacGetMenuId() ) ; } Refresh(); } if (m_invokingWindow) wxMenubarSetInvokingWindow( menu, m_invokingWindow ); return menuOld;}bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title){ if ( !wxMenuBarBase::Insert(pos, menu, title) ) return false; m_titles.Insert(title, pos); UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ; if ( IsAttached() && s_macInstalledMenuBar == this ) { if (s_macInstalledMenuBar == this) { menu->MacBeforeDisplay( false ) ; if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() ) ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ; else ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos+1)->MacGetMenuId() ) ; } Refresh(); } if (m_invokingWindow) wxMenubarSetInvokingWindow( menu, m_invokingWindow ); return true;}wxMenu *wxMenuBar::Remove(size_t pos){ wxMenu *menu = wxMenuBarBase::Remove(pos); if ( !menu ) return NULL; if ( IsAttached() ) { if (s_macInstalledMenuBar == this) ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; Refresh(); } m_titles.RemoveAt(pos); return menu;}bool wxMenuBar::Append(wxMenu *menu, const wxString& title){ WXHMENU submenu = menu ? menu->GetHMenu() : 0; wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") ); if ( !wxMenuBarBase::Append(menu, title) ) return false; m_titles.Add(title); UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ; if ( IsAttached() ) { if (s_macInstalledMenuBar == this) { menu->MacBeforeDisplay( false ) ; ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ; } Refresh(); } // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables // adding menu later on. if (m_invokingWindow) wxMenubarSetInvokingWindow( menu, m_invokingWindow ); return true;}static void wxMenubarUnsetInvokingWindow( wxMenu *menu ){ menu->SetInvokingWindow( (wxWindow*) NULL ); wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); while (node) { wxMenuItem *menuitem = node->GetData(); if (menuitem->IsSubMenu()) wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() ); node = node->GetNext(); }}static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win ){ menu->SetInvokingWindow( win ); wxMenuItem *menuitem; wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); while (node) { menuitem = node->GetData(); if (menuitem->IsSubMenu()) wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win ); node = node->GetNext(); }}void wxMenuBar::UnsetInvokingWindow(){ m_invokingWindow = (wxWindow*) NULL; wxMenu *menu; wxMenuList::compatibility_iterator node = m_menus.GetFirst(); while (node) { menu = node->GetData(); wxMenubarUnsetInvokingWindow( menu ); node = node->GetNext(); }}void wxMenuBar::SetInvokingWindow(wxFrame *frame){ m_invokingWindow = frame; wxMenu *menu; wxMenuList::compatibility_iterator node = m_menus.GetFirst(); while (node) { menu = node->GetData(); wxMenubarSetInvokingWindow( menu, frame ); node = node->GetNext(); }}void wxMenuBar::Detach(){ wxMenuBarBase::Detach() ;}void wxMenuBar::Attach(wxFrame *frame){ wxMenuBarBase::Attach( frame ) ;}// ---------------------------------------------------------------------------// wxMenuBar searching for menu items// ---------------------------------------------------------------------------// Find the itemString in menuString, and return the item id or wxNOT_FOUNDint wxMenuBar::FindMenuItem(const wxString& menuString, const wxString& itemString) const{ wxString menuLabel = wxStripMenuCodes(menuString); size_t count = GetMenuCount(); for ( size_t i = 0; i < count; i++ ) { wxString title = wxStripMenuCodes(m_titles[i]); if ( menuLabel == title ) return _wxMenuAt(m_menus, i)->FindItem(itemString); } return wxNOT_FOUND;}wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const{ if ( itemMenu ) *itemMenu = NULL; wxMenuItem *item = NULL; size_t count = GetMenuCount(); for ( size_t i = 0; !item && (i < count); i++ ) item = _wxMenuAt(m_menus, i)->FindItem(id, itemMenu); return item;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -