tbar95.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,707 行 · 第 1/4 页

CPP
1,707
字号
    // Realize() later
    tool->Attach(this);

    InvalidateBestSize();
    return true;
}

bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
{
    // the main difficulty we have here is with the controls in the toolbars:
    // as we (sometimes) use several separators to cover up the space used by
    // them, the indices are not the same for us and the toolbar

    // first determine the position of the first button to delete: it may be
    // different from pos if we use several separators to cover the space used
    // by a control
    wxToolBarToolsList::compatibility_iterator node;
    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
    {
        wxToolBarToolBase *tool2 = node->GetData();
        if ( tool2 == tool )
        {
            // let node point to the next node in the list
            node = node->GetNext();

            break;
        }

        if ( tool2->IsControl() )
        {
            pos += ((wxToolBarTool *)tool2)->GetSeparatorsCount() - 1;
        }
    }

    // now determine the number of buttons to delete and the area taken by them
    size_t nButtonsToDelete = 1;

    // get the size of the button we're going to delete
    RECT r;
    if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) )
    {
        wxLogLastError(_T("TB_GETITEMRECT"));
    }

    int width = r.right - r.left;

    if ( tool->IsControl() )
    {
        nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount();
        width *= nButtonsToDelete;
        tool->GetControl()->Destroy();
    }

    // do delete all buttons
    m_nButtons -= nButtonsToDelete;
    while ( nButtonsToDelete-- > 0 )
    {
        if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) )
        {
            wxLogLastError(wxT("TB_DELETEBUTTON"));

            return false;
        }
    }

    tool->Detach();

    // and finally reposition all the controls after this button (the toolbar
    // takes care of all normal items)
    for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
    {
        wxToolBarToolBase *tool2 = node->GetData();
        if ( tool2->IsControl() )
        {
            int x;
            wxControl *control = tool2->GetControl();
            control->GetPosition(&x, NULL);
            control->Move(x - width, wxDefaultCoord);
        }
    }

    InvalidateBestSize();
    return true;
}

void wxToolBar::CreateDisabledImageList()
{
    // as we can't use disabled image list with older versions of comctl32.dll,
    // don't even bother creating it
    if ( wxTheApp->GetComCtl32Version() >= 470 )
    {
        // search for the first disabled button img in the toolbar, if any
        for ( wxToolBarToolsList::compatibility_iterator
                node = m_tools.GetFirst(); node; node = node->GetNext() )
        {
            wxToolBarToolBase *tool = node->GetData();
            wxBitmap bmpDisabled = tool->GetDisabledBitmap();
            if ( bmpDisabled.Ok() )
            {
                m_disabledImgList = new wxImageList
                                        (
                                            m_defaultWidth,
                                            m_defaultHeight,
                                            bmpDisabled.GetMask() != NULL,
                                            GetToolsCount()
                                        );
                return;
            }
        }

        // we don't have any disabled bitmaps
    }

    m_disabledImgList = NULL;
}

bool wxToolBar::Realize()
{
    const size_t nTools = GetToolsCount();
    if ( nTools == 0 )
    {
        // nothing to do
        return true;
    }

    const bool isVertical = HasFlag(wxTB_VERTICAL);

    bool doRemap, doRemapBg, doTransparent;
#ifdef __WXWINCE__
    doRemapBg = false;
    doRemap = false;
    doTransparent = false;
#else
    if (wxSystemOptions::GetOptionInt(wxT("msw.remap")) == 2)
    {
        doRemapBg = doRemap = false;
        doTransparent = true;
    }
    else
    {   doRemap = !wxSystemOptions::HasOption(wxT("msw.remap"))
            || wxSystemOptions::GetOptionInt(wxT("msw.remap")) == 1;
        doRemapBg = !doRemap;
        doTransparent = false;
    }
#endif

    // delete all old buttons, if any
    for ( size_t pos = 0; pos < m_nButtons; pos++ )
    {
        if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) )
        {
            wxLogDebug(wxT("TB_DELETEBUTTON failed"));
        }
    }

    // First, add the bitmap: we use one bitmap for all toolbar buttons
    // ----------------------------------------------------------------

    wxToolBarToolsList::compatibility_iterator node;
    int bitmapId = 0;

    wxSize sizeBmp;
    if ( HasFlag(wxTB_NOICONS) )
    {
        // no icons, don't leave space for them
        sizeBmp.x =
        sizeBmp.y = 0;
    }
    else // do show icons
    {
        // if we already have a bitmap, we'll replace the existing one --
        // otherwise we'll install a new one
        HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap;

        sizeBmp.x = m_defaultWidth;
        sizeBmp.y = m_defaultHeight;

        const wxCoord totalBitmapWidth  = m_defaultWidth *
                                          wx_truncate_cast(wxCoord, nTools),
                      totalBitmapHeight = m_defaultHeight;

        // Create a bitmap and copy all the tool bitmaps to it
        wxMemoryDC dcAllButtons;
        wxBitmap bitmap(totalBitmapWidth, totalBitmapHeight);
        dcAllButtons.SelectObject(bitmap);
#ifdef __WXWINCE__
        dcAllButtons.SetBackground(wxBrush(wxColour(192,192,192)));
#else
        if (doTransparent)
            dcAllButtons.SetBackground(*wxTRANSPARENT_BRUSH);
        else
            dcAllButtons.SetBackground(wxBrush(GetBackgroundColour()));
#endif
        dcAllButtons.Clear();

        m_hBitmap = bitmap.GetHBITMAP();
        HBITMAP hBitmap = (HBITMAP)m_hBitmap;

#ifndef __WXWINCE__
        if (doRemapBg)
        {
            dcAllButtons.SelectObject(wxNullBitmap);

            // Even if we're not remapping the bitmap
            // content, we still have to remap the background.
            hBitmap = (HBITMAP)MapBitmap((WXHBITMAP) hBitmap,
                totalBitmapWidth, totalBitmapHeight);

            dcAllButtons.SelectObject(bitmap);


        }
#endif // !__WXWINCE__

        // the button position
        wxCoord x = 0;

        // the number of buttons (not separators)
        int nButtons = 0;

        CreateDisabledImageList();
        for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
        {
            wxToolBarToolBase *tool = node->GetData();
            if ( tool->IsButton() )
            {
                const wxBitmap& bmp = tool->GetNormalBitmap();

                const int w = bmp.GetWidth();
                const int h = bmp.GetHeight();

                if ( bmp.Ok() )
                {
                    int xOffset = wxMax(0, (m_defaultWidth - w)/2);
                    int yOffset = wxMax(0, (m_defaultHeight - h)/2);

                    // notice the last parameter: do use mask
                    dcAllButtons.DrawBitmap(bmp, x + xOffset, yOffset, true);
                }
                else
                {
                    wxFAIL_MSG( _T("invalid tool button bitmap") );
                }

                // also deal with disabled bitmap if we want to use them
                if ( m_disabledImgList )
                {
                    wxBitmap bmpDisabled = tool->GetDisabledBitmap();
#if wxUSE_IMAGE && wxUSE_WXDIB
                    if ( !bmpDisabled.Ok() )
                    {
                        // no disabled bitmap specified but we still need to
                        // fill the space in the image list with something, so
                        // we grey out the normal bitmap
                        wxImage imgGreyed;
                        wxCreateGreyedImage(bmp.ConvertToImage(), imgGreyed);

                        // we need to have light grey background colour for
                        // MapBitmap() to work correctly
                        for ( int y = 0; y < h; y++ )
                        {
                            for ( int x = 0; x < w; x++ )
                            {
                                if ( imgGreyed.IsTransparent(x, y) )
                                    imgGreyed.SetRGB(x, y,
                                                     wxLIGHT_GREY->Red(),
                                                     wxLIGHT_GREY->Green(),
                                                     wxLIGHT_GREY->Blue());
                            }
                        }

                        bmpDisabled = wxBitmap(imgGreyed);
                    }
#endif // wxUSE_IMAGE

                    MapBitmap(bmpDisabled.GetHBITMAP(), w, h);

                    m_disabledImgList->Add(bmpDisabled);
                }

                // still inc width and number of buttons because otherwise the
                // subsequent buttons will all be shifted which is rather confusing
                // (and like this you'd see immediately which bitmap was bad)
                x += m_defaultWidth;
                nButtons++;
            }
        }

        dcAllButtons.SelectObject(wxNullBitmap);

        // don't delete this HBITMAP!
        bitmap.SetHBITMAP(0);

        if (doRemap)
        {
            // Map to system colours
            hBitmap = (HBITMAP)MapBitmap((WXHBITMAP) hBitmap,
                totalBitmapWidth, totalBitmapHeight);


        }

        bool addBitmap = true;

        if ( oldToolBarBitmap )
        {
#ifdef TB_REPLACEBITMAP
            if ( wxApp::GetComCtl32Version() >= 400 )
            {
                TBREPLACEBITMAP replaceBitmap;
                replaceBitmap.hInstOld = NULL;
                replaceBitmap.hInstNew = NULL;
                replaceBitmap.nIDOld = (UINT) oldToolBarBitmap;
                replaceBitmap.nIDNew = (UINT) hBitmap;
                replaceBitmap.nButtons = nButtons;
                if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP,
                                    0, (LPARAM) &replaceBitmap) )
                {
                    wxFAIL_MSG(wxT("Could not replace the old bitmap"));
                }

                ::DeleteObject(oldToolBarBitmap);

                // already done
                addBitmap = false;
            }
            else
#endif // TB_REPLACEBITMAP
            {
                // we can't replace the old bitmap, so we will add another one
                // (awfully inefficient, but what else to do?) and shift the bitmap
                // indices accordingly
                addBitmap = true;

                bitmapId = m_nButtons;
            }
        }

        if ( addBitmap ) // no old bitmap or we can't replace it
        {
            TBADDBITMAP addBitmap;
            addBitmap.hInst = 0;
            addBitmap.nID = (UINT) hBitmap;
            if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP,
                               (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 )
            {
                wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
            }
        }

        if ( m_disabledImgList )
        {
            HIMAGELIST oldImageList = (HIMAGELIST)
                ::SendMessage(GetHwnd(),
                              TB_SETDISABLEDIMAGELIST,
                              0,
                              (LPARAM)GetHimagelistOf(m_disabledImgList));

            // delete previous image list if any
            if ( oldImageList )
                ::DeleteObject( oldImageList );
        }
    }

    // don't call SetToolBitmapSize() as we don't want to change the values of
    // m_defaultWidth/Height
    if ( !::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0,
                        MAKELONG(sizeBmp.x, sizeBmp.y)) )
    {
        wxLogLastError(_T("TB_SETBITMAPSIZE"));
    }

    // Next add the buttons and separators
    // -----------------------------------

    TBBUTTON *buttons = new TBBUTTON[nTools];

    // this array will hold the indices of all controls in the toolbar
    wxArrayInt controlIds;

    bool lastWasRadio = false;
    int i = 0;
    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
    {
        wxToolBarToolBase *tool = node->GetData();

        // don't add separators to the vertical toolbar with old comctl32.dll
        // versions as they didn't handle this properly
        if ( isVertical && tool->IsSeparator() &&
                wxApp::GetComCtl32Version() <= 472 )
        {
            continue;
        }


        TBBUTTON& button = buttons[i];

        wxZeroMemory(button);

        bool isRadio = false;
        switch ( tool->GetStyle() )
        {
            case wxTOOL_STYLE_CONTROL:
                button.idCommand = tool->GetId();
                // fall through: create just a separator too

            case wxTOOL_STYLE_SEPARATOR:
                button.fsState = TBSTATE_ENABLED;
                button.fsStyle = TBSTYLE_SEP;
                break;

            case wxTOOL_STYLE_BUTTON:
                if ( !HasFlag(wxTB_NOICONS) )
                    button.iBitmap = bitmapId;

                if ( HasFlag(wxTB_TEXT) )
                {
                    const wxString& label = tool->GetLabel();
                    if ( !label.empty() )
                    {
                        button.iString = (int)label.c_str();
                    }
                }

                button.idCommand = tool->GetId();

                if ( tool->IsEnabled() )

⌨️ 快捷键说明

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