示例#1
0
int wxMenuItem::MSGetMenuItemPos() const
{
    if ( !m_parentMenu )
        return -1;

    const HMENU hMenu = GetHMenuOf(m_parentMenu);
    if ( !hMenu )
        return -1;

    const UINT id = GetMSWId();
    const int menuItems = ::GetMenuItemCount(hMenu);
    for ( int i = 0; i < menuItems; i++ )
    {
        const UINT state = ::GetMenuState(hMenu, i, MF_BYPOSITION);
        if ( state == (UINT)-1 )
        {
            // This indicates that the item at this position and is not
            // supposed to happen here, but test for it just in case.
            continue;
        }

        if ( state & MF_POPUP )
        {
            if ( ::GetSubMenu(hMenu, i) == (HMENU)wxUIntToPtr(id) )
                return i;
        }
        else if ( !(state & MF_SEPARATOR) )
        {
            if ( ::GetMenuItemID(hMenu, i) == id )
                return i;
        }
    }

    return -1;
}
示例#2
0
bool wxMenuItem::IsChecked() const
{
    // fix that RTTI is always getting the correct state (separators cannot be
    // checked, but the Windows call below returns true
    if ( IsSeparator() )
        return false;

    // the item might not be attached to a menu yet
    //
    // TODO: shouldn't we just always call the base class version? It seems
    //       like it ought to always be in sync
    if ( !m_parentMenu )
        return wxMenuItemBase::IsChecked();

    HMENU hmenu = GetHMenuOf(m_parentMenu);
    int flag = ::GetMenuState(hmenu, GetMSWId(), MF_BYCOMMAND);

    return (flag & MF_CHECKED) != 0;
}
示例#3
0
void wxMenuItem::Enable(bool enable)
{
    if ( m_isEnabled == enable )
        return;

    if ( m_parentMenu )
    {
        long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
                                 GetMSWId(),
                                 MF_BYCOMMAND |
                                 (enable ? MF_ENABLED : MF_GRAYED));

        if ( rc == -1 )
        {
            wxLogLastError(wxT("EnableMenuItem"));
        }
    }

    wxMenuItemBase::Enable(enable);
}
示例#4
0
void wxMenuItem::Check(bool check)
{
    wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );

    if ( m_isChecked == check )
        return;

    if ( m_parentMenu )
    {
        int flags = check ? MF_CHECKED : MF_UNCHECKED;
        HMENU hmenu = GetHMenuOf(m_parentMenu);

        if ( GetKind() == wxITEM_RADIO )
        {
            // it doesn't make sense to uncheck a radio item -- what would this
            // do?
            if ( !check )
                return;

            // get the index of this item in the menu
            const wxMenuItemList& items = m_parentMenu->GetMenuItems();
            int pos = items.IndexOf(this);
            wxCHECK_RET( pos != wxNOT_FOUND,
                         wxT("menuitem not found in the menu items list?") );

            // get the radio group range
            int start,
                end;

            if ( !m_parentMenu->MSWGetRadioGroupRange(pos, &start, &end) )
            {
                wxFAIL_MSG( wxT("Menu radio item not part of radio group?") );
                return;
            }

#ifdef __WIN32__
            // calling CheckMenuRadioItem() with such parameters hangs my system
            // (NT4 SP6) and I suspect this could happen to the others as well,
            // so don't do it!
            wxCHECK_RET( start != -1 && end != -1,
                         wxT("invalid ::CheckMenuRadioItem() parameter(s)") );

            if ( !::CheckMenuRadioItem(hmenu,
                                       start,   // the first radio group item
                                       end,     // the last one
                                       pos,     // the one to check
                                       MF_BYPOSITION) )
            {
                wxLogLastError(wxT("CheckMenuRadioItem"));
            }
#endif // __WIN32__

            // also uncheck all the other items in this radio group
            wxMenuItemList::compatibility_iterator node = items.Item(start);
            for ( int n = start; n <= end && node; n++ )
            {
                if ( n != pos )
                {
                    node->GetData()->m_isChecked = false;
                }

                node = node->GetNext();
            }
        }
        else // check item
        {
            if ( ::CheckMenuItem(hmenu,
                                 GetMSWId(),
                                 MF_BYCOMMAND | flags) == (DWORD)-1 )
            {
                wxFAIL_MSG(wxT("CheckMenuItem() failed, item not in the menu?"));
            }
        }
    }

    wxMenuItemBase::Check(check);
}
示例#5
0
void wxMenuItem::DoSetBitmap(const wxBitmap& bmp, bool bChecked)
{
    if ( bChecked )
    {
        if ( m_bmpChecked.IsSameAs(bmp) )
            return;

        m_bmpChecked = bmp;
    }
    else
    {
        if ( m_bmpUnchecked.IsSameAs(bmp) )
            return;

        m_bmpUnchecked = bmp;
    }

#if wxUSE_OWNER_DRAWN
    // already marked as owner-drawn, cannot be reverted
    if ( IsOwnerDrawn() )
        return;

    if ( MSWMustUseOwnerDrawn() )
    {
        SetOwnerDrawn(true);

        // Parent menu has to be rearranged/recalculated in this case
        // (all other menu items have to be also set to owner-drawn mode).
        if ( m_parentMenu )
        {
            size_t pos;
            wxMenuItem *item = m_parentMenu->FindChildItem(GetMSWId(), &pos);
            if ( item )
            {
                wxCHECK_RET( item == this, wxS("Non unique menu item ID?") );

                m_parentMenu->Remove(this);
                m_parentMenu->Insert(pos, this);
            }
            //else: the item hasn't been inserted into the parent menu yet
        }
        return;
    }
#endif // wxUSE_OWNER_DRAWN

    // the item can be not attached to any menu yet and SetBitmap() is still
    // valid to call in this case and should do nothing else
    if ( !m_parentMenu )
        return;

    HMENU hMenu = GetHMenuOf(m_parentMenu);
    if ( !hMenu )
        return;

    const UINT id = GetMSWId();

    const UINT state = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
    if ( state == (UINT)-1 )
        return;

    // update the bitmap of the native menu item
    // don't set hbmpItem for the checkable items as it would
    // be used for both checked and unchecked state
    WinStruct<MENUITEMINFO> mii;
    if ( IsCheckable() )
    {
        mii.fMask = MIIM_CHECKMARKS;
        mii.hbmpChecked = GetHBitmapForMenu(true);
        mii.hbmpUnchecked = GetHBitmapForMenu(false);
    }
    else
    {
        mii.fMask = MIIM_BITMAP;
        mii.hbmpItem = GetHBitmapForMenu();
    }

    if ( !::SetMenuItemInfo(hMenu, id, FALSE, &mii) )
    {
        wxLogLastError(wxT("SetMenuItemInfo"));
    }
}
示例#6
0
void wxMenuItem::SetItemLabel(const wxString& txt)
{
    wxString text = txt;

    // don't do anything if label didn't change
    if ( m_text == txt )
        return;

    // wxMenuItemBase will do stock ID checks
    wxMenuItemBase::SetItemLabel(text);

    // the item can be not attached to any menu yet and SetItemLabel() is still
    // valid to call in this case and should do nothing else
    if ( !m_parentMenu )
        return;

#if wxUSE_ACCEL
    m_parentMenu->UpdateAccel(this);
#endif // wxUSE_ACCEL

    const UINT id = GetMSWId();
    HMENU hMenu = GetHMenuOf(m_parentMenu);
    if ( !hMenu )
        return;

    const UINT state = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
    if ( state == (UINT)-1 )
        return;

    // update the text of the native menu item
    WinStruct<MENUITEMINFO> info;

    // surprisingly, calling SetMenuItemInfo() with just MIIM_STRING doesn't
    // work as it resets the menu bitmap, so we need to first get the old item
    // state and then modify it
    const bool isLaterThanWin95 = wxGetWinVersion() > wxWinVersion_95;
    info.fMask = MIIM_STATE |
                 MIIM_ID |
                 MIIM_SUBMENU |
                 MIIM_CHECKMARKS |
                 MIIM_DATA;
    if ( isLaterThanWin95 )
        info.fMask |= MIIM_BITMAP | MIIM_FTYPE;
    else
        info.fMask |= MIIM_TYPE;
    if ( !::GetMenuItemInfo(hMenu, id, FALSE, &info) )
    {
        wxLogLastError(wxT("GetMenuItemInfo"));
        return;
    }

#if wxUSE_OWNER_DRAWN
    // Don't set the text for the owner drawn items, they don't use it and even
    // though setting it doesn't seem to actually do any harm under Windows 7,
    // avoid doing this relatively nonsensical operation just in case it does
    // break something on other, past or future, Windows versions.
    //
    // Notice that we do need to call SetMenuItemInfo() even for the ownerdrawn
    // items however as otherwise their size wouldn't be recalculated as
    // WM_MEASUREITEM wouldn't be sent and this could result in display
    // problems if the length of the menu item changed significantly.
    //
    // Also notice that we shouldn't use our IsOwnerDrawn() because it can be
    // true because it was set by e.g. SetBitmap(), even if the item wasn't
    // made owner drawn at Windows level.
    if ( !(state & MF_OWNERDRAW) )
#endif // wxUSE_OWNER_DRAWN
    {
        if ( isLaterThanWin95 )
            info.fMask |= MIIM_STRING;
        //else: MIIM_TYPE already specified
        info.dwTypeData = wxMSW_CONV_LPTSTR(m_text);
        info.cch = m_text.length();
    }

    if ( !::SetMenuItemInfo(hMenu, id, FALSE, &info) )
    {
        wxLogLastError(wxT("SetMenuItemInfo"));
    }
}
示例#7
0
void wxMenuItem::SetItemLabel(const wxString& txt)
{
    wxString text = txt;

    // don't do anything if label didn't change
    if ( m_text == txt )
        return;

    // wxMenuItemBase will do stock ID checks
    wxMenuItemBase::SetItemLabel(text);

    // the item can be not attached to any menu yet and SetItemLabel() is still
    // valid to call in this case and should do nothing else
    if ( !m_parentMenu )
        return;

#if wxUSE_ACCEL
    m_parentMenu->UpdateAccel(this);
#endif // wxUSE_ACCEL

    const UINT id = GetMSWId();
    HMENU hMenu = GetHMenuOf(m_parentMenu);
    if ( !hMenu || ::GetMenuState(hMenu, id, MF_BYCOMMAND) == (UINT)-1 )
        return;

#if wxUSE_OWNER_DRAWN
    if ( IsOwnerDrawn() )
    {
        // we don't need to do anything for owner drawn items, they will redraw
        // themselves using the new text the next time they're displayed
        return;
    }
#endif // owner drawn

    // update the text of the native menu item
    WinStruct<MENUITEMINFO> info;

    // surprisingly, calling SetMenuItemInfo() with just MIIM_STRING doesn't
    // work as it resets the menu bitmap, so we need to first get the old item
    // state and then modify it
    const bool isLaterThanWin95 = wxGetWinVersion() > wxWinVersion_95;
    info.fMask = MIIM_STATE |
                 MIIM_ID |
                 MIIM_SUBMENU |
                 MIIM_CHECKMARKS |
                 MIIM_DATA;
    if ( isLaterThanWin95 )
        info.fMask |= MIIM_BITMAP | MIIM_FTYPE;
    else
        info.fMask |= MIIM_TYPE;
    if ( !::GetMenuItemInfo(hMenu, id, FALSE, &info) )
    {
        wxLogLastError(wxT("GetMenuItemInfo"));
        return;
    }

    if ( isLaterThanWin95 )
        info.fMask |= MIIM_STRING;
    //else: MIIM_TYPE already specified
    info.dwTypeData = (LPTSTR)m_text.wx_str();
    info.cch = m_text.length();
    if ( !::SetMenuItemInfo(hMenu, id, FALSE, &info) )
    {
        wxLogLastError(wxT("SetMenuItemInfo"));
    }
}