X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6ae2a4b72f92c807a59d407c8061416bf310900f..dd9f8b6bb6935360a8271dc3e8749fb026b601a8:/src/msw/tbar95.cpp diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index f2c24ec171..16ebe1ffc1 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -44,8 +44,10 @@ #endif #include "wx/sysopt.h" +#include "wx/dcclient.h" #include "wx/msw/private.h" +#include "wx/msw/dc.h" #if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" @@ -303,6 +305,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; } @@ -400,8 +407,16 @@ wxSize wxToolBar::DoGetBestSize() const sizeBest.y = size.cy; } - if (!IsVertical() && !(GetWindowStyle() & wxTB_NODIVIDER)) - sizeBest.y += 1; + if (!IsVertical()) + { + // Without the extra height, DoGetBestSize can report a size that's + // smaller than the actual window, causing windows to overlap slightly + // in some circumstances, leading to missing borders (especially noticeable + // in AUI layouts). + if (!(GetWindowStyle() & wxTB_NODIVIDER)) + sizeBest.y += 2; + sizeBest.y ++; + } CacheBestSize(sizeBest); @@ -790,8 +805,8 @@ bool wxToolBar::Realize() TBREPLACEBITMAP replaceBitmap; replaceBitmap.hInstOld = NULL; replaceBitmap.hInstNew = NULL; - replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; - replaceBitmap.nIDNew = (UINT) hBitmap; + replaceBitmap.nIDOld = (UINT_PTR)oldToolBarBitmap; + replaceBitmap.nIDNew = (UINT_PTR)hBitmap; replaceBitmap.nButtons = nButtons; if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, 0, (LPARAM) &replaceBitmap) ) @@ -820,7 +835,7 @@ bool wxToolBar::Realize() { TBADDBITMAP addBitmap; addBitmap.hInst = 0; - addBitmap.nID = (UINT) hBitmap; + addBitmap.nID = (UINT_PTR)hBitmap; if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP, (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 ) { @@ -900,7 +915,7 @@ bool wxToolBar::Realize() { const wxString& label = tool->GetLabel(); if ( !label.empty() ) - button.iString = (int)label.wx_str(); + button.iString = (INT_PTR)label.wx_str(); } button.idCommand = tool->GetId(); @@ -927,7 +942,7 @@ bool wxToolBar::Realize() DoToggleTool(tool, true); } } - else if (tool->IsToggled()) + else if ( tool->IsToggled() ) { wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious(); int prevIndex = i - 1; @@ -941,7 +956,7 @@ bool wxToolBar::Realize() if ( tool->Toggle(false) ) DoToggleTool(tool, false); - prevButton.fsState = TBSTATE_ENABLED; + prevButton.fsState &= ~TBSTATE_CHECKED; nodePrev = nodePrev->GetPrevious(); prevIndex--; } @@ -958,6 +973,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; @@ -1161,9 +1180,14 @@ bool wxToolBar::Realize() // message handlers // ---------------------------------------------------------------------------- -bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id) +bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id_) { - wxToolBarToolBase *tool = FindById((int)id); + // cast to signed is important as we compare this id with (signed) ints in + // FindById() and without the cast we'd get a positive int from a + // "negative" (i.e. > 32767) WORD + const int id = (signed short)id_; + + wxToolBarToolBase *tool = FindById(id); if ( !tool ) return false; @@ -1185,7 +1209,7 @@ bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id) // OnLeftClick() can veto the button state change - for buttons which // may be toggled only, of couse - if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() ) + if ( !OnLeftClick(id, toggled) && tool->CanBeToggled() ) { // revert back tool->Toggle(!toggled); @@ -1200,11 +1224,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 ( HandleWindowEvent(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 @@ -1487,7 +1538,14 @@ void wxToolBar::OnMouseEvent(wxMouseEvent& event) void wxToolBar::OnEraseBackground(wxEraseEvent& event) { RECT rect = wxGetClientRect(GetHwnd()); - HDC hdc = GetHdcOf((*event.GetDC())); + + wxDC *dc = event.GetDC(); + if (!dc) return; + wxMSWDCImpl *impl = (wxMSWDCImpl*) dc->GetImpl(); + HDC hdc = GetHdcOf(*impl); + + int majorVersion, minorVersion; + wxGetOsVersion(& majorVersion, & minorVersion); #if wxUSE_UXTHEME // we may need to draw themed colour so that we appear correctly on @@ -1509,9 +1567,36 @@ 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) ) + // we need to always draw our background under XP, as otherwise it doesn't + // appear correctly with some themes (e.g. Zune one) + if ( majorVersion == 5 || + UseBgCol() || (GetMSWToolbarStyle() & TBSTYLE_TRANSPARENT) ) { // do draw our background // @@ -1593,6 +1678,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)); @@ -1662,20 +1751,54 @@ 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; + + wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); + HRESULT hr = theme->DrawThemeBackground(hTheme, GetHdcOf(*impl), 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) ) { - // yes, do erase it! - dc.DrawRectangle(rectItem); - // Necessary in case we use a no-paint-on-size // style in the parent: the controls can disappear staticText->Refresh(false);