⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.cpp

📁 wxWidgets 是一个跨平台的 GUI 框架。它给开发人员提供了统一的接口
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////// Name:        src/mac/carbon/menu.cpp// Purpose:     wxMenu, wxMenuBar, wxMenuItem// Author:      Stefan Csomor// Modified by:// Created:     1998-01-01// RCS-ID:      $Id: menu.cpp,v 1.96 2006/10/25 07:31:46 RD Exp $// Copyright:   (c) Stefan Csomor// Licence:     wxWindows licence/////////////////////////////////////////////////////////////////////////////// ============================================================================// headers & declarations// ============================================================================// wxWidgets headers// -----------------#include "wx/wxprec.h"#include "wx/menu.h"#ifndef WX_PRECOMP    #include "wx/log.h"    #include "wx/app.h"    #include "wx/utils.h"    #include "wx/frame.h"    #include "wx/menuitem.h"#endif#include "wx/mac/uma.h"// other standard headers// ----------------------#include <string.h>IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)// the (popup) menu title has this special idstatic const int idMenuTitle = -3;static const short kwxMacAppleMenuId = 1 ;// Find an item given the Macintosh Menu ReferenceWX_DECLARE_HASH_MAP(MenuRef, wxMenu*, wxPointerHash, wxPointerEqual, MacMenuMap);static MacMenuMap wxWinMacMenuList;wxMenu *wxFindMenuFromMacMenu(MenuRef inMenuRef){    MacMenuMap::iterator node = wxWinMacMenuList.find(inMenuRef);    return (node == wxWinMacMenuList.end()) ? NULL : node->second;}void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu) ;void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu){    // adding NULL MenuRef is (first) surely a result of an error and    // (secondly) breaks menu command processing    wxCHECK_RET( inMenuRef != (MenuRef) NULL, wxT("attempt to add a NULL MenuRef to menu list") );    wxWinMacMenuList[inMenuRef] = menu;}void wxRemoveMacMenuAssociation(wxMenu *menu) ;void wxRemoveMacMenuAssociation(wxMenu *menu){   // iterate over all the elements in the class    MacMenuMap::iterator it;    for ( it = wxWinMacMenuList.begin(); it != wxWinMacMenuList.end(); ++it )    {        if ( it->second == menu )        {            wxWinMacMenuList.erase(it);            break;        }    }}// ============================================================================// implementation// ============================================================================static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );// Menus// Construct a menu with optional title (then use append)#ifdef __DARWIN__short wxMenu::s_macNextMenuId = 3 ;#elseshort wxMenu::s_macNextMenuId = 2 ;#endifstaticwxMenu *_wxMenuAt(const wxMenuList &menuList, size_t pos){    wxMenuList::compatibility_iterator menuIter = menuList.GetFirst();    while (pos-- > 0)        menuIter = menuIter->GetNext();    return menuIter->GetData() ;}void wxMenu::Init(){    m_doBreak = false;    m_startRadioGroup = -1;    // create the menu    m_macMenuId = s_macNextMenuId++;    m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );    if ( !m_hMenu )    {        wxLogLastError(wxT("UMANewMenu failed"));    }    wxAssociateMenuWithMacMenu( (MenuRef)m_hMenu , this ) ;    // if we have a title, insert it in the beginning of the menu    if ( !m_title.empty() )    {        Append(idMenuTitle, m_title) ;        AppendSeparator() ;    }}wxMenu::~wxMenu(){    wxRemoveMacMenuAssociation( this ) ;    if (MAC_WXHMENU(m_hMenu))        ::DisposeMenu(MAC_WXHMENU(m_hMenu));}void wxMenu::Break(){    // not available on the mac platform}void wxMenu::Attach(wxMenuBarBase *menubar){    wxMenuBase::Attach(menubar);    EndRadioGroup();}// function appends a new item or submenu to the menu// append a new item or submenu to the menubool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos){    wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );    if ( pItem->IsSeparator() )    {        if ( pos == (size_t)-1 )            AppendMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu),                CFSTR(""), kMenuItemAttrSeparator, 0,NULL);         else            InsertMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu),                CFSTR(""), pos, kMenuItemAttrSeparator, 0);     }    else    {        wxMenu *pSubMenu = pItem->GetSubMenu() ;        if ( pSubMenu != NULL )        {            wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));            pSubMenu->m_menuParent = this ;            if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())                pSubMenu->MacBeforeDisplay( true ) ;            if ( pos == (size_t)-1 )                UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetText()), wxFont::GetDefaultEncoding(), pSubMenu->m_macMenuId);            else                UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetText()), wxFont::GetDefaultEncoding(), pos, pSubMenu->m_macMenuId);            pItem->UpdateItemBitmap() ;            pItem->UpdateItemStatus() ;        }        else        {            if ( pos == (size_t)-1 )            {                UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , wxFont::GetDefaultEncoding() );                pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;            }            else            {                // MacOS counts menu items from 1 and inserts after, therefore having the                // same effect as wx 0 based and inserting before, we must correct pos                // after however for updates to be correct                UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), pos);                pos += 1 ;            }            SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , wxIdToMacCommand ( pItem->GetId() ) ) ;            SetMenuItemRefCon( MAC_WXHMENU(m_hMenu) , pos , (URefCon) pItem ) ;            pItem->UpdateItemText() ;            pItem->UpdateItemBitmap() ;            pItem->UpdateItemStatus() ;            if ( pItem->GetId() == idMenuTitle )                UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;        }    }    // if we're already attached to the menubar, we must update it    if ( IsAttached() && GetMenuBar()->IsAttached() )        GetMenuBar()->Refresh();    return true ;}void wxMenu::EndRadioGroup(){    // we're not inside a radio group any longer    m_startRadioGroup = -1;}wxMenuItem* wxMenu::DoAppend(wxMenuItem *item){    wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );    bool check = false;    if ( item->GetKind() == wxITEM_RADIO )    {        int count = GetMenuItemCount();        if ( m_startRadioGroup == -1 )        {            // start a new radio group            m_startRadioGroup = count;            // for now it has just one element            item->SetAsRadioGroupStart();            item->SetRadioGroupEnd(m_startRadioGroup);            // ensure that we have a checked item in the radio group            check = true;        }        else // extend the current radio group        {            // we need to update its end item            item->SetRadioGroupStart(m_startRadioGroup);            wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup);            if ( node )            {                node->GetData()->SetRadioGroupEnd(count);            }            else            {                wxFAIL_MSG( _T("where is the radio group start item?") );            }        }    }    else // not a radio item    {        EndRadioGroup();    }    if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )        return NULL;    if ( check )        // check the item initially        item->Check(true);    return item;}wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item){    if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))        return item;    return NULL;}wxMenuItem *wxMenu::DoRemove(wxMenuItem *item){    // we need to find the items position in the child list    size_t pos;    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();    for ( pos = 0; node; pos++ )    {        if ( node->GetData() == item )            break;        node = node->GetNext();    }    // DoRemove() (unlike Remove) can only be called for existing item!    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );    ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);    if ( IsAttached() && GetMenuBar()->IsAttached() )        // otherwise, the change won't be visible        GetMenuBar()->Refresh();    // and from internal data structures    return wxMenuBase::DoRemove(item);}void wxMenu::SetTitle(const wxString& label){    m_title = label ;    UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;}bool wxMenu::ProcessCommand(wxCommandEvent & event){    bool processed = false;    // Try the menu's event handler    if ( /* !processed && */ GetEventHandler())        processed = GetEventHandler()->ProcessEvent(event);    // Try the window the menu was popped up from    // (and up through the hierarchy)    wxWindow *win = GetInvokingWindow();    if ( !processed && win )        processed = win->GetEventHandler()->ProcessEvent(event);    return processed;}// ---------------------------------------------------------------------------// other// ---------------------------------------------------------------------------wxWindow *wxMenu::GetWindow() const{    if ( m_invokingWindow != NULL )        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 0int 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 OSvoid 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 callvoid wxMenu::MacAfterDisplay( bool isSubMenu ){    if ( isSubMenu )        ::DeleteMenu(MacGetMenuId());    wxMenuItemList::compatibility_iterator node;    wxMenuItem *item;    for (node = GetMenuItems().GetFirst(); node; node = node->GetNext())    {        item = (wxMenuItem *)node->GetData();        wxMenu* subMenu = item->GetSubMenu() ;        if (subMenu)        {            subMenu->MacAfterDisplay( true ) ;        }        else        {            // no need to undo hidings        }    }}// Menu Bar/*Mac Implementation note :The Mac has only one global menubar, so we attempt to install the currentlyactive menubar from a frame, we currently don't take into account mdi-frameswhich would ask for menu-merging

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -