X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bec9bf3e20e07cfb3874069acce98aa2e898b8dc..43f4e852a1b2ac37c3db6a2b87315192ac549191:/src/msw/toolbar.cpp diff --git a/src/msw/toolbar.cpp b/src/msw/toolbar.cpp index 5dd2f917ff..8052cec705 100644 --- a/src/msw/toolbar.cpp +++ b/src/msw/toolbar.cpp @@ -127,6 +127,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged) + EVT_ERASE_BACKGROUND(wxToolBar::OnEraseBackground) END_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -340,7 +341,10 @@ bool wxToolBar::Create(wxWindow *parent, // in WM_ERASEBKGND too (by default this won't be done but if the toolbar // has a non default background colour, then it would be used in both // places resulting in flicker) - SetBackgroundStyle(wxBG_STYLE_PAINT); + if (wxApp::GetComCtl32Version() >= 600) + { + SetBackgroundStyle(wxBG_STYLE_PAINT); + } return true; } @@ -405,11 +409,7 @@ void wxToolBar::Recreate() m_hBitmap = 0; } - if ( m_disabledImgList ) - { - delete m_disabledImgList; - m_disabledImgList = NULL; - } + wxDELETE(m_disabledImgList); Realize(); } @@ -572,14 +572,18 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) // get the size of the button we're going to delete const RECT r = wxGetTBItemRect(GetHwnd(), pos); - int width = r.right - r.left; + int delta = IsVertical() ? r.bottom - r.top : r.right - r.left; if ( tool->IsControl() ) { nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount(); - width *= nButtonsToDelete; + + if ( !IsVertical() ) + delta *= nButtonsToDelete; } + m_totalFixedSize -= delta; + // do delete all buttons m_nButtons -= nButtonsToDelete; while ( nButtonsToDelete-- > 0 ) @@ -592,14 +596,45 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) } } - // 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() ) + // and finally rearrange the tools + + // search for any stretch spacers before the removed tool + bool hasPrecedingStrechables = false; + for ( wxToolBarToolsList::compatibility_iterator nodeStch = m_tools.GetFirst(); + nodeStch != node; nodeStch = nodeStch->GetNext() ) { - wxToolBarTool *tool2 = (wxToolBarTool*)node->GetData(); - if ( tool2->IsControl() ) + if ( ((wxToolBarTool*)nodeStch->GetData())->IsStretchable() ) { - tool2->MoveBy(-width); + hasPrecedingStrechables = true; + break; + } + } + + if ( hasPrecedingStrechables ) + { + // if the removed tool is preceded by stretch spacers + // just redistribute the space + UpdateStretchableSpacersSize(); + } + else + { + // reposition all the controls after this button but before any + // stretch spacer (the toolbar takes care of all normal items) + for ( /* node -> first after deleted */ ; node; node = node->GetNext() ) + { + wxToolBarTool *tool2 = (wxToolBarTool*)node->GetData(); + + if ( tool2->IsControl() ) + { + tool2->MoveBy(-delta); + } + + // if a stretch spacer is found just redistribute the available space + else if ( tool2->IsStretchable() ) + { + UpdateStretchableSpacersSize(); + break; + } } } @@ -610,11 +645,7 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) void wxToolBar::CreateDisabledImageList() { - if (m_disabledImgList != NULL) - { - delete m_disabledImgList; - m_disabledImgList = NULL; - } + wxDELETE(m_disabledImgList); // as we can't use disabled image list with older versions of comctl32.dll, // don't even bother creating it @@ -626,12 +657,13 @@ void wxToolBar::CreateDisabledImageList() { wxToolBarToolBase *tool = node->GetData(); wxBitmap bmpDisabled = tool->GetDisabledBitmap(); - if ( bmpDisabled.Ok() ) + if ( bmpDisabled.IsOk() ) { + const wxSize sizeBitmap = bmpDisabled.GetSize(); m_disabledImgList = new wxImageList ( - m_defaultWidth, - m_defaultHeight, + sizeBitmap.x, + sizeBitmap.y, bmpDisabled.GetMask() != NULL, GetToolsCount() ); @@ -751,7 +783,7 @@ bool wxToolBar::Realize() const int w = bmp.GetWidth(); const int h = bmp.GetHeight(); - if ( bmp.Ok() ) + if ( bmp.IsOk() ) { int xOffset = wxMax(0, (m_defaultWidth - w)/2); int yOffset = wxMax(0, (m_defaultHeight - h)/2); @@ -769,7 +801,7 @@ bool wxToolBar::Realize() { wxBitmap bmpDisabled = tool->GetDisabledBitmap(); #if wxUSE_IMAGE && wxUSE_WXDIB - if ( !bmpDisabled.Ok() ) + if ( !bmpDisabled.IsOk() ) { // no disabled bitmap specified but we still need to // fill the space in the image list with something, so @@ -953,7 +985,7 @@ bool wxToolBar::Realize() { const wxString& label = tool->GetLabel(); if ( !label.empty() ) - button.iString = (INT_PTR)label.wx_str(); + button.iString = (INT_PTR) wxMSW_CONV_LPCTSTR(label); } button.idCommand = tool->GetId(); @@ -1021,6 +1053,14 @@ bool wxToolBar::Realize() break; } + // Instead of using fixed widths for all buttons, size them + // automatically according to the size of their bitmap and text + // label, if present. This particularly matters for toolbars + // with the wxTB_HORZ_LAYOUT style: they look hideously ugly + // without autosizing when the labels have even slightly + // different lengths. + button.fsStyle |= TBSTYLE_AUTOSIZE; + bitmapId++; break; } @@ -1219,13 +1259,13 @@ void wxToolBar::UpdateStretchableSpacersSize() // reduce their size if there is not enough place for all tools const int totalSize = IsVertical() ? GetClientSize().y : GetClientSize().x; const int extraSize = totalSize - m_totalFixedSize; - const int sizeSpacer = extraSize > 0 ? extraSize / numSpaces : 0; + const int sizeSpacer = extraSize > 0 ? extraSize / numSpaces : 1; // the last spacer should consume all remaining space if we have too much // of it (which can be greater than sizeSpacer because of the rounding) const int sizeLastSpacer = extraSize > 0 ? extraSize - (numSpaces - 1)*sizeSpacer - : 0; + : 1; // cumulated offset by which we need to move all the following controls to // the right: while the toolbar takes care of the normal items, we must @@ -1303,7 +1343,7 @@ bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id_) // Without the two lines of code below, if the toolbar was repainted during // OnLeftClick(), then it could end up without the tool bitmap temporarily // (see http://lists.nongnu.org/archive/html/lmi/2008-10/msg00014.html). - // The Update() call bellow ensures that this won't happen, by repainting + // The Update() call below ensures that this won't happen, by repainting // invalidated areas of the toolbar immediately. // // To complicate matters, the tool would be drawn in depressed state (this @@ -1330,7 +1370,7 @@ bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id_) ::SendMessage(GetHwnd(), TB_SETSTATE, id, MAKELONG(state, 0)); // OnLeftClick() can veto the button state change - for buttons which - // may be toggled only, of couse + // may be toggled only, of course. if ( !allowLeftClick && tool->CanBeToggled() ) { // revert back @@ -1651,6 +1691,15 @@ void wxToolBar::OnMouseEvent(wxMouseEvent& event) } } +// This handler is needed to fix problems with painting the background of +// toolbar icons with comctl32.dll < 6.0. +void wxToolBar::OnEraseBackground(wxEraseEvent& event) +{ +#ifdef wxHAS_MSW_BACKGROUND_ERASE_HOOK + MSWDoEraseBackground(event.GetDC()->GetHDC()); +#endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK +} + bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam) { // wait until we have some tools @@ -1729,10 +1778,18 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) { // for some reason TB_GETITEMRECT returns a rectangle 1 pixel // shorter than the full window size (at least under Windows 7) - // but we need to erase the full height below + // but we need to erase the full width/height below RECT rcItem = wxGetTBItemRect(GetHwnd(), toolIndex); - rcItem.top = 0; - rcItem.bottom = rectTotal.height; + if ( IsVertical() ) + { + rcItem.left = 0; + rcItem.right = rectTotal.width; + } + else + { + rcItem.top = 0; + rcItem.bottom = rectTotal.height; + } rgnDummySeps.Union(wxRectFromRECT(rcItem)); } @@ -1744,18 +1801,15 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) } } - if ( !rgnDummySeps.IsOk() ) + if ( rgnDummySeps.IsOk() ) { - // don't interfere with toolbar default painting at all if we don't - // need to -- and we don't if we have no dummy separators at all - return false; - } - - // exclude the area occupied by the controls and stretchable spaces from - // the update region to prevent the toolbar from drawing separators in it - if ( !::ValidateRgn(GetHwnd(), GetHrgnOf(rgnDummySeps)) ) - { - wxLogLastError(wxT("ValidateRgn()")); + // exclude the area occupied by the controls and stretchable spaces + // from the update region to prevent the toolbar from drawing + // separators in it + if ( !::ValidateRgn(GetHwnd(), GetHrgnOf(rgnDummySeps)) ) + { + wxLogLastError(wxT("ValidateRgn()")); + } } // still let the native control draw everything else normally but set up a @@ -1779,11 +1833,14 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) GetParent()->MSWSetEraseBgHook(NULL); - // erase the dummy separators region ourselves now as nobody painted over - // them - WindowHDC hdc(GetHwnd()); - ::SelectClipRgn(hdc, GetHrgnOf(rgnDummySeps)); - MSWDoEraseBackground(hdc); + if ( rgnDummySeps.IsOk() ) + { + // erase the dummy separators region ourselves now as nobody painted + // over them + WindowHDC hdc(GetHwnd()); + ::SelectClipRgn(hdc, GetHrgnOf(rgnDummySeps)); + MSWDoEraseBackground(hdc); + } return true; } @@ -1807,7 +1864,7 @@ WXHBRUSH wxToolBar::MSWGetToolbarBgBrush() wxBrush * const brush = wxTheBrushList->FindOrCreateBrush(colBg); - return brush ? brush->GetResourceHandle() : 0; + return brush ? static_cast(brush->GetResourceHandle()) : 0; } WXHBRUSH wxToolBar::MSWGetBgBrushForChild(WXHDC hDC, wxWindowMSW *child)