From c301af42f923a9997e99bf8d3b8f00df667f88f9 Mon Sep 17 00:00:00 2001 From: Stefan Ziegler <33447587+sz5000@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:00:08 +0200 Subject: [PATCH] Fix wxMSW toolbar drop down arrow appearance in dark mode We have no choice but to draw it ourselves, using the appropriate colour, as by default it is drawn in black which has almost no contrast with the background when using dark mode. Closes #24901. --- src/msw/toolbar.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/msw/toolbar.cpp b/src/msw/toolbar.cpp index 90bd5f9787..71fb23f35e 100644 --- a/src/msw/toolbar.cpp +++ b/src/msw/toolbar.cpp @@ -1687,14 +1687,22 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), return true; case CDDS_ITEMPREPAINT: + { // If we get here, we must have returned CDRF_NOTIFYITEMDRAW // from above, so we're using the dark mode and need to // customize the colours for it. nmtbcd->clrText = nmtbcd->clrTextHighlight = wxColourToRGB(GetForegroundColour()); - nmtbcd->clrHighlightHotTrack = wxSysColourToRGB(wxSYS_COLOUR_HOTLIGHT); - *result = CDRF_DODEFAULT | TBCDRF_USECDCOLORS | TBCDRF_HILITEHOTTRACK; + const wxColour colBg = m_hasBgCol + ? GetBackgroundColour() + : wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); + nmtbcd->clrHighlightHotTrack = wxColourToRGB(colBg.ChangeLightness(115)); + + *result = CDRF_DODEFAULT | + CDRF_NOTIFYPOSTPAINT | + TBCDRF_USECDCOLORS | + TBCDRF_HILITEHOTTRACK; // Draw custom checked button background when it is not hot: // by default it is drawn in a light colour not appropriate for @@ -1712,6 +1720,55 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), } return true; + } + + case CDDS_ITEMPOSTPAINT: + { + // custom draw the drop-down arrow here, as it is always black + WinStruct bi; + bi.dwMask = TBIF_STYLE | TBIF_COMMAND; + const auto itemIndex = + ::SendMessage(GetHwnd(), TB_GETBUTTONINFO, + (WPARAM)nmtbcd->nmcd.dwItemSpec, (LPARAM)&bi); + if ( itemIndex >= 0 && bi.fsStyle & TBSTYLE_DROPDOWN ) + { + RECT ddrc = { 0 }; + ::SendMessage(GetHwnd(), TB_GETITEMDROPDOWNRECT, + (WPARAM)itemIndex, (LPARAM)&ddrc); + + wxColour colBg = m_hasBgCol + ? GetBackgroundColour() + : wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); + + if ( nmtbcd->nmcd.uItemState & CDIS_HOT ) + { + // Make this slightly different from the colour used + // for the button itself above. + colBg = colBg.ChangeLightness(120); + } + + AutoHBRUSH bgBrush(wxColourToRGB(colBg)); + ::FillRect(nmtbcd->nmcd.hdc, &ddrc, bgBrush); + + int arrowCenterX = (ddrc.left + ddrc.right) / 2; + int arrowCenterY = (ddrc.top + ddrc.bottom) / 2; + POINT ptsArrow[3] = + { + { arrowCenterX - FromDIP(3), arrowCenterY - FromDIP(2) }, + { arrowCenterX + FromDIP(3), arrowCenterY - FromDIP(2) }, + { arrowCenterX, arrowCenterY + FromDIP(2) } + }; + + AutoHBRUSH fgBrush(wxColourToRGB(GetForegroundColour())); + AutoHPEN hPen(wxColourToRGB(GetForegroundColour())); + ::SelectObject(nmtbcd->nmcd.hdc, hPen); + ::SelectObject(nmtbcd->nmcd.hdc, fgBrush); + ::Polygon(nmtbcd->nmcd.hdc, ptsArrow, 3); + } + + *result = CDRF_DODEFAULT; + return true; + } } return false;