From 2e45ddc2d2596cee9ac005b6c8a5f1253e2a73bb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 14 Dec 2022 18:18:13 +0000 Subject: [PATCH] Fix static box and check/radio buttons text colour in dark mode The labels of these controls were unreadable because they used the same text colour as in normal, light mode even after enabling dark mode support for them, so fix this by explicitly setting the default (for dark mode, i.e. light) text colour for them. Add a new "setForeground" field to MSWDarkModeSupport struct to allow doing this easily and in a single place in wxControl code, so that it could be customized, or even skipped, if these controls support for the dark mode is improved, in the future. --- include/wx/msw/checkbox.h | 2 ++ include/wx/msw/control.h | 4 ++++ include/wx/msw/radiobut.h | 2 ++ include/wx/msw/statbox.h | 2 ++ src/msw/checkbox.cpp | 12 ++++++++++++ src/msw/control.cpp | 3 +++ src/msw/radiobut.cpp | 13 +++++++++++++ src/msw/statbox.cpp | 9 +++++++++ 8 files changed, 47 insertions(+) diff --git a/include/wx/msw/checkbox.h b/include/wx/msw/checkbox.h index 8289e6d820..28b2078364 100644 --- a/include/wx/msw/checkbox.h +++ b/include/wx/msw/checkbox.h @@ -62,6 +62,8 @@ public: protected: virtual wxSize DoGetBestClientSize() const override; + virtual bool MSWGetDarkModeSupport(MSWDarkModeSupport& support) const override; + virtual void DoSet3StateValue(wxCheckBoxState value) override; virtual wxCheckBoxState DoGet3StateValue() const override; diff --git a/include/wx/msw/control.h b/include/wx/msw/control.h index 381d210455..fdc921ad51 100644 --- a/include/wx/msw/control.h +++ b/include/wx/msw/control.h @@ -134,6 +134,10 @@ protected: // The theme IDs to use. If neither this field nor the theme name is // set, no theme is applied to the window. const wchar_t* themeId = nullptr; + + // For some controls we need to set the foreground explicitly, even if + // they have some support for the dark theme. + bool setForeground = false; }; // Called after creating the control to enable dark mode support if needed. diff --git a/include/wx/msw/radiobut.h b/include/wx/msw/radiobut.h index 3676cc32e7..71bb3cc8ac 100644 --- a/include/wx/msw/radiobut.h +++ b/include/wx/msw/radiobut.h @@ -58,6 +58,8 @@ protected: virtual wxBorder GetDefaultBorder() const override { return wxBORDER_NONE; } virtual wxSize DoGetBestSize() const override; + virtual bool MSWGetDarkModeSupport(MSWDarkModeSupport& support) const override; + // Implement wxMSWOwnerDrawnButtonBase methods. virtual int MSWGetButtonStyle() const override; virtual void MSWOnButtonResetOwnerDrawn() override; diff --git a/include/wx/msw/statbox.h b/include/wx/msw/statbox.h index f8bb9f9ae8..ce058eb2a6 100644 --- a/include/wx/msw/statbox.h +++ b/include/wx/msw/statbox.h @@ -79,6 +79,8 @@ public: protected: virtual wxWindowList GetCompositeWindowParts() const override; + virtual bool MSWGetDarkModeSupport(MSWDarkModeSupport& support) const override; + // return the region with all the windows inside this static box excluded virtual WXHRGN MSWGetRegionWithoutChildren(); diff --git a/src/msw/checkbox.cpp b/src/msw/checkbox.cpp index ac2784da74..2704787aff 100644 --- a/src/msw/checkbox.cpp +++ b/src/msw/checkbox.cpp @@ -88,6 +88,18 @@ WXDWORD wxCheckBox::MSWGetStyle(long style, WXDWORD *exstyle) const return msStyle; } +bool wxCheckBox::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const +{ + // Just as radio buttons, check boxes have some dark theme support, but we + // still need to change their foreground manually to make it readable in + // dark mode. + wxCheckBoxBase::MSWGetDarkModeSupport(support); + + support.setForeground = true; + + return true; +} + // ---------------------------------------------------------------------------- // wxCheckBox geometry // ---------------------------------------------------------------------------- diff --git a/src/msw/control.cpp b/src/msw/control.cpp index 21866a1220..a902b5fcdc 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -143,6 +143,9 @@ bool wxControl::MSWCreateControl(const wxChar *classname, { wxMSWDarkMode::AllowForWindow(m_hWnd, support.themeName, support.themeId); + if ( support.setForeground ) + SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT)); + if ( const int msgTT = MSWGetToolTipMessage() ) { const HWND hwndTT = (HWND)::SendMessage(GetHwnd(), msgTT, 0, 0); diff --git a/src/msw/radiobut.cpp b/src/msw/radiobut.cpp index 1502014441..232f828cd0 100644 --- a/src/msw/radiobut.cpp +++ b/src/msw/radiobut.cpp @@ -75,6 +75,19 @@ bool wxRadioButton::Create(wxWindow *parent, return true; } +bool wxRadioButton::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const +{ + // Weirdly enough, even though radio buttons support dark theme (they + // notably change the way they draw the focus rectangle if we set it), they + // still use the default black foreground colour in it, making their text + // unreadable, so we need to change it manually. + wxRadioButtonBase::MSWGetDarkModeSupport(support); + + support.setForeground = true; + + return true; +} + // ---------------------------------------------------------------------------- // wxRadioButton functions // ---------------------------------------------------------------------------- diff --git a/src/msw/statbox.cpp b/src/msw/statbox.cpp index 13b789086a..71225a2586 100644 --- a/src/msw/statbox.cpp +++ b/src/msw/statbox.cpp @@ -95,6 +95,15 @@ bool wxStaticBox::Create(wxWindow *parent, return true; } +bool wxStaticBox::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const +{ + // Static boxes don't seem to have any dark mode support, so just set the + // foreground colour contrasting with the dark background for them. + support.setForeground = true; + + return true; +} + bool wxStaticBox::ShouldUseCustomPaint() const { // When not using double buffering, we paint the box ourselves by default