X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/24bc71f48bdf755884649c5ff15136adac300694..65fd2fc2616552e4204223b7c2b69d9bc87c1f2d:/src/msw/tbar95.cpp diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index 64a3802e26..54547adf94 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -40,6 +40,7 @@ #include "wx/control.h" #include "wx/app.h" // for GetComCtl32Version #include "wx/image.h" + #include "wx/stattext.h" #endif #include "wx/sysopt.h" @@ -148,14 +149,38 @@ public: clientData, shortHelp, longHelp) { m_nSepCount = 0; + m_staticText = 0; } - wxToolBarTool(wxToolBar *tbar, wxControl *control) - : wxToolBarToolBase(tbar, control) + wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label) + : wxToolBarToolBase(tbar, control, label) { + if ( IsControl() && !m_label.empty() ) + { + // create a control to render the control's label + m_staticText = new wxStaticText + ( + m_tbar, + wxID_ANY, + m_label, + wxDefaultPosition, + wxDefaultSize, + wxALIGN_CENTRE | wxST_NO_AUTORESIZE + ); + } + else // no label + { + m_staticText = NULL; + } + m_nSepCount = 1; } + virtual ~wxToolBarTool() + { + delete m_staticText; + } + virtual void SetLabel(const wxString& label) { if ( label == m_label ) @@ -163,12 +188,23 @@ public: wxToolBarToolBase::SetLabel(label); + if ( m_staticText ) + m_staticText->SetLabel(label); + // we need to update the label shown in the toolbar because it has a // pointer to the internal buffer of the old label // // TODO: use TB_SETBUTTONINFO } + wxStaticText* GetStaticText() + { + wxASSERT_MSG( IsControl(), + _T("only makes sense for embedded control tools") ); + + return m_staticText; + } + // set/get the number of separators which we use to cover the space used by // a control in the toolbar void SetSeparatorsCount(size_t count) { m_nSepCount = count; } @@ -176,6 +212,7 @@ public: private: size_t m_nSepCount; + wxStaticText *m_staticText; DECLARE_NO_COPY_CLASS(wxToolBarTool) }; @@ -201,9 +238,10 @@ wxToolBarToolBase *wxToolBar::CreateTool(int id, clientData, shortHelp, longHelp); } -wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control) +wxToolBarToolBase * +wxToolBar::CreateTool(wxControl *control, const wxString& label) { - return new wxToolBarTool(this, control); + return new wxToolBarTool(this, control, label); } // ---------------------------------------------------------------------------- @@ -220,7 +258,7 @@ void wxToolBar::Init() m_defaultWidth = DEFAULTBITMAPX; m_defaultHeight = DEFAULTBITMAPY; - m_pInTool = 0; + m_pInTool = NULL; } bool wxToolBar::Create(wxWindow *parent, @@ -265,6 +303,11 @@ bool wxToolBar::MSWCreateToolbar(const wxPoint& pos, const wxSize& size) // toolbar-specific post initialisation ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); +#ifdef TB_SETEXTENDEDSTYLE + if ( wxApp::GetComCtl32Version() >= 471 ) + ::SendMessage(GetHwnd(), TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS); +#endif + return true; } @@ -362,6 +405,9 @@ wxSize wxToolBar::DoGetBestSize() const sizeBest.y = size.cy; } + if (!IsVertical() && !(GetWindowStyle() & wxTB_NODIVIDER)) + sizeBest.y += 1; + CacheBestSize(sizeBest); return sizeBest; @@ -489,13 +535,16 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) // takes care of all normal items) for ( /* node -> first after deleted */ ; node; node = node->GetNext() ) { - wxToolBarToolBase *tool2 = node->GetData(); + wxToolBarTool *tool2 = (wxToolBarTool*)node->GetData(); if ( tool2->IsControl() ) { int x; wxControl *control = tool2->GetControl(); control->GetPosition(&x, NULL); control->Move(x - width, wxDefaultCoord); + + wxStaticText* staticText = tool2->GetStaticText(); + staticText->Move(x - width, wxDefaultCoord); } } @@ -680,8 +729,8 @@ bool wxToolBar::Realize() // 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); + wxImage + imgGreyed = bmp.ConvertToImage().ConvertToGreyscale(); #ifdef wxREMAP_BUTTON_COLOURS if ( remapValue == Remap_Buttons ) @@ -856,7 +905,7 @@ bool wxToolBar::Realize() { const wxString& label = tool->GetLabel(); if ( !label.empty() ) - button.iString = (int)label.c_str(); + button.iString = (int)label.wx_str(); } button.idCommand = tool->GetId(); @@ -914,6 +963,10 @@ bool wxToolBar::Realize() button.fsStyle = TBSTYLE_BUTTON; break; + case wxITEM_DROPDOWN: + button.fsStyle = TBSTYLE_DROPDOWN; + break; + default: wxFAIL_MSG( _T("unexpected toolbar button kind") ); button.fsStyle = TBSTYLE_BUTTON; @@ -944,7 +997,7 @@ bool wxToolBar::Realize() size_t index = 0; for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ ) { - wxToolBarToolBase *tool = node->GetData(); + wxToolBarTool *tool = (wxToolBarTool*)node->GetData(); // we calculate the running y coord for vertical toolbars so we need to // get the items size for all items but for the horizontal ones we @@ -971,7 +1024,15 @@ bool wxToolBar::Realize() } wxControl *control = tool->GetControl(); + wxStaticText * const staticText = tool->GetStaticText(); + wxSize size = control->GetSize(); + wxSize staticTextSize; + if ( staticText ) + { + staticTextSize = staticText->GetSize(); + staticTextSize.y += 3; // margin between control and its label + } // the position of the leftmost controls corner int left = wxDefaultCoord; @@ -1026,18 +1087,36 @@ bool wxToolBar::Realize() ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); // adjust the controls width to exactly cover the separators - control->SetSize((nSeparators + 1)*widthSep, wxDefaultCoord); + size.x = (nSeparators + 1)*widthSep; + control->SetSize(size.x, wxDefaultCoord); } - // position the control itself correctly vertically - int height = r.bottom - r.top; + // position the control itself correctly vertically centering it on the + // icon area of the toolbar + int height = r.bottom - r.top - staticTextSize.y; + int diff = height - size.y; - if ( diff < 0 ) + if ( diff < 0 || !HasFlag(wxTB_TEXT) ) { - // the control is too high, resize to fit - control->SetSize(wxDefaultCoord, height - 2); + // not enough room for the static text + if ( staticText ) + staticText->Hide(); + + // recalculate height & diff without the staticText control + height = r.bottom - r.top; + diff = height - size.y; + if ( diff < 0 ) + { + // the control is too high, resize to fit + control->SetSize(wxDefaultCoord, height - 2); - diff = 2; + diff = 2; + } + } + else // enough space for both the control and the label + { + if ( staticText ) + staticText->Show(); } int top; @@ -1057,6 +1136,11 @@ bool wxToolBar::Realize() } control->Move(left, top + (diff + 1) / 2); + if ( staticText ) + { + staticText->Move(left + (size.x - staticTextSize.x)/2, + r.bottom - staticTextSize.y); + } } // the max index is the "real" number of buttons - i.e. counting even the @@ -1071,9 +1155,9 @@ bool wxToolBar::Realize() } else if ( m_nButtons > 0 ) // vertical non empty toolbar { - if ( m_maxRows == 0 ) - // if not set yet, have one column - SetRows(m_nButtons); + // if not set yet, have one column + m_maxRows = 1; + SetRows(m_nButtons); } InvalidateBestSize(); @@ -1125,11 +1209,38 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *WXUNUSED(result)) { + LPNMHDR hdr = (LPNMHDR)lParam; + if ( hdr->code == TBN_DROPDOWN ) + { + LPNMTOOLBAR tbhdr = (LPNMTOOLBAR)lParam; + + wxCommandEvent evt(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, tbhdr->iItem); + if ( GetEventHandler()->ProcessEvent(evt) ) + { + // Event got handled, don't display default popup menu + return false; + } + + const wxToolBarToolBase * const tool = FindById(tbhdr->iItem); + wxCHECK_MSG( tool, false, _T("drop down message for unknown tool") ); + + wxMenu * const menu = tool->GetDropdownMenu(); + if ( !menu ) + return false; + + // Display popup menu below button + RECT r; + if (::SendMessage(GetHwnd(), TB_GETITEMRECT, GetToolPos(tbhdr->iItem), (LPARAM)&r)) + PopupMenu(menu, r.left, r.bottom); + + return true; + } + + if( !HasFlag(wxTB_NO_TOOLTIPS) ) { #if wxUSE_TOOLTIPS // First check if this applies to us - NMHDR *hdr = (NMHDR *)lParam; // the tooltips control created by the toolbar is sometimes Unicode, even // in an ANSI application - this seems to be a bug in comctl32.dll v5 @@ -1331,6 +1442,30 @@ void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(tog wxFAIL_MSG( _T("not implemented") ); } +void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap ) +{ + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id)); + if ( tool ) + { + wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools.")); + + tool->SetNormalBitmap(bitmap); + Realize(); + } +} + +void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap ) +{ + wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id)); + if ( tool ) + { + wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools.")); + + tool->SetDisabledBitmap(bitmap); + Realize(); + } +} + // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- @@ -1356,9 +1491,14 @@ void wxToolBar::OnSysColourChanged(wxSysColourChangedEvent& event) void wxToolBar::OnMouseEvent(wxMouseEvent& event) { - if (event.Leaving() && m_pInTool) + if ( event.Leaving() ) { - OnMouseEnter( -1 ); + if ( m_pInTool ) + { + OnMouseEnter(wxID_ANY); + m_pInTool = NULL; + } + event.Skip(); return; } @@ -1385,6 +1525,9 @@ void wxToolBar::OnEraseBackground(wxEraseEvent& event) RECT rect = wxGetClientRect(GetHwnd()); HDC hdc = GetHdcOf((*event.GetDC())); + int majorVersion, minorVersion; + wxGetOsVersion(& majorVersion, & minorVersion); + #if wxUSE_UXTHEME // we may need to draw themed colour so that we appear correctly on // e.g. notebook page under XP with themes but only do it if the parent @@ -1405,6 +1548,30 @@ void wxToolBar::OnEraseBackground(wxEraseEvent& event) wxLogApiError(_T("DrawThemeParentBackground(toolbar)"), hr); } } + + // Only draw a rebar theme on Vista, since it doesn't jive so well with XP + if ( !UseBgCol() && majorVersion >= 6 ) + { + wxUxThemeEngine *theme = wxUxThemeEngine::GetIfActive(); + if ( theme ) + { + wxUxThemeHandle hTheme(this, L"REBAR"); + + RECT r; + wxRect rect = GetClientRect(); + wxCopyRectToRECT(rect, r); + + HRESULT hr = theme->DrawThemeBackground(hTheme, hdc, 0, 0, & r, NULL); + if ( hr == S_OK ) + return; + + // it can also return S_FALSE which seems to simply say that it + // didn't draw anything but no error really occurred + if ( FAILED(hr) ) + wxLogApiError(_T("DrawThemeParentBackground(toolbar)"), hr); + } + } + #endif // wxUSE_UXTHEME if ( UseBgCol() || (GetMSWToolbarStyle() & TBSTYLE_TRANSPARENT) ) @@ -1489,6 +1656,10 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) // no controls, nothing to erase return false; + wxSize clientSize = GetClientSize(); + int majorVersion, minorVersion; + wxGetOsVersion(& majorVersion, & minorVersion); + // prepare the DC on which we'll be drawing wxClientDC dc(this); dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID)); @@ -1515,12 +1686,18 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) // otherwise for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { - wxToolBarToolBase *tool = node->GetData(); + wxToolBarTool *tool = (wxToolBarTool*)node->GetData(); if ( tool->IsControl() ) { // get the control rect in our client coords wxControl *control = tool->GetControl(); + wxStaticText *staticText = tool->GetStaticText(); wxRect rectCtrl = control->GetRect(); + wxRect rectStaticText(0,0,0,0); + if ( staticText ) + { + rectStaticText = staticText->GetRect(); + } // iterate over all buttons TBBUTTON tbb; @@ -1552,14 +1729,56 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam) // does it intersect the control? wxRect rectItem; wxCopyRECTToRect(r, rectItem); - if ( rectCtrl.Intersects(rectItem) ) + if ( rectCtrl.Intersects(rectItem) || (staticText && rectStaticText.Intersects(rectItem))) { // yes, do erase it! - dc.DrawRectangle(rectItem); + bool haveRefreshed = false; + +#if wxUSE_UXTHEME + if ( !UseBgCol() && !GetParent()->UseBgCol() ) + { + // Don't use DrawThemeBackground + } + else if ( !UseBgCol() && majorVersion >= 6 ) + { + wxUxThemeEngine *theme = wxUxThemeEngine::GetIfActive(); + if ( theme ) + { + wxUxThemeHandle hTheme(this, L"REBAR"); + + RECT clipRect = r; + + // Draw the whole background since the pattern may be position sensitive; + // but clip it to the area of interest. + r.left = 0; + r.right = clientSize.x; + r.top = 0; + r.bottom = clientSize.y; + + HRESULT hr = theme->DrawThemeBackground(hTheme, (HDC) dc.GetHDC(), 0, 0, & r, & clipRect); + if ( hr == S_OK ) + haveRefreshed = true; + } + } +#endif + + if (!haveRefreshed) + dc.DrawRectangle(rectItem); + } + + if ( rectCtrl.Intersects(rectItem) ) + { // Necessary in case we use a no-paint-on-size // style in the parent: the controls can disappear control->Refresh(false); + } + + if ( staticText && rectStaticText.Intersects(rectItem) ) + { + // Necessary in case we use a no-paint-on-size + // style in the parent: the controls can disappear + staticText->Refresh(false); } } } @@ -1574,18 +1793,11 @@ void wxToolBar::HandleMouseMove(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam) y = GET_Y_LPARAM(lParam); wxToolBarToolBase* tool = FindToolForPosition( x, y ); - // cursor left current tool - if ( tool != m_pInTool && !tool ) - { - m_pInTool = 0; - OnMouseEnter( -1 ); - } - - // cursor entered a tool - if ( tool != m_pInTool && tool ) + // has the current tool changed? + if ( tool != m_pInTool ) { m_pInTool = tool; - OnMouseEnter( tool->GetId() ); + OnMouseEnter(tool ? tool->GetId() : wxID_ANY); } }