From bd281c2cc909bedc83999aa0d60e83d2c5fcd469 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 13 Nov 2022 22:12:09 +0000 Subject: [PATCH] Add support for using custom theme class in dark mode This is needed for at least wxStatusBar, although the gripper is still not drawn correctly even when this particular theme class is used -- but at least the main part of the status bar now uses the correct colours. --- include/wx/msw/control.h | 6 ++++++ include/wx/msw/private/darkmode.h | 5 ++++- include/wx/msw/statusbar.h | 2 ++ src/msw/control.cpp | 2 +- src/msw/darkmode.cpp | 14 ++++++++------ src/msw/statusbar.cpp | 6 ++++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/wx/msw/control.h b/include/wx/msw/control.h index b136ca2bf9..28452e4637 100644 --- a/include/wx/msw/control.h +++ b/include/wx/msw/control.h @@ -124,6 +124,12 @@ protected: // Look in our GetSubcontrols() for the windows with the given ID. virtual wxWindow *MSWFindItem(long id, WXHWND hWnd) const override; + // Return the theme class to use for this control in dark mode. Default is + // not to use any special class, but use "Explorer" as app name, as this + // works for several controls, but not all of them and the other must + // override this function. + virtual const wchar_t* MSWGetDarkThemeClass() const { return nullptr; } + // for controls like radiobuttons which are really composite this array // holds the ids (not HWNDs!) of the sub controls diff --git a/include/wx/msw/private/darkmode.h b/include/wx/msw/private/darkmode.h index 60ee866a05..e99eb3bb1c 100644 --- a/include/wx/msw/private/darkmode.h +++ b/include/wx/msw/private/darkmode.h @@ -21,7 +21,10 @@ bool IsActive(); void EnableForTLW(HWND hwnd); // Set dark theme for the given (child) window if appropriate. -void AllowForWindow(HWND hwnd); +// +// Optional theme class can be specified if a particular class must be used, +// otherwise the default one is used for it. +void AllowForWindow(HWND hwnd, const wchar_t* themeClass = nullptr); } // namespace wxMSWDarkMode diff --git a/include/wx/msw/statusbar.h b/include/wx/msw/statusbar.h index f314d8ca7e..5ce902e2d2 100644 --- a/include/wx/msw/statusbar.h +++ b/include/wx/msw/statusbar.h @@ -69,6 +69,8 @@ protected: virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result) override; #endif + virtual const wchar_t* MSWGetDarkThemeClass() const override; + // implementation of the public SetStatusWidths() void MSWUpdateFieldsWidths(); diff --git a/src/msw/control.cpp b/src/msw/control.cpp index 38c76c3055..9718ca0b50 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -138,7 +138,7 @@ bool wxControl::MSWCreateControl(const wxChar *classname, return false; } - wxMSWDarkMode::AllowForWindow(m_hWnd); + wxMSWDarkMode::AllowForWindow(m_hWnd, MSWGetDarkThemeClass()); // saving the label in m_labelOrig to return it verbatim // later in GetLabel() diff --git a/src/msw/darkmode.cpp b/src/msw/darkmode.cpp index 1be84d55d5..457ac5e9d0 100644 --- a/src/msw/darkmode.cpp +++ b/src/msw/darkmode.cpp @@ -246,15 +246,17 @@ void EnableForTLW(HWND hwnd) wxMSWImpl::AllowDarkModeForWindow(hwnd, TRUE); } -void AllowForWindow(HWND hwnd) +void AllowForWindow(HWND hwnd, const wchar_t* themeClass) { if ( wxMSWImpl::ShouldUseDarkMode() ) { - // Using "DARK_EXPLORER" theme works as well, but is subtly different - // and it seems better to use the explicit (even if undocumented) API - // provided for this instead of relying on this special theme name. wxMSWImpl::AllowDarkModeForWindow(hwnd, TRUE); - ::SetWindowTheme(hwnd, L"EXPLORER", nullptr); + + // For some reason using a theme class is incompatible with using + // "Explorer" as the app name, even though it looks like it ought to + // be, but passing ("Explorer", "ExplorerStatusBar") here, for example, + // does _not_ work, while omitting the app name in this case does work. + ::SetWindowTheme(hwnd, themeClass ? nullptr : L"Explorer", themeClass); } } @@ -279,7 +281,7 @@ void EnableForTLW(HWND WXUNUSED(hwnd)) { } -void AllowForWindow(HWND WXUNUSED(hwnd)) +void AllowForWindow(HWND WXUNUSED(hwnd), const wchar_t* WXUNUSED(themeClass)) { } diff --git a/src/msw/statusbar.cpp b/src/msw/statusbar.cpp index f194a6a96f..d2a928526a 100644 --- a/src/msw/statusbar.cpp +++ b/src/msw/statusbar.cpp @@ -679,4 +679,10 @@ bool wxStatusBar::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM* W } #endif // wxUSE_TOOLTIPS +const wchar_t* wxStatusBar::MSWGetDarkThemeClass() const +{ + // This is not documented anywhere but seems to work. + return L"ExplorerStatusBar"; +} + #endif // wxUSE_STATUSBAR && wxUSE_NATIVE_STATUSBAR