Exemplo n.º 1
0
int wxDirDialog::ShowModal()
{
    WX_HOOK_MODAL_DIALOG();

    wxWindow* const parent = GetParent();
    WXHWND hWndParent = parent ? GetHwndOf(parent) : NULL;

    // Use IFileDialog under new enough Windows, it's more user-friendly.
    int rc;
#if wxUSE_IFILEDIALOG
    if ( wxGetWinVersion() >= wxWinVersion_Vista )
    {
        rc = ShowIFileDialog(hWndParent);
    }
    else
    {
        rc = wxID_NONE;
    }

    if ( rc == wxID_NONE )
#endif // wxUSE_IFILEDIALOG
    {
        rc = ShowSHBrowseForFolder(hWndParent);
    }

    // change current working directory if asked so
    if ( rc == wxID_OK && HasFlag(wxDD_CHANGE_DIR) )
        wxSetWorkingDirectory(m_path);

    return rc;
}
Exemplo n.º 2
0
bool wxMenuItem::MSWMustUseOwnerDrawn()
{
    // 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 ||
                                GetTextColour().IsOk() ||
                                GetBackgroundColour().IsOk() ||
                                GetFont().IsOk();

    // Windows XP or earlier don't display menu bitmaps bigger than
    // standard size correctly (they're truncated), so we must use
    // owner-drawn items to show them correctly there. OTOH Win7
    // doesn't seem to have any problems with even very large bitmaps
    // so don't use owner-drawn items unnecessarily there (Vista wasn't
    // actually tested but I assume it works as 7 rather than as XP).
    if ( !mustUseOwnerDrawn && winver < wxWinVersion_Vista )
    {
        const wxBitmap& bmpUnchecked = GetBitmap(false),
                        bmpChecked   = GetBitmap(true);

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

    return mustUseOwnerDrawn;
}
Exemplo n.º 3
0
    // Returns non-NULL theme only if we're using Win7-style tooltips.
    static wxUxThemeEngine* GetTooltipTheme()
    {
        // Even themed applications under XP still use "classic" tooltips.
        if ( wxGetWinVersion() <= wxWinVersion_XP )
            return NULL;

        return wxUxThemeEngine::GetIfActive();
    }
Exemplo n.º 4
0
void wxButton::DoSetAuthNeeded(bool show)
{
    // show/hide UAC symbol on Windows Vista and later
    if ( wxGetWinVersion() >= wxWinVersion_6 )
    {
        m_authNeeded = show;
        ::SendMessage(GetHwnd(), BCM_SETSHIELD, 0, show);
        InvalidateBestSize();
    }
}
Exemplo n.º 5
0
wxSize wxHyperlinkCtrl::DoGetBestClientSize() const
{
    // LM_GETIDEALSIZE only exists under Vista so use the generic version even
    // when using the native control under XP
    if ( !HasNativeHyperlinkCtrl() || (wxGetWinVersion() < wxWinVersion_6) )
        return wxGenericHyperlinkCtrl::DoGetBestClientSize();

    SIZE idealSize;
    ::SendMessage(m_hWnd, LM_GETIDEALSIZE, 0, (LPARAM)&idealSize);

    return wxSize(idealSize.cx, idealSize.cy);
}
Exemplo n.º 6
0
bool wxStaticBitmap::Create(wxWindow *parent,
                            wxWindowID id,
                            const wxGDIImage& bitmap,
                            const wxPoint& pos,
                            const wxSize& size,
                            long style,
                            const wxString& name)
{
    if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
        return false;

    // we may have either bitmap or icon: if a bitmap with mask is passed, we
    // will transform it to an icon ourselves because otherwise the mask will
    // be ignored by Windows
    m_isIcon = bitmap.IsKindOf(CLASSINFO(wxIcon));

    wxGDIImage *image = ConvertImage( bitmap );
    m_isIcon = image->IsKindOf( CLASSINFO(wxIcon) );

    // create the native control
    if ( !MSWCreateControl(_T("STATIC"), wxEmptyString, pos, size) )
    {
        // control creation failed
        return false;
    }

    // no need to delete the new image
    SetImageNoCopy(image);

    // GetBestSize will work properly now, so set the best size if needed
    SetInitialSize(size);

    // Win9x and 2000 don't draw correctly the images with alpha channel so we
    // need to draw them ourselves and it's easier to just always do it rather
    // than check if we have an image with alpha or not
    if ( wxGetWinVersion() <= wxWinVersion_2000 )
    {
	Connect(wxEVT_PAINT, wxPaintEventHandler(wxStaticBitmap::DoPaintManually));
    }

    return true;
}
Exemplo n.º 7
0
// returns the HBITMAP to use in MENUITEMINFO
HBITMAP wxMenuItem::GetHBitmapForMenu(bool checked)
{
    // Under versions of Windows older than Vista 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 inverts the bitmap for the selected
    //     item and this looks downright ugly
    //
    // So we prefer to instead draw it ourselves in MSWOnDrawItem().by using
    // HBMMENU_CALLBACK when inserting it
    //
    // However under Vista using HBMMENU_CALLBACK causes the entire menu to be
    // drawn using the classic theme instead of the current one and it does
    // handle transparency just fine so do use the real bitmap there
#if wxUSE_IMAGE
    if ( wxGetWinVersion() >= wxWinVersion_Vista )
    {
        wxBitmap bmp = GetBitmap(checked);
        if ( bmp.IsOk() )
        {
            // we must use PARGB DIB for the menu bitmaps so ensure that we do
            wxImage img(bmp.ConvertToImage());
            if ( !img.HasAlpha() )
            {
                img.InitAlpha();
                SetBitmap(img, checked);
            }

            return GetHbitmapOf(GetBitmap(checked));
        }
        //else: bitmap is not set
        return NULL;
    }
#endif // wxUSE_IMAGE

    return HBMMENU_CALLBACK;
}
Exemplo n.º 8
0
int wxDirDialog::ShowModal()
{
    WX_HOOK_MODAL_DIALOG();

    wxWindow* const parent = GetParent();
    WXHWND hWndParent = parent ? GetHwndOf(parent) : NULL;

    // Use IFileDialog under new enough Windows, it's more user-friendly.
    int rc;
#if wxUSE_IFILEDIALOG
    // While the new dialog is available under Vista, it may return a wrong
    // path there (see http://support.microsoft.com/kb/969885/en-us), so we
    // don't use it there by default. We could improve the version test to
    // allow its use if the comdlg32.dll version is greater than 6.0.6002.22125
    // as this means that the hotfix correcting this bug is installed.
    if ( wxGetWinVersion() > wxWinVersion_Vista )
    {
        rc = ShowIFileDialog(hWndParent);
    }
    else
    {
        rc = wxID_NONE;
    }

    if ( rc == wxID_NONE )
#endif // wxUSE_IFILEDIALOG
    {
        rc = ShowSHBrowseForFolder(hWndParent);
    }

    // change current working directory if asked so
    if ( rc == wxID_OK && HasFlag(wxDD_CHANGE_DIR) )
        wxSetWorkingDirectory(m_path);

    return rc;
}
Exemplo n.º 9
0
void wxStaticBox::PaintForeground(wxDC& dc, const RECT& rc)
{
    wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
    MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(*impl), 0);

    // when using XP themes, neither setting the text colour nor transparent
    // background mode doesn't change anything: the static box def window proc
    // still draws the label in its own colours, so we need to redraw the text
    // ourselves if we have a non default fg colour
    if ( m_hasFgCol && wxUxThemeEngine::GetIfActive() )
    {
        // draw over the text in default colour in our colour
        HDC hdc = GetHdcOf(*impl);
        ::SetTextColor(hdc, GetForegroundColour().GetPixel());

        const bool rtl = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft;
        if ( rtl )
            ::SetTextAlign(hdc, TA_RTLREADING | TA_RIGHT);

        // Get dimensions of the label
        const wxString label = GetLabel();

        // choose the correct font
        AutoHFONT font;
        SelectInHDC selFont;
        if ( m_hasFont )
        {
            selFont.Init(hdc, GetHfontOf(GetFont()));
        }
        else // no font set, use the one set by the theme
        {
            wxUxThemeHandle hTheme(this, L"BUTTON");
            if ( hTheme )
            {
                wxUxThemeFont themeFont;
                if ( wxUxThemeEngine::Get()->GetThemeFont
                                             (
                                                hTheme,
                                                hdc,
                                                BP_GROUPBOX,
                                                GBS_NORMAL,
                                                TMT_FONT,
                                                themeFont.GetPtr()
                                             ) == S_OK )
                {
                    font.Init(themeFont.GetLOGFONT());
                    if ( font )
                        selFont.Init(hdc, font);
                }
            }
        }

        // Get the font extent
        int width, height;
        dc.GetTextExtent(wxStripMenuCodes(label, wxStrip_Mnemonics),
                         &width, &height);

        int x;
        int y = height;

        // first we need to correctly paint the background of the label
        // as Windows ignores the brush offset when doing it
        //
        // FIXME: value of x is hardcoded as this is what it is on my system,
        //        no idea if it's true everywhere
        RECT dimensions = {0, 0, 0, y};
        if ( !rtl )
        {
            x = 9;
            dimensions.left = x;
            dimensions.right = x + width;
        }
        else
        {
            x = rc.right - 7;
            dimensions.left = x - width;
            dimensions.right = x;
        }

        // need to adjust the rectangle to cover all the label background
        dimensions.left -= 2;
        dimensions.right += 2;
        dimensions.bottom += 2;

        if ( UseBgCol() )
        {
            // our own background colour should be used for the background of
            // the label: this is consistent with the behaviour under pre-XP
            // systems (i.e. without visual themes) and generally makes sense
            wxBrush brush = wxBrush(GetBackgroundColour());
            wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
            ::FillRect(GetHdcOf(*impl), &dimensions, GetHbrushOf(brush));
        }
        else // paint parent background
        {
            PaintBackground(dc, dimensions);
        }

        UINT drawTextFlags = DT_SINGLELINE | DT_VCENTER;

        // determine the state of UI queues to draw the text correctly under XP
        // and later systems
        static const bool isXPorLater = wxGetWinVersion() >= wxWinVersion_XP;
        if ( isXPorLater )
        {
            if ( ::SendMessage(GetHwnd(), WM_QUERYUISTATE, 0, 0) &
                    UISF_HIDEACCEL )
            {
                drawTextFlags |= DT_HIDEPREFIX;
            }
        }

        // now draw the text
        if ( !rtl )
        {
            RECT rc2 = { x, 0, x + width, y };
            ::DrawText(hdc, label.t_str(), label.length(), &rc2,
                       drawTextFlags);
        }
        else // RTL
        {
            RECT rc2 = { x, 0, x - width, y };
            ::DrawText(hdc, label.t_str(), label.length(), &rc2,
                       drawTextFlags | DT_RTLREADING);
        }
    }
}
Exemplo n.º 10
0
WXLRESULT wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
    if ( nMsg == WM_NCHITTEST )
    {
        // This code breaks some other processing such as enter/leave tracking
        // so it's off by default.

        static int s_useHTClient = -1;
        if (s_useHTClient == -1)
            s_useHTClient = wxSystemOptions::GetOptionInt(wxT("msw.staticbox.htclient"));
        if (s_useHTClient == 1)
        {
            int xPos = GET_X_LPARAM(lParam);
            int yPos = GET_Y_LPARAM(lParam);

            ScreenToClient(&xPos, &yPos);

            // Make sure you can drag by the top of the groupbox, but let
            // other (enclosed) controls get mouse events also
            if ( yPos < 10 )
                return (long)HTCLIENT;
        }
    }

    if ( nMsg == WM_PRINTCLIENT )
    {
        // we have to process WM_PRINTCLIENT ourselves as otherwise child
        // windows' background (eg buttons in radio box) would never be drawn
        // unless we have a parent with non default background

        // so check first if we have one
        if ( !HandlePrintClient((WXHDC)wParam) )
        {
            // no, we don't, erase the background ourselves
            // (don't use our own) - see PaintBackground for explanation
            wxBrush brush(GetParent()->GetBackgroundColour());
            wxFillRect(GetHwnd(), (HDC)wParam, GetHbrushOf(brush));
        }

        return 0;
    }

    if ( nMsg == WM_UPDATEUISTATE )
    {
        // DefWindowProc() redraws just the static box text when it gets this
        // message and it does it using the standard (blue in standard theme)
        // colour and not our own label colour that we use in PaintForeground()
        // resulting in the label mysteriously changing the colour when e.g.
        // "Alt" is pressed anywhere in the window, see #12497.
        //
        // To avoid this we simply refresh the window forcing our own code
        // redrawing the label in the correct colour to be called. This is
        // inefficient but there doesn't seem to be anything else we can do.
        //
        // Notice that the problem is XP-specific and doesn't arise under later
        // systems.
        if ( m_hasFgCol && wxGetWinVersion() == wxWinVersion_XP )
            Refresh();
    }

    return wxControl::MSWWindowProc(nMsg, wParam, lParam);
}
Exemplo n.º 11
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 int itemPos = MSGetMenuItemPos();
    if ( itemPos == -1 )
        return;

    HMENU hMenu = GetHMenuOf(m_parentMenu);

    // 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, itemPos, TRUE, &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 ( !(info.fState & 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, itemPos, TRUE, &info) )
    {
        wxLogLastError(wxT("SetMenuItemInfo"));
    }
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
    WXLRESULT rc = 0;
    bool processed = false;

    switch ( message )
    {
        case WM_CLOSE:
            // if we can't close, tell the system that we processed the
            // message - otherwise it would close us
            processed = !Close();
            break;

        case WM_SIZE:
            processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
            break;

        case WM_COMMAND:
            {
                WORD id, cmd;
                WXHWND hwnd;
                UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
                              &id, &hwnd, &cmd);

                HandleCommand(id, cmd, (WXHWND)hwnd);

                // don't pass WM_COMMAND to the base class whether we processed
                // it or not because we did generate an event for it (our
                // HandleCommand() calls the base class version) and we must
                // not do it again or the handlers which skip the event would
                // be called twice
                processed = true;
            }
            break;

#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
#if wxUSE_MENUS
        case WM_INITMENUPOPUP:
            processed = HandleMenuPopup(wxEVT_MENU_OPEN, (WXHMENU)wParam);
            break;

        case WM_MENUSELECT:
            {
                WXWORD item, flags;
                WXHMENU hmenu;
                UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);

                processed = HandleMenuSelect(item, flags, hmenu);
            }
            break;

        case WM_EXITMENULOOP:
            // Under Windows 98 and 2000 and later we're going to get
            // WM_UNINITMENUPOPUP which will be used to generate this event
            // with more information (notably the menu that was closed) so we
            // only need this one under old Windows systems where the newer
            // event is never sent.
            if ( wxGetWinVersion() < wxWinVersion_98 )
                processed = HandleExitMenuLoop(wParam);
            break;

        case WM_UNINITMENUPOPUP:
            processed = HandleMenuPopup(wxEVT_MENU_CLOSE, (WXHMENU)wParam);
            break;
#endif // wxUSE_MENUS

        case WM_QUERYDRAGICON:
            {
                const wxIcon& icon = GetIcon();
                HICON hIcon = icon.IsOk() ? GetHiconOf(icon)
                                        : (HICON)GetDefaultIcon();
                rc = (WXLRESULT)hIcon;
                processed = rc != 0;
            }
            break;
#endif // !__WXMICROWIN__
    }

    if ( !processed )
        rc = wxFrameBase::MSWWindowProc(message, wParam, lParam);

    return rc;
}
Exemplo n.º 14
0
void wxAuiMSWTabArt::DrawTab(wxDC& dc,
    wxWindow* wnd,
    const wxAuiNotebookPage& page,
    const wxRect& in_rect,
    int close_button_state,
    wxRect* out_tab_rect,
    wxRect* out_button_rect,
    int* x_extent)
{
    if ( !IsThemed() )
    {
        wxAuiGenericTabArt::DrawTab(dc, wnd, page, in_rect, close_button_state, out_tab_rect, out_button_rect, x_extent);
        return;
    }

    if ( !m_closeBtnSize.IsFullySpecified() )
        InitSizes(wnd, dc);

    // figure out the size of the tab
    wxSize tabSize = GetTabSize(dc,
        wnd,
        page.caption,
        page.bitmap,
        page.active,
        close_button_state,
        x_extent);

    wxCoord tabHeight = tabSize.y;
    wxCoord tabWidth = tabSize.x;
    wxCoord tabX = in_rect.x;
    wxCoord tabY = 0;

    if (!page.active)
    {
        tabY += wnd->FromDIP(2);
        tabHeight -= wnd->FromDIP(2);
    }
    else
    {
        tabX -= wnd->FromDIP(2);
        tabWidth += wnd->FromDIP(4);
        tabHeight += 2;
    }

    int clipWidth = tabWidth;
    if ( tabX + clipWidth > in_rect.x + in_rect.width )
        clipWidth = (in_rect.x + in_rect.width) - tabX;
    dc.SetClippingRegion(tabX - wnd->FromDIP(2), tabY, clipWidth + wnd->FromDIP(4), tabHeight);


    // draw tab
    wxRect tabRect(tabX, tabY, tabWidth, tabHeight);

    int tabState;
    if ( page.active )
        tabState = TIS_SELECTED;
    else if ( page.hover )
        tabState = TIS_HOT;
    else
        tabState = TIS_NORMAL;

    wxUxThemeHandle hTabTheme(wnd, L"Tab");
    RECT tabR;
    wxCopyRectToRECT(tabRect, tabR);
    ::DrawThemeBackground(hTabTheme, GetHdcOf(dc.GetTempHDC()), TABP_TABITEM,
        tabState,
        &tabR, NULL);

    // Apparently, in at least some Windows 10 installations the call above
    // does not draw the left edge of the first tab and it needs to be drawn
    // separately, or it wouldn't be drawn at all.
    if ( tabX == GetIndentSize() )
    {
        ::DrawThemeBackground
            (
                hTabTheme,
                GetHdcOf(dc.GetTempHDC()),
                TABP_TABITEMLEFTEDGE,
                tabState,
                &tabR,
                NULL
            );
    }

    wxRect textRect = tabRect;
    if ( !page.active )
        textRect.Offset(0, wnd->FromDIP(1));
    if ( close_button_state != wxAUI_BUTTON_STATE_HIDDEN )
        textRect.width -= m_closeBtnSize.x + wnd->FromDIP(3);

    dc.SetFont(wnd->GetFont());
    dc.DrawLabel(page.caption, page.bitmap, textRect, wxALIGN_CENTRE);

    // draw focus rectangle
    if ( page.active && (wnd->FindFocus() == wnd) )
    {
        wxRect focusRect = tabRect;
        focusRect.Deflate(wnd->FromDIP(2));

        wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
    }

    // draw close button
    if ( close_button_state != wxAUI_BUTTON_STATE_HIDDEN )
    {
        wxUxThemeHandle hToolTipTheme(wnd, L"TOOLTIP");

        int btnState;
        if ( close_button_state == wxAUI_BUTTON_STATE_HOVER )
            btnState = TTCS_HOT;
        else if ( close_button_state == wxAUI_BUTTON_STATE_PRESSED )
            btnState = TTCS_PRESSED;
        else
            btnState = TTCS_NORMAL;

        int offsetY = tabY;
        if ( wxGetWinVersion() < wxWinVersion_Vista )
            offsetY++; // WinXP theme needs a little more padding

        wxRect rect(tabX + tabWidth - m_closeBtnSize.x - wnd->FromDIP(4),
            offsetY + (tabHeight / 2) - (m_closeBtnSize.y / 2),
            m_closeBtnSize.x,
            m_closeBtnSize.y);

        RECT btnR;
        wxCopyRectToRECT(rect, btnR);
        ::DrawThemeBackground(hToolTipTheme, GetHdcOf(dc.GetTempHDC()), TTP_CLOSE, btnState, &btnR, NULL);

        if ( out_button_rect )
            *out_button_rect = rect;
    }

    *out_tab_rect = wxRect(tabX, tabY, tabWidth, tabHeight);

    dc.DestroyClippingRegion();
}
Exemplo n.º 15
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"));
    }
}
Exemplo n.º 16
0
bool wxMSWOwnerDrawnButtonBase::MSWDrawButton(WXDRAWITEMSTRUCT *item)
{
    DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)item;

    if ( !MSWIsOwnerDrawn() || dis->CtlType != ODT_BUTTON )
        return false;

    // shall we draw a focus rect?
    const bool isFocused = m_isPressed || m_win->HasFocus();

    int flags = MSWGetButtonCheckedFlag();

    if ( dis->itemState & ODS_SELECTED )
        flags |= wxCONTROL_SELECTED | wxCONTROL_PRESSED;

    if ( !m_win->IsEnabled() )
        flags |= wxCONTROL_DISABLED;

    if ( m_isPressed )
        flags |= wxCONTROL_PRESSED;

    if ( wxFindWindowAtPoint(wxGetMousePosition()) == m_win )
        flags |= wxCONTROL_CURRENT;


    // calculate the rectangles for the button itself and the label
    HDC hdc = dis->hDC;
    const RECT& rect = dis->rcItem;

    // calculate the rectangles for the button itself and the label
    const wxSize bestSize = m_win->GetBestSize();
    RECT rectButton,
         rectLabel;
    rectLabel.top = rect.top + (rect.bottom - rect.top - bestSize.y) / 2;
    rectLabel.bottom = rectLabel.top + bestSize.y;

    // choose the values consistent with those used for native, non
    // owner-drawn, buttons
    static const int MARGIN = 3;
    int CXMENUCHECK = ::GetSystemMetrics(SM_CXMENUCHECK) + 1;

    // the buttons were even bigger under Windows XP
    if ( wxGetWinVersion() < wxWinVersion_6 )
        CXMENUCHECK += 2;

    // The space between the button and the label
    // is included in the button bitmap.
    const int buttonSize = wxMin(CXMENUCHECK - MARGIN, m_win->GetSize().y);
    rectButton.top = rect.top + (rect.bottom - rect.top - buttonSize) / 2;
    rectButton.bottom = rectButton.top + buttonSize;

    const bool isRightAligned = m_win->HasFlag(wxALIGN_RIGHT);
    if ( isRightAligned )
    {
        rectLabel.right = rect.right - CXMENUCHECK;
        rectLabel.left = rect.left;

        rectButton.left = rectLabel.right + ( CXMENUCHECK + MARGIN - buttonSize ) / 2;
        rectButton.right = rectButton.left + buttonSize;
    }
    else // normal, left-aligned button
    {
        rectButton.left = rect.left + ( CXMENUCHECK - MARGIN - buttonSize ) / 2;
        rectButton.right = rectButton.left + buttonSize;

        rectLabel.left = rect.left + CXMENUCHECK;
        rectLabel.right = rect.right;
    }

    // Erase the background.
    ::FillRect(hdc, &rect, m_win->MSWGetBgBrush(hdc));

    // draw the button itself
    wxDCTemp dc(hdc);

    MSWDrawButtonBitmap(dc, wxRectFromRECT(rectButton), flags);

    // draw the text
    const wxString& label = m_win->GetLabel();

    // first we need to measure it
    UINT fmt = DT_NOCLIP;

    // drawing underlying doesn't look well with focus rect (and the native
    // control doesn't do it)
    if ( isFocused )
        fmt |= DT_HIDEPREFIX;
    if ( isRightAligned )
        fmt |= DT_RIGHT;
    // TODO: also use DT_HIDEPREFIX if the system is configured so

    // we need to get the label real size first if we have to draw a focus rect
    // around it
    if ( isFocused )
    {
        RECT oldLabelRect = rectLabel; // needed if right aligned

        if ( !::DrawText(hdc, label.t_str(), label.length(), &rectLabel,
                         fmt | DT_CALCRECT) )
        {
            wxLogLastError(wxT("DrawText(DT_CALCRECT)"));
        }

        if ( isRightAligned )
        {
            // move the label rect to the right
            const int labelWidth = rectLabel.right - rectLabel.left;
            rectLabel.right = oldLabelRect.right;
            rectLabel.left = rectLabel.right - labelWidth;
        }
    }

    if ( flags & wxCONTROL_DISABLED )
    {
        ::SetTextColor(hdc, ::GetSysColor(COLOR_GRAYTEXT));
    }

    if ( !::DrawText(hdc, label.t_str(), label.length(), &rectLabel, fmt) )
    {
        wxLogLastError(wxT("DrawText()"));
    }

    // finally draw the focus
    if ( isFocused )
    {
        rectLabel.left--;
        rectLabel.right++;
        if ( !::DrawFocusRect(hdc, &rectLabel) )
        {
            wxLogLastError(wxT("DrawFocusRect()"));
        }
    }

    return true;
}
Exemplo n.º 17
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
        }
Exemplo n.º 18
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;
    }

    // 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;

#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. Later we might want to use a boolean in the
    // wxMenu to avoid search. Also we might make this fix unnecessary by
    // getting the correct margin using NONCLIENTMETRICS.
    static const wxWinVersion winver = wxGetWinVersion();
    if ( winver < wxWinVersion_XP &&
            !pItem->IsOwnerDrawn() && !pItem->IsSeparator() )
    {
        // Check if any other items are ownerdrawn, and make ownerdrawn if so
        wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
        while (node)
        {
            if (node->GetData()->IsOwnerDrawn())
            {
                pItem->SetOwnerDrawn(true);
                break;
            }
            node = node->GetNext();
        }
    }
#endif // wxUSE_OWNER_DRAWN

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
#ifndef __DMC__
        // 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
        bool mustUseOwnerDrawn = winver < wxWinVersion_98 ||
                                 pItem->GetTextColour().Ok() ||
                                 pItem->GetBackgroundColour().Ok() ||
                                 pItem->GetFont().Ok();
        if ( !mustUseOwnerDrawn )
        {
            const wxBitmap& bmpUnchecked = pItem->GetBitmap(false),
                            bmpChecked = pItem->GetBitmap(true);
            if ( (bmpUnchecked.Ok() && !IsLessThanStdSize(bmpUnchecked)) ||
                    (bmpChecked.Ok() && !IsLessThanStdSize(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;

            if ( pItem->GetBitmap().IsOk() )
            {
                mii.fMask |= MIIM_BITMAP;
                mii.hbmpItem = GetHBitmapForMenu(pItem);
            }

            if ( pItem->IsCheckable() )
            {
                mii.fMask |= MIIM_CHECKMARKS;
                mii.hbmpChecked = GetHBitmapForMenu(pItem, true);
                mii.hbmpUnchecked = GetHBitmapForMenu(pItem, false);
            }

            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->ResetOwnerDrawn();
            }
        }
#endif // __DMC__

        if ( !ok )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;
        }
    }
    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;
        }
    }


    // if we just appended the title, highlight it
    if ( id == 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;
}