Exemple #1
0
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;

    menu->wxMenuBase::SetTitle(title);

    if (GetHmenu())
    {
        if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
                           (UINT_PTR)submenu, title.t_str()) )
        {
            wxLogLastError(wxT("AppendMenu"));
        }

#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accelerator table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return true;
}
Exemple #2
0
wxMenu *wxMenuBar::Remove(size_t pos)
{
    wxMenu *menu = wxMenuBarBase::Remove(pos);
    if ( !menu )
        return NULL;

    if (GetHmenu())
    {
        if ( !::RemoveMenu(GetHmenu(), (UINT)MSWPositionForWxMenu(menu,pos), MF_BYPOSITION) )
        {
            wxLogLastError(wxT("RemoveMenu"));
        }

#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return menu;
}
Exemple #3
0
bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
{
    // Find out which MSW item before which we'll be inserting before
    // wxMenuBarBase::Insert is called and GetMenu(pos) is the new menu.
    // If IsAttached() is false this won't be used anyway
    bool isAttached =
        (GetHmenu() != 0);

    if ( !wxMenuBarBase::Insert(pos, menu, title) )
        return false;

    menu->wxMenuBase::SetTitle(title);

    if ( isAttached )
    {
        // We have a problem with the index if there is an extra "Window" menu
        // in this menu bar, which is added by wxMDIParentFrame to it directly
        // using Windows API (so that it remains invisible to the user code),
        // but which does affect the indices of the items we insert after it.
        // So we check if any of the menus before the insertion position is a
        // foreign one and adjust the insertion index accordingly.
        int mswExtra = 0;

        // Skip all this if the total number of menus matches (notice that the
        // internal menu count has already been incremented by wxMenuBarBase::
        // Insert() call above, hence -1).
        int mswCount = ::GetMenuItemCount(GetHmenu());
        if ( mswCount != -1 &&
                static_cast<unsigned>(mswCount) != GetMenuCount() - 1 )
        {
            wxMenuList::compatibility_iterator node = m_menus.GetFirst();
            for ( size_t n = 0; n < pos; n++ )
            {
                if ( ::GetSubMenu(GetHmenu(), n) != GetHmenuOf(node->GetData()) )
                    mswExtra++;
                else
                    node = node->GetNext();
            }
        }

        if ( !::InsertMenu(GetHmenu(), pos + mswExtra,
                           MF_BYPOSITION | MF_POPUP | MF_STRING,
                           (UINT_PTR)GetHmenuOf(menu), title.t_str()) )
        {
            wxLogLastError(wxT("InsertMenu"));
        }
#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return true;
}
Exemple #4
0
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;

    menu->wxMenuBase::SetTitle(title);

#if defined(WINCE_WITHOUT_COMMANDBAR)
    if (IsAttached())
#else
    if (GetHmenu())
#endif
    {
#if defined(WINCE_WITHOUT_COMMANDBAR)
        if (!GetToolBar())
            return false;
        TBBUTTON tbButton;
        memset(&tbButton, 0, sizeof(TBBUTTON));
        tbButton.iBitmap = I_IMAGENONE;
        tbButton.fsState = TBSTATE_ENABLED;
        tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;

        size_t pos = GetMenuCount();
        HMENU hPopupMenu = (HMENU) menu->GetHMenu() ;
        tbButton.dwData = (DWORD)hPopupMenu;
        wxString label = wxStripMenuCodes(title);
        tbButton.iString = (int) label.wx_str();

        tbButton.idCommand = NewControlId();
        if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton))
        {
            wxLogLastError(wxT("TB_INSERTBUTTON"));
            return false;
        }
#else
        if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
                           (UINT_PTR)submenu, title.wx_str()) )
        {
            wxLogLastError(wxT("AppendMenu"));
        }
#endif

#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accelerator table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return true;
}
Exemple #5
0
void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
{
    wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );

    m_titles[pos] = label;

    if ( !IsAttached() )
    {
        return;
    }
    //else: have to modify the existing menu

    int mswpos = MSWPositionForWxMenu(GetMenu(pos),pos);

    UINT id;
    UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, mswpos, MF_BYPOSITION);
    if ( flagsOld == 0xFFFFFFFF )
    {
        wxLogLastError(wxT("GetMenuState"));

        return;
    }

    if ( flagsOld & MF_POPUP )
    {
        // HIBYTE contains the number of items in the submenu in this case
        flagsOld &= 0xff;
        id = (UINT)::GetSubMenu((HMENU)m_hMenu, mswpos);
    }
    else
    {
        id = pos;
    }

#ifdef __WXWINCE__
    MENUITEMINFO info;
    wxZeroMemory(info);
    info.cbSize = sizeof(info);
    info.fMask = MIIM_TYPE;
    info.fType = MFT_STRING;
    info.cch = label.Length();
    info.dwTypeData = (LPTSTR) label.c_str();
    if ( !SetMenuItemInfo(GetHmenu(), id, TRUE, & info) )
    {
        wxLogLastError(wxT("SetMenuItemInfo"));
    }

#else
    if ( ::ModifyMenu(GetHmenu(), mswpos, MF_BYPOSITION | MF_STRING | flagsOld,
        id, label) == (int)0xFFFFFFFF )
    {
        wxLogLastError(wxT("ModifyMenu"));
    }
#endif

    Refresh();
}
Exemple #6
0
void wxMenu::SetTitle(const wxString& label)
{
    bool hasNoTitle = m_title.empty();
    m_title = label;

    HMENU hMenu = GetHmenu();

    if ( hasNoTitle )
    {
        if ( !label.empty() )
        {
            if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
                               (UINT_PTR)idMenuTitle, m_title.t_str()) ||
                 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
            {
                wxLogLastError(wxT("InsertMenu"));
            }
        }
    }
    else
    {
        if ( label.empty() )
        {
            // remove the title and the separator after it
            if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
                 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
            {
                wxLogLastError(wxT("RemoveMenu"));
            }
        }
        else
        {
            // modify the title
            if ( !ModifyMenu(hMenu, 0u,
                             MF_BYPOSITION | MF_STRING,
                             (UINT_PTR)idMenuTitle, m_title.t_str()) )
            {
                wxLogLastError(wxT("ModifyMenu"));
            }
        }
    }

    // put the title string in bold face
    if ( !m_title.empty() )
    {
        SetDefaultMenuItem(GetHmenu(), (UINT)idMenuTitle);
    }
}
Exemple #7
0
bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id_)
{
    const int id = (signed short)id_;

    // ignore commands from the menu title
    if ( id != idMenuTitle )
    {
        // Default value for uncheckable items.
        int checked = -1;

        // update the check item when it's clicked
        wxMenuItem * const item = FindItem(id);
        if ( item && item->IsCheckable() )
        {
            item->Toggle();

            // Get the status of the menu item: note that it has been just changed
            // by Toggle() above so here we already get the new state of the item.
            //
            // Also notice that we must pass unsigned id_ and not sign-extended id
            // to ::GetMenuState() as this is what it expects.
            UINT menuState = ::GetMenuState(GetHmenu(), id_, MF_BYCOMMAND);
            checked = (menuState & MF_CHECKED) != 0;
        }

        SendEvent(id, checked);
    }

    return true;
}
Exemple #8
0
bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
{
    // Find out which MSW item before which we'll be inserting before
    // wxMenuBarBase::Insert is called and GetMenu(pos) is the new menu.
    // If IsAttached() is false this won't be used anyway
    int mswpos = (!IsAttached() || (pos == m_menus.GetCount()))
        ?   -1 // append the menu
        :   MSWPositionForWxMenu(GetMenu(pos),pos);

    if ( !wxMenuBarBase::Insert(pos, menu, title) )
        return false;

    m_titles.Insert(title, pos);

    if ( IsAttached() )
    {
#if defined(WINCE_WITHOUT_COMMANDAR)
        if (!GetToolBar())
            return false;
        TBBUTTON tbButton;
        memset(&tbButton, 0, sizeof(TBBUTTON));
        tbButton.iBitmap = I_IMAGENONE;
        tbButton.fsState = TBSTATE_ENABLED;
        tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;

        HMENU hPopupMenu = (HMENU) menu->GetHMenu() ;
        tbButton.dwData = (DWORD)hPopupMenu;
        wxString label = wxStripMenuCodes(title);
        tbButton.iString = (int) label.c_str();

        tbButton.idCommand = NewControlId();
        if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton))
        {
            wxLogLastError(wxT("TB_INSERTBUTTON"));
            return false;
        }
#else
        if ( !::InsertMenu(GetHmenu(), mswpos,
                           MF_BYPOSITION | MF_POPUP | MF_STRING,
                           (UINT)GetHmenuOf(menu), title) )
        {
            wxLogLastError(wxT("InsertMenu"));
        }
#endif
#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        Refresh();
    }

    return true;
}
Exemple #9
0
wxMenuItem* wxMenu::DoRemove(
  wxMenuItem*                       pItem
)
{
    //
    // We need to find the items position in the child list
    //
    size_t                          nPos;
    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();

    for (nPos = 0; node; nPos++)
    {
        if (node->GetData() == pItem)
            break;
        node = node->GetNext();
    }

    //
    // DoRemove() (unlike Remove) can only be called for existing item!
    //
    wxCHECK_MSG(node, NULL, wxT("bug in wxMenu::Remove logic"));

#if wxUSE_ACCEL
    //
    // Remove the corresponding accel from the accel table
    //
    int                             n = FindAccel(pItem->GetId());

    if (n != wxNOT_FOUND)
    {
        delete m_vAccels[n];
        m_vAccels.RemoveAt(n);
    }

#endif // wxUSE_ACCEL
    //
    // Remove the item from the menu
    //
    ::WinSendMsg( GetHmenu()
                 ,MM_REMOVEITEM
                 ,MPFROM2SHORT(pItem->GetId(), TRUE)
                 ,(MPARAM)0
                );
    if (IsAttached() && GetMenuBar()->IsAttached())
    {
        //
        // Otherwise, the chane won't be visible
        //
        GetMenuBar()->Refresh();
    }

    //
    // And from internal data structures
    //
    return wxMenuBase::DoRemove(pItem);
} // end of wxMenu::DoRemove
Exemple #10
0
wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
{
    wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
    if ( !menuOld )
        return NULL;

    menu->wxMenuBase::SetTitle(title);

#if defined(WINCE_WITHOUT_COMMANDBAR)
    if (IsAttached())
#else
    if (GetHmenu())
#endif
    {
        int mswpos = MSWPositionForWxMenu(menuOld,pos);

        // can't use ModifyMenu() because it deletes the submenu it replaces
        if ( !::RemoveMenu(GetHmenu(), (UINT)mswpos, MF_BYPOSITION) )
        {
            wxLogLastError(wxT("RemoveMenu"));
        }

        if ( !::InsertMenu(GetHmenu(), (UINT)mswpos,
                           MF_BYPOSITION | MF_POPUP | MF_STRING,
                           (UINT_PTR)GetHmenuOf(menu), title.wx_str()) )
        {
            wxLogLastError(wxT("InsertMenu"));
        }

#if wxUSE_ACCEL
        if ( menuOld->HasAccels() || menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return menuOld;
}
Exemple #11
0
wxMenu *wxMenuBar::Remove(size_t pos)
{
    wxMenu *menu = wxMenuBarBase::Remove(pos);
    if ( !menu )
        return NULL;

#if defined(WINCE_WITHOUT_COMMANDBAR)
    if (IsAttached())
#else
    if (GetHmenu())
#endif
    {
#if defined(WINCE_WITHOUT_COMMANDBAR)
        if (GetToolBar())
        {
            if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_DELETEBUTTON, (UINT) pos, (LPARAM) 0))
            {
                wxLogLastError(wxT("TB_DELETEBUTTON"));
            }
        }
#else
        if ( !::RemoveMenu(GetHmenu(), (UINT)MSWPositionForWxMenu(menu,pos), MF_BYPOSITION) )
        {
            wxLogLastError(wxT("RemoveMenu"));
        }
#endif

#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    m_titles.RemoveAt(pos);

    return menu;
}
Exemple #12
0
wxMenu* wxMenuBar::Remove(
  size_t                            nPos
)
{
    wxMenu*                         pMenu = wxMenuBarBase::Remove(nPos);
    SHORT                           nId;

    if (!pMenu)
        return NULL;

    nId = SHORT1FROMMR(::WinSendMsg( (HWND)GetHmenu()
                                    ,MM_ITEMIDFROMPOSITION
                                    ,MPFROMSHORT(nPos)
                                    ,(MPARAM)0)
                                   );
    if (nId == MIT_ERROR)
    {
        wxLogLastError(wxT("LogLastError"));
        return NULL;
    }
    if (IsAttached())
    {
        ::WinSendMsg( (HWND)GetHmenu()
                     ,MM_REMOVEITEM
                     ,MPFROM2SHORT(nId, TRUE)
                     ,(MPARAM)0
                    );

#if wxUSE_ACCEL
        if (pMenu->HasAccels())
        {
            //
            // Need to rebuild accell table
            //
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL
        Refresh();
    }
    m_titles.RemoveAt(nPos);
    return pMenu;
} // end of wxMenuBar::Remove
Exemple #13
0
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
    // we need to find the item's 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();
    }

#if wxUSE_ACCEL
    // remove the corresponding accel from the accel table
    int n = FindAccel(item->GetId());
    if ( n != wxNOT_FOUND )
    {
        delete m_accels[n];

        m_accels.RemoveAt(n);

#if wxUSE_OWNER_DRAWN
        ResetMaxAccelWidth();
#endif
    }
    //else: this item doesn't have an accel, nothing to do
#endif // wxUSE_ACCEL

    // Update indices of radio groups.
    if ( m_radioData )
    {
        bool inExistingGroup = m_radioData->UpdateOnRemoveItem(pos);

        wxASSERT_MSG( !inExistingGroup || item->GetKind() == wxITEM_RADIO,
                      wxT("Removing non radio button from radio group?") );
    }

    // remove the item from the menu
    if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
    {
        wxLogLastError(wxT("RemoveMenu"));
    }

    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        // otherwise, the change won't be visible
        GetMenuBar()->Refresh();
    }

    // and from internal data structures
    return wxMenuBase::DoRemove(item);
}
Exemple #14
0
bool wxMenuBar::IsEnabledTop(size_t pos) const
{
    wxCHECK_MSG( pos < GetMenuCount(), false, wxS("invalid menu index") );
    WinStruct<MENUITEMINFO> mii;
    mii.fMask = MIIM_STATE;
    if ( !::GetMenuItemInfo(GetHmenu(), pos, TRUE, &mii) )
    {
        wxLogLastError(wxS("GetMenuItemInfo(menubar)"));
    }

    return !(mii.fState & MFS_GRAYED);
}
Exemple #15
0
bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id)
{
    // ignore commands from the menu title
    if ( id != (WXWORD)idMenuTitle )
    {
        // get the checked status of the command: notice that menuState is the
        // old state of the menu, so the test for MF_CHECKED must be inverted
        UINT menuState = ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND);
        SendEvent(id, !(menuState & MF_CHECKED));
    }

    return true;
}
Exemple #16
0
void wxMenu::SetTitle( const wxString& rLabel )
{
    bool bHasNoTitle = m_title.empty();
    HWND hMenu = GetHmenu();

    m_title = rLabel;
    if (bHasNoTitle)
    {
        if (!rLabel.empty())
        {
            if (!::WinSetWindowText(hMenu, rLabel.c_str()))
            {
                wxLogLastError(wxT("SetMenuTitle"));
            }
        }
    }
    else
    {
        if (rLabel.empty() )
        {
            ::WinSendMsg( GetHmenu()
                         ,MM_REMOVEITEM
                         ,MPFROM2SHORT(hMenu, TRUE)
                         ,(MPARAM)0
                        );
        }
        else
        {
            //
            // Modify the title
            //
            if (!::WinSetWindowText(hMenu, rLabel.c_str()))
            {
                wxLogLastError(wxT("SetMenuTitle"));
            }
        }
    }
} // end of wxMenu::SetTitle
Exemple #17
0
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
    // we need to find the item's 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 an existing item!
    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );

#if wxUSE_ACCEL
    // remove the corresponding accel from the accel table
    int n = FindAccel(item->GetId());
    if ( n != wxNOT_FOUND )
    {
        delete m_accels[n];

        m_accels.RemoveAt(n);

#if wxUSE_OWNER_DRAWN
        ResetMaxAccelWidth();
#endif
    }
    //else: this item doesn't have an accel, nothing to do
#endif // wxUSE_ACCEL

    // remove the item from the menu
    if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
    {
        wxLogLastError(wxT("RemoveMenu"));
    }

    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        // otherwise, the change won't be visible
        GetMenuBar()->Refresh();
    }

    // and from internal data structures
    return wxMenuBase::DoRemove(item);
}
Exemple #18
0
// The wxWindow destructor will take care of deleting the submenus.
wxMenu::~wxMenu()
{
    // we should free Windows resources only if Windows doesn't do it for us
    // which happens if we're attached to a menubar or a submenu of another
    // menu
    if ( !IsAttached() && !GetParent() )
    {
        if ( !::DestroyMenu(GetHmenu()) )
        {
            wxLogLastError(wxT("DestroyMenu"));
        }
    }

#if wxUSE_ACCEL
    // delete accels
    WX_CLEAR_ARRAY(m_accels);
#endif // wxUSE_ACCEL
}
Exemple #19
0
bool wxMenu::OS2Command( WXUINT WXUNUSED(uParam),
                         WXWORD vId )
{
    //
    // Ignore commands from the menu title
    //

    if (vId != (WXWORD)idMenuTitle)
    {
        SendEvent( vId
                  ,(int)::WinSendMsg( GetHmenu()
                                     ,MM_QUERYITEMATTR
                                     ,MPFROMSHORT(vId)
                                     ,(MPARAM)MIA_CHECKED
                                    )
                 );
    }
    return true;
} // end of wxMenu::OS2Command
Exemple #20
0
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
    // we need to find the item's 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();
    }

#if wxUSE_ACCEL
    RemoveAccel(item);
#endif // wxUSE_ACCEL

    // Update indices of radio groups.
    if ( m_radioData )
    {
        if ( m_radioData->UpdateOnRemoveItem(pos) )
        {
            wxASSERT_MSG( item->IsRadio(),
                          wxT("Removing non radio button from radio group?") );
        }
        //else: item being removed is not in a radio group
    }

    // remove the item from the menu
    if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
    {
        wxLogLastError(wxT("RemoveMenu"));
    }

    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        // otherwise, the change won't be visible
        GetMenuBar()->Refresh();
    }

    // and from internal data structures
    return wxMenuBase::DoRemove(item);
}
Exemple #21
0
void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
{
    wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );

    m_menus[pos]->wxMenuBase::SetTitle(label);

    if ( !IsAttached() )
    {
        return;
    }
    //else: have to modify the existing menu

    int mswpos = MSWPositionForWxMenu(GetMenu(pos),pos);

    UINT_PTR id;
    UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, mswpos, MF_BYPOSITION);
    if ( flagsOld == 0xFFFFFFFF )
    {
        wxLogLastError(wxT("GetMenuState"));

        return;
    }

    if ( flagsOld & MF_POPUP )
    {
        // HIBYTE contains the number of items in the submenu in this case
        flagsOld &= 0xff;
        id = (UINT_PTR)::GetSubMenu((HMENU)m_hMenu, mswpos);
    }
    else
    {
        id = pos;
    }

    if ( ::ModifyMenu(GetHmenu(), mswpos, MF_BYPOSITION | MF_STRING | flagsOld,
                      id, label.t_str()) == (int)0xFFFFFFFF )
    {
        wxLogLastError(wxT("ModifyMenu"));
    }

    Refresh();
}
Exemple #22
0
bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id_)
{
    const int id = (signed short)id_;

    // ignore commands from the menu title
    if ( id != idMenuTitle )
    {
        // update the check item when it's clicked
        wxMenuItem * const item = FindItem(id);
        if ( item && item->IsCheckable() )
            item->Toggle();

        // get the status of the menu item: note that it has been just changed
        // by Toggle() above so here we already get the new state of the item
        UINT menuState = ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND);
        SendEvent(id, menuState & MF_CHECKED);
    }

    return true;
}
Exemple #23
0
//
// The wxWindow destructor will take care of deleting the submenus.
//
wxMenu::~wxMenu()
{
    //
    // We should free PM resources only if PM doesn't do it for us
    // which happens if we're attached to a menubar or a submenu of another
    // menu
    if (!IsAttached() && !GetParent())
    {
        if (!::WinDestroyWindow((HWND)GetHmenu()) )
        {
            wxLogLastError(wxT("WinDestroyWindow"));
        }
    }

#if wxUSE_ACCEL
    //
    // Delete accels
    //
    WX_CLEAR_ARRAY(m_vAccels);
#endif // wxUSE_ACCEL
} // end of wxMenu::~wxMenu
Exemple #24
0
void wxMenuBar::SetMenuLabel(
  size_t                            nPos
, const wxString&                   rLabel
)
{
    SHORT                           nId;
    MENUITEM                        vItem;

    wxCHECK_RET(nPos < GetMenuCount(), wxT("invalid menu index"));
    m_titles[nPos] = rLabel;

    if (!IsAttached())
    {
        return;
    }

    nId = SHORT1FROMMR(::WinSendMsg((HWND)m_hMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(nPos), (MPARAM)0));
    if (nId == MIT_ERROR)
    {
        wxLogLastError(wxT("LogLastError"));
        return;
    }
    if(!::WinSendMsg( (HWND)m_hMenu
                     ,MM_QUERYITEM
                     ,MPFROM2SHORT(nId, TRUE)
                     ,MPARAM(&vItem)
                    ))
    {
        wxLogLastError(wxT("QueryItem"));
    }
    nId = vItem.id;

    if (::WinSendMsg(GetHmenu(), MM_SETITEMTEXT, MPFROMSHORT(nId), (MPARAM)rLabel.wx_str()));
    {
        wxLogLastError(wxT("ModifyMenu"));
    }
    Refresh();
} // end of wxMenuBar::SetMenuLabel
Exemple #25
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    UINT flags = 0;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetText();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // adjust position to account for the title, if any
    if ( !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
        // is the item owner-drawn just because of the bitmap?
        if ( pItem->GetBitmap().Ok() &&
                !pItem->GetTextColour().Ok() &&
                    !pItem->GetBackgroundColour().Ok() &&
                        !pItem->GetFont().Ok() )
        {
            // try to use InsertMenuItem() as it's guaranteed to look correctly
            // while our owner-drawning code is not

            // first compile-time check
#ifdef MIIM_BITMAP
            WinStruct<MENUITEMINFO> mii;

            // now run-time one: MIIM_BITMAP only works under WinME/2000+
            if ( wxGetWinVersion() >= wxWinVersion_98 )
            {
                mii.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
                mii.wID = id;
                mii.cch = itemText.length();
                mii.dwTypeData = wx_const_cast(wxChar *, itemText.c_str());

                // we can't pass HBITMAP directly as hbmpItem for 2 reasons:
                //  1. we can't draw it with transparency then (this is not
                //     very important now but would be with themed menu bg)
                //  2. worse, Windows inverses the bitmap for the selected
                //     item and this looks downright ugly
                //
                // so instead draw it ourselves in MSWOnDrawItem()
                mii.dwItemData = wx_reinterpret_cast(ULONG_PTR, pItem);
                mii.hbmpItem = HBMMENU_CALLBACK;

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;

                    // don't call SetMenuInfo() directly, this would prevent
                    // the app from starting up under Windows 95/NT 4
                    typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);

                    wxDynamicLibrary dllUser(_T("user32"));
                    wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
                    if ( pfnSetMenuInfo )
                    {
                        mi.fMask = MIM_STYLE;
                        mi.dwStyle = MNS_CHECKORBMP;
                        if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
                            wxLogLastError(_T("SetMenuInfo(MNS_NOCHECK)"));
                    }

                    // tell the item that it's not really owner-drawn but only
                    // needs to draw its bitmap, the rest is done by Windows
                    pItem->ResetOwnerDrawn();
                }
            }
#endif // MIIM_BITMAP
        }
Exemple #26
0
void wxMenu::SetTitle(const wxString& label)
{
    bool hasNoTitle = m_title.empty();
    m_title = label;

    HMENU hMenu = GetHmenu();

    if ( hasNoTitle )
    {
        if ( !label.empty() )
        {
            if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
                               (UINT_PTR)idMenuTitle, m_title.wx_str()) ||
                 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
            {
                wxLogLastError(wxT("InsertMenu"));
            }
        }
    }
    else
    {
        if ( label.empty() )
        {
            // remove the title and the separator after it
            if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
                 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
            {
                wxLogLastError(wxT("RemoveMenu"));
            }
        }
        else
        {
            // modify the title
#ifdef __WXWINCE__
            WinStruct<MENUITEMINFO> info;
            info.fMask = MIIM_TYPE;
            info.fType = MFT_STRING;
            info.cch = m_title.length();
            info.dwTypeData = const_cast<wxChar *>(m_title.wx_str());
            if ( !SetMenuItemInfo(hMenu, 0, TRUE, & info) )
            {
                wxLogLastError(wxT("SetMenuItemInfo"));
            }
#else
            if ( !ModifyMenu(hMenu, 0u,
                             MF_BYPOSITION | MF_STRING,
                             (UINT_PTR)idMenuTitle, m_title.wx_str()) )
            {
                wxLogLastError(wxT("ModifyMenu"));
            }
#endif
        }
    }

#ifdef __WIN32__
    // put the title string in bold face
    if ( !m_title.empty() )
    {
        SetDefaultMenuItem(GetHmenu(), (UINT)idMenuTitle);
    }
#endif // Win32
}
Exemple #27
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    // we should support disabling the item even prior to adding it to the menu
    UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT_PTR id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT_PTR)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetMSWId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetItemLabel();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // Update radio groups data if we're inserting a new radio item.
    //
    // NB: If we supported inserting non-radio items in the middle of existing
    //     radio groups to break them into two subgroups, we'd need to update
    //     m_radioData in this case too but currently this is not supported.
    bool checkInitially = false;
    if ( pItem->GetKind() == wxITEM_RADIO )
    {
        if ( !m_radioData )
            m_radioData = new wxMenuRadioItemsData;

        if ( m_radioData->UpdateOnInsert(pos) )
            checkInitially = true;
    }

    // adjust position to account for the title of a popup menu, if any
    if ( !GetMenuBar() && !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

#if wxUSE_OWNER_DRAWN
    // Under older systems mixing owner-drawn and non-owner-drawn items results
    // in inconsistent margins, so we force this one to be owner-drawn if any
    // other items already are.
    if ( m_ownerDrawn )
        pItem->SetOwnerDrawn(true);
#endif // wxUSE_OWNER_DRAWN

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
#ifndef __DMC__

        if ( !m_ownerDrawn && !pItem->IsSeparator() )
        {
            // MIIM_BITMAP only works under WinME/2000+ so we always use owner
            // drawn item under the previous versions and we also have to use
            // them in any case if the item has custom colours or font
            static const wxWinVersion winver = wxGetWinVersion();
            bool mustUseOwnerDrawn = winver < wxWinVersion_98 ||
                                     pItem->GetTextColour().IsOk() ||
                                     pItem->GetBackgroundColour().IsOk() ||
                                     pItem->GetFont().IsOk();

            if ( !mustUseOwnerDrawn )
            {
                const wxBitmap& bmpUnchecked = pItem->GetBitmap(false),
                                bmpChecked   = pItem->GetBitmap(true);

                if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked)) ||
                     (bmpChecked.IsOk()   && IsGreaterThanStdSize(bmpChecked)) )
                {
                    mustUseOwnerDrawn = true;
                }
            }

            // use InsertMenuItem() if possible as it's guaranteed to look
            // correct while our owner-drawn code is not
            if ( !mustUseOwnerDrawn )
            {
                WinStruct<MENUITEMINFO> mii;
                mii.fMask = MIIM_STRING | MIIM_DATA;

                // don't set hbmpItem for the checkable items as it would
                // be used for both checked and unchecked state
                if ( pItem->IsCheckable() )
                {
                    mii.fMask |= MIIM_CHECKMARKS;
                    mii.hbmpChecked = GetHBitmapForMenu(pItem, true);
                    mii.hbmpUnchecked = GetHBitmapForMenu(pItem, false);
                }
                else if ( pItem->GetBitmap().IsOk() )
                {
                    mii.fMask |= MIIM_BITMAP;
                    mii.hbmpItem = GetHBitmapForMenu(pItem);
                }

                mii.cch = itemText.length();
                mii.dwTypeData = const_cast<wxChar *>(itemText.wx_str());

                if ( flags & MF_POPUP )
                {
                    mii.fMask |= MIIM_SUBMENU;
                    mii.hSubMenu = GetHmenuOf(pItem->GetSubMenu());
                }
                else
                {
                    mii.fMask |= MIIM_ID;
                    mii.wID = id;
                }

                mii.dwItemData = reinterpret_cast<ULONG_PTR>(pItem);

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;

                    // don't call SetMenuInfo() directly, this would prevent
                    // the app from starting up under Windows 95/NT 4
                    typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);

                    wxDynamicLibrary dllUser(wxT("user32"));
                    wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
                    if ( pfnSetMenuInfo )
                    {
                        mi.fMask = MIM_STYLE;
                        mi.dwStyle = MNS_CHECKORBMP;
                        if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
                        {
                            wxLogLastError(wxT("SetMenuInfo(MNS_NOCHECK)"));
                        }
                    }

                    // tell the item that it's not really owner-drawn but only
                    // needs to draw its bitmap, the rest is done by Windows
                    pItem->SetOwnerDrawn(false);
                }
            }
        }
#endif // __DMC__

        if ( !ok )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;

            bool updateAllMargins = false;

            // get size of bitmap always return valid value (0 for invalid bitmap),
            // so we don't needed check if bitmap is valid ;)
            int uncheckedW = pItem->GetBitmap(false).GetWidth();
            int checkedW   = pItem->GetBitmap(true).GetWidth();

            if ( m_maxBitmapWidth < uncheckedW )
            {
                m_maxBitmapWidth = uncheckedW;
                updateAllMargins = true;
            }

            if ( m_maxBitmapWidth < checkedW )
            {
                m_maxBitmapWidth = checkedW;
                updateAllMargins = true;
            }

            // make other item ownerdrawn and update margin width for equals alignment
            if ( !m_ownerDrawn || updateAllMargins )
            {
                // we must use position in SetOwnerDrawnMenuItem because
                // all separators have the same id
                int pos = 0;
                wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
                while (node)
                {
                    wxMenuItem* item = node->GetData();

                    if ( !item->IsOwnerDrawn())
                    {
                        item->SetOwnerDrawn(true);
                        SetOwnerDrawnMenuItem(GetHmenu(), pos,
                                              reinterpret_cast<ULONG_PTR>(item), TRUE);
                    }

                    item->SetMarginWidth(m_maxBitmapWidth);

                    node = node->GetNext();
                    pos++;
                }

                // set menu as ownerdrawn
                m_ownerDrawn = true;

                ResetMaxAccelWidth();
            }
            // only update our margin for equals alignment to other item
            else if ( !updateAllMargins )
            {
                pItem->SetMarginWidth(m_maxBitmapWidth);
            }
        }
    }
    else
#endif // wxUSE_OWNER_DRAWN
    {
        // item is just a normal string (passed in data parameter)
        flags |= MF_STRING;

#ifdef __WXWINCE__
        itemText = wxMenuItem::GetLabelText(itemText);
#endif

        pData = (wxChar*)itemText.wx_str();
    }

    // item might have already been inserted by InsertMenuItem() above
    if ( !ok )
    {
        if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
        {
            wxLogLastError(wxT("InsertMenu[Item]()"));

            return false;
        }
    }


    // Check the item if it should be initially checked.
    if ( checkInitially )
        pItem->Check(true);

    // if we just appended the title, highlight it
    if ( id == (UINT_PTR)idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}
Exemple #28
0
bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
{
    // Find out which MSW item before which we'll be inserting before
    // wxMenuBarBase::Insert is called and GetMenu(pos) is the new menu.
    // If IsAttached() is false this won't be used anyway
    bool isAttached =
#if defined(WINCE_WITHOUT_COMMANDBAR)
        IsAttached();
#else
        (GetHmenu() != 0);
#endif

    if ( !wxMenuBarBase::Insert(pos, menu, title) )
        return false;

    menu->wxMenuBase::SetTitle(title);

    if ( isAttached )
    {
#if defined(WINCE_WITHOUT_COMMANDBAR)
        if (!GetToolBar())
            return false;
        TBBUTTON tbButton;
        memset(&tbButton, 0, sizeof(TBBUTTON));
        tbButton.iBitmap = I_IMAGENONE;
        tbButton.fsState = TBSTATE_ENABLED;
        tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE;

        HMENU hPopupMenu = (HMENU) menu->GetHMenu() ;
        tbButton.dwData = (DWORD)hPopupMenu;
        wxString label = wxStripMenuCodes(title);
        tbButton.iString = (int) wxMSW_CONV_LPCTSTR(label);

        tbButton.idCommand = NewControlId();
        if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton))
        {
            wxLogLastError(wxT("TB_INSERTBUTTON"));
            return false;
        }
#else
        // We have a problem with the index if there is an extra "Window" menu
        // in this menu bar, which is added by wxMDIParentFrame to it directly
        // using Windows API (so that it remains invisible to the user code),
        // but which does affect the indices of the items we insert after it.
        // So we check if any of the menus before the insertion position is a
        // foreign one and adjust the insertion index accordingly.
        int mswExtra = 0;

        // Skip all this if the total number of menus matches (notice that the
        // internal menu count has already been incremented by wxMenuBarBase::
        // Insert() call above, hence -1).
        int mswCount = ::GetMenuItemCount(GetHmenu());
        if ( mswCount != -1 &&
                static_cast<unsigned>(mswCount) != GetMenuCount() - 1 )
        {
            wxMenuList::compatibility_iterator node = m_menus.GetFirst();
            for ( size_t n = 0; n < pos; n++ )
            {
                if ( ::GetSubMenu(GetHmenu(), n) != GetHmenuOf(node->GetData()) )
                    mswExtra++;
                else
                    node = node->GetNext();
            }
        }

        if ( !::InsertMenu(GetHmenu(), pos + mswExtra,
                           MF_BYPOSITION | MF_POPUP | MF_STRING,
                           (UINT_PTR)GetHmenuOf(menu), title.t_str()) )
        {
            wxLogLastError(wxT("InsertMenu"));
        }
#endif
#if wxUSE_ACCEL
        if ( menu->HasAccels() )
        {
            // need to rebuild accell table
            RebuildAccelTable();
        }
#endif // wxUSE_ACCEL

        if (IsAttached())
            Refresh();
    }

    return true;
}
Exemple #29
0
//
// Append a new item or submenu to the menu
//
bool wxMenu::DoInsertOrAppend( wxMenuItem* pItem,
                               size_t      nPos )
{
    wxMenu*    pSubmenu = pItem->GetSubMenu();
    MENUITEM&  rItem = (pSubmenu != NULL)?pSubmenu->m_vMenuData:
                       pItem->m_vMenuData;

    ERRORID    vError;
    wxString   sError;

#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    //
    // If "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    //
    if (m_bDoBreak)
    {
        rItem.afStyle |= MIS_BREAK;
        m_bDoBreak = false;
    }

    //
    // Id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::MM_INSERTITEM message API
    //
    if (pSubmenu != NULL)
    {
        wxASSERT_MSG(pSubmenu->GetHMenu(), wxT("invalid submenu"));
        pSubmenu->SetParent(this);

        rItem.iPosition = 0; // submenus have a 0 position
        rItem.id        = (USHORT)pSubmenu->GetHMenu();
        rItem.afStyle  |= MIS_SUBMENU | MIS_TEXT;
    }
    else
    {
        rItem.id = (USHORT)pItem->GetId();
    }

    char *pData = NULL;

#if wxUSE_OWNER_DRAWN
    if (pItem->IsOwnerDrawn())
    {
        //
        // Want to get {Measure|Draw}Item messages?
        // item draws itself, passing pointer to data doesn't work in OS/2
        // Will eventually need to set the image handle somewhere into vItem.hItem
        //
        rItem.afStyle             |= MIS_OWNERDRAW;
        pData                      = NULL;
        rItem.hItem                = (HBITMAP)pItem->GetBitmap().GetHBITMAP();
        pItem->m_vMenuData.afStyle = rItem.afStyle;
        pItem->m_vMenuData.hItem   = rItem.hItem;
    }
    else
#endif
    if (pItem->IsSeparator())
    {
        rItem.afStyle = MIS_SEPARATOR;
    }
    else
    {
        if (pItem->GetId() == idMenuTitle)
        {
            // Item is an unselectable title to be passed via pData
            rItem.afStyle = MIS_STATIC;
        }
        else
        {
            //
            // Menu is just a normal string (passed in data parameter)
            //
            rItem.afStyle |= MIS_TEXT;
        }
        pData = (char*) pItem->GetItemLabel().wx_str();
    }

    if (nPos == (size_t)-1)
    {
        rItem.iPosition = MIT_END;
    }
    else
    {
        rItem.iPosition = (SHORT)nPos;
    }

    APIRET                          rc;

    rc = (APIRET)::WinSendMsg( GetHmenu()
                              ,MM_INSERTITEM
                              ,(MPARAM)&rItem
                              ,(MPARAM)pData
                             );
#if wxUSE_OWNER_DRAWN
    if (pItem->IsOwnerDrawn())
    {
        MENUITEM                   vMenuItem;

        ::WinSendMsg( GetHmenu()
                     ,MM_QUERYITEM
                     ,MPFROM2SHORT( (USHORT)pItem->GetId()
                                   ,(USHORT)(FALSE)
                                  )
                     ,&vMenuItem
                    );
    }
#endif

    if (rc == (APIRET)MIT_MEMERROR || rc == (APIRET)MIT_ERROR)
    {
        vError = ::WinGetLastError(vHabmain);
        sError = wxPMErrorToStr(vError);
        wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError.c_str());
        wxLogLastError(wxT("Insert or AppendMenu"));
        return false;
    }

    //
    // If we're already attached to the menubar, we must update it
    //
    if (IsAttached() && GetMenuBar()->IsAttached())
    {
        GetMenuBar()->Refresh();
    }

    return true;
} // end of wxMenu::DoInsertOrAppend
Exemple #30
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    // we should support disabling the item even prior to adding it to the menu
    UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT_PTR id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT_PTR)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetMSWId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetItemLabel();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // Update radio groups data if we're inserting a new menu item.
    // Inserting radio and non-radio item has a different impact
    // on radio groups so we have to handle each case separately.
    // (Inserting a radio item in the middle of existing group extends
    // the group, but inserting non-radio item breaks it into two subgroups.)
    //
    bool checkInitially = false;
    if ( pItem->IsRadio() )
    {
        if ( !m_radioData )
            m_radioData = new wxMenuRadioItemsData;

        if ( m_radioData->UpdateOnInsertRadio(pos) )
            checkInitially = true;
    }
    else if ( m_radioData )
    {
        if ( m_radioData->UpdateOnInsertNonRadio(pos) )
        {
            // One of the existing groups has been split into two subgroups.
            wxFAIL_MSG(wxS("Inserting non-radio item inside a radio group?"));
        }
    }

    // Also handle the case of check menu items that had been checked before
    // being attached to the menu: we don't need to actually call Check() on
    // them, so we don't use checkInitially in this case, but we do need to
    // make them checked at Windows level too. Notice that we shouldn't ask
    // Windows for the checked state here, as wxMenuItem::IsChecked() does, as
    // the item is not attached yet, so explicitly call the base class version.
    if ( pItem->IsCheck() && pItem->wxMenuItemBase::IsChecked() )
        flags |= MF_CHECKED;

    // adjust position to account for the title of a popup menu, if any
    if ( !GetMenuBar() && !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

#if wxUSE_OWNER_DRAWN
    // Under older systems mixing owner-drawn and non-owner-drawn items results
    // in inconsistent margins, so we force this one to be owner-drawn if any
    // other items already are.
    if ( m_ownerDrawn )
        pItem->SetOwnerDrawn(true);

    // check if we have something more than a simple text item
    bool makeItemOwnerDrawn = false;
#endif // wxUSE_OWNER_DRAWN

    if (
#if wxUSE_OWNER_DRAWN
            !pItem->IsOwnerDrawn() &&
#endif
        !pItem->IsSeparator() )
            {
                WinStruct<MENUITEMINFO> mii;
                mii.fMask = MIIM_STRING | MIIM_DATA;

                // don't set hbmpItem for the checkable items as it would
                // be used for both checked and unchecked state
                if ( pItem->IsCheckable() )
                {
                    mii.fMask |= MIIM_CHECKMARKS;
                    mii.hbmpChecked = pItem->GetHBitmapForMenu(wxMenuItem::Checked);
                    mii.hbmpUnchecked = pItem->GetHBitmapForMenu(wxMenuItem::Unchecked);
                }
                else if ( pItem->GetBitmap().IsOk() )
                {
                    mii.fMask |= MIIM_BITMAP;
                    mii.hbmpItem = pItem->GetHBitmapForMenu(wxMenuItem::Normal);
                }

                mii.cch = itemText.length();
                mii.dwTypeData = wxMSW_CONV_LPTSTR(itemText);

                if ( flags & MF_POPUP )
                {
                    mii.fMask |= MIIM_SUBMENU;
                    mii.hSubMenu = GetHmenuOf(pItem->GetSubMenu());
                }
                else
                {
                    mii.fMask |= MIIM_ID;
                    mii.wID = id;
                }

                if ( flags & MF_GRAYED )
                {
                    mii.fMask |= MIIM_STATE;
                    mii.fState = MFS_GRAYED;
                }

                if ( flags & MF_CHECKED )
                {
                    mii.fMask |= MIIM_STATE;
                    mii.fState = MFS_CHECKED;
                }

                mii.dwItemData = reinterpret_cast<ULONG_PTR>(pItem);

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
#if wxUSE_OWNER_DRAWN
            // In case of failure switch new item to the owner-drawn mode.
            makeItemOwnerDrawn = true;
#endif
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;
                    mi.fMask = MIM_STYLE;
                    mi.dwStyle = MNS_CHECKORBMP;
                    if ( !::SetMenuInfo(GetHmenu(), &mi) )
                    {
                        wxLogLastError(wxT("SetMenuInfo(MNS_NOCHECK)"));
                    }
                }
        }

#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() || makeItemOwnerDrawn )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;

            bool updateAllMargins = false;

            // get size of bitmap always return valid value (0 for invalid bitmap),
            // so we don't needed check if bitmap is valid ;)
            int uncheckedW = pItem->GetBitmap(false).GetWidth();
            int checkedW   = pItem->GetBitmap(true).GetWidth();

            if ( m_maxBitmapWidth < uncheckedW )
            {
                m_maxBitmapWidth = uncheckedW;
                updateAllMargins = true;
            }

            if ( m_maxBitmapWidth < checkedW )
            {
                m_maxBitmapWidth = checkedW;
                updateAllMargins = true;
            }

            // make other item ownerdrawn and update margin width for equals alignment
            if ( !m_ownerDrawn || updateAllMargins )
            {
                // we must use position in SetOwnerDrawnMenuItem because
                // all separators have the same id
                int position = 0;
                wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
                while (node)
                {
                    wxMenuItem* item = node->GetData();

                    // Current item is already added to the list of items
                    // but is not yet physically attached to the menu
                    // so we have to skip setting it as an owner drawn.
                    // It will be done later on when the item will be created.
                    if ( !item->IsOwnerDrawn() && item != pItem )
                    {
                        item->SetOwnerDrawn(true);
                        SetOwnerDrawnMenuItem(GetHmenu(), position,
                                              reinterpret_cast<ULONG_PTR>(item), TRUE);
                    }

                    item->SetMarginWidth(m_maxBitmapWidth);

                    node = node->GetNext();
                    // Current item is already added to the list of items
                    // but is not yet physically attached to the menu
                    // so it cannot be counted while determining position
                    // in the menu.
                    if ( item != pItem )
                        position++;
                }

                // set menu as ownerdrawn
                m_ownerDrawn = true;

                ResetMaxAccelWidth();
            }
            // only update our margin for equals alignment to other item
            else if ( !updateAllMargins )
            {
                pItem->SetMarginWidth(m_maxBitmapWidth);
            }
        }
#endif // wxUSE_OWNER_DRAWN

    // item might have already been inserted by InsertMenuItem() above
    if ( !ok )
    {
        if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
        {
            wxLogLastError(wxT("InsertMenu[Item]()"));

            return false;
        }

#if wxUSE_OWNER_DRAWN
        if ( makeItemOwnerDrawn )
        {
            pItem->SetOwnerDrawn(true);
            SetOwnerDrawnMenuItem(GetHmenu(), pos,
                                  reinterpret_cast<ULONG_PTR>(pItem), TRUE);
        }
#endif
    }


    // Check the item if it should be initially checked.
    if ( checkInitially )
        pItem->Check(true);

    // if we just appended the title, highlight it
    if ( id == (UINT_PTR)idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}