📄 menu.cpp
字号:
return m_invokingWindow;
else if ( GetMenuBar() != NULL)
return (wxWindow *) GetMenuBar()->GetFrame();
return NULL;
}
// helper functions returning the mac menu position for a certain item, note that this is
// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
int wxMenu::MacGetIndexFromId( int id )
{
size_t pos;
wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
for ( pos = 0; node; pos++ )
{
if ( node->GetData()->GetId() == id )
break;
node = node->GetNext();
}
if (!node)
return 0;
return pos + 1 ;
}
int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
{
size_t pos;
wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
for ( pos = 0; node; pos++ )
{
if ( node->GetData() == pItem )
break;
node = node->GetNext();
}
if (!node)
return 0;
return pos + 1 ;
}
void wxMenu::MacEnableMenu( bool bDoEnable )
{
UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
::DrawMenuBar() ;
}
// MacOS needs to know about submenus somewhere within this menu
// before it can be displayed, also hide special menu items
// like preferences that are handled by the OS
void wxMenu::MacBeforeDisplay( bool isSubMenu )
{
wxMenuItem* previousItem = NULL ;
size_t pos ;
wxMenuItemList::compatibility_iterator node;
wxMenuItem *item;
for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
{
item = (wxMenuItem *)node->GetData();
wxMenu* subMenu = item->GetSubMenu() ;
if (subMenu)
{
subMenu->MacBeforeDisplay( true ) ;
}
else // normal item
{
#if TARGET_CARBON
// what we do here is to hide the special items which are
// shown in the application menu anyhow -- it doesn't make
// sense to show them in their normal place as well
if ( item->GetId() == wxApp::s_macAboutMenuItemId ||
( UMAGetSystemVersion() >= 0x1000 && (
item->GetId() == wxApp::s_macPreferencesMenuItemId ||
item->GetId() == wxApp::s_macExitMenuItemId ) ) )
{
ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
pos + 1, kMenuItemAttrHidden, 0 );
// also check for a separator which was used just to
// separate this item from the others, so don't leave
// separator at the menu start or end nor 2 consecutive
// separators
wxMenuItemList::compatibility_iterator nextNode = node->GetNext();
wxMenuItem *next = nextNode ? nextNode->GetData() : NULL;
size_t posSeptoHide;
if ( !previousItem && next && next->IsSeparator() )
{
// next (i.e. second as we must be first) item is
// the separator to hide
wxASSERT_MSG( pos == 0, _T("should be the menu start") );
posSeptoHide = 2;
}
else if ( GetMenuItems().GetCount() == pos + 1 &&
previousItem != NULL &&
previousItem->IsSeparator() )
{
// prev item is a trailing separator we want to hide
posSeptoHide = pos;
}
else if ( previousItem && previousItem->IsSeparator() &&
next && next->IsSeparator() )
{
// two consecutive separators, this is one too many
posSeptoHide = pos;
}
else // no separators to hide
{
posSeptoHide = 0;
}
if ( posSeptoHide )
{
// hide the separator as well
ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
posSeptoHide,
kMenuItemAttrHidden,
0 );
}
}
#endif // TARGET_CARBON
}
previousItem = item ;
}
if ( isSubMenu )
::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
}
// undo all changes from the MacBeforeDisplay call
void wxMenu::MacAfterDisplay( bool isSubMenu )
{
if ( isSubMenu )
::DeleteMenu(MacGetMenuId());
wxMenuItem* previousItem = NULL ;
wxMenuItemList::compatibility_iterator node;
wxMenuItem *item;
int pos ;
for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
{
item = (wxMenuItem *)node->GetData();
wxMenu* subMenu = item->GetSubMenu() ;
if (subMenu)
{
subMenu->MacAfterDisplay( true ) ;
}
else
{
// no need to undo hidings
}
previousItem = item ;
}
}
// Menu Bar
/*
Mac Implementation note :
The Mac has only one global menubar, so we attempt to install the currently
active menubar from a frame, we currently don't take into account mdi-frames
which would ask for menu-merging
Secondly there is no mac api for changing a menubar that is not the current
menubar, so we have to wait for preparing the actual menubar until the
wxMenubar is to be used
We can in subsequent versions use MacInstallMenuBar to provide some sort of
auto-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 ;
char appleMenuTitle[3] = { 01 , kMenuAppleLogoFilledGlyph , 0 } ;
verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
verify_noerr( SetMenuTitle( appleMenu , (ConstStr255Param) appleMenuTitle ) );
// 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
MacInsertMenuItem( appleMenu , "\p-" , 0 ) ;
#endif
MacInsertMenuItem( appleMenu , "\pAbout..." , 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;
int pos ;
wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
if ( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
{
for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
{
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 ;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -