This is not complete yet, but it's already doing something (note that you need to enable it explicitly to test, the simplest way to do it is by setting WX_MSW_DARK_MODE=2
in the environment).
The most glaring missing piece (at least among those that I've seen, maybe there is something even worse) is support for dark scrollbars. Support for this in some other projects is achieved by hooking OpenNcThemeData()
function and forcing it to use Explorer::ScrollBar
instead of ScrollBar
, but doing this requires mucking with IAT and doesn't seem very robust, so I'm not really sure what to do about it yet. We could add an option to opt-in into doing this, but this looks like a cop out rather than a real solution.
Anyhow, testing this is already welcome, even if, to return to the beginning, many things don't work yet.
https://github.com/wxWidgets/wxWidgets/pull/23028
(46 files)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 7 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
It seems to be simply impossible to customize appearance of some native controls, e.g. date/time pickers don't seem to allow doing it in any way and using MSWShouldUseAutoDarkMode()
hack for them is just too ugly -- even using the generic versions would be better.
The radio box buttons are also using black text on dark background right now, but this can be fixed by just (finally) rewriting wxRadioBox
to use wxRadioButton
s inside it instead of using the native buttons directly and I plan to do it.
There are certainly other problems in addition to these ones, but it could still be already interesting to test this branch with the real applications. Please let me know if anybody does it!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 1 commit.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
I started testing the dark mode code on the xLights project, The AUI controls don't change to dark mode in my testing. Any ideas how to fix this. Thanks for all your hard work.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks for testing and I should have mentioned that this part is only about the native Windows controls (and some generic ones, such as wxActivityIndicator
). I still need to do it for wxAUI and wxSTC too. Hopefully I'll be able to do it soon, but I haven't done it yet.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Hi, I tried using this branch and enabled wxSystemOptions::SetOption("msw.dark-mode", 2);
in the dataview.cpp sample file.
No apparent change, what am I missing?
diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 67314a3251..25389e8f28 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -32,6 +32,7 @@ #include "wx/imaglist.h" #include "wx/itemattr.h" #include "wx/notebook.h" +#include "wx/sysopt.h" #ifdef wxHAS_GENERIC_DATAVIEWCTRL #include "wx/headerctrl.h" @@ -380,6 +381,7 @@ wxIMPLEMENT_APP(MyApp); bool MyApp::OnInit() { + wxSystemOptions::SetOption("msw.dark-mode", 2); if ( !wxApp::OnInit() ) return false;
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Calling this option here is too late, but then this mechanism is mostly meant to be used to force the dark mode from outside of the program, if you want to enable it programmatically, just call MSWEnableDarkMode()
directly.
Also notice that there is a known problem with the wxDVC selection colour in dark mode that I'll fix soon.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks - I was able to get it to work.
Major problem (IMO)
Observations
wxToolBar
(while in a wxDialog) shows black text over a dark background - which makes it unreadable. The hover background colour can not be seen as wellwxNotebook
inherits its light background, while the text foreground is using light colour as well, as a result, most of the controls looks "disabled" (see below screenshots)wxFontPicker
button shows black colour over black backgroundwxSTC
are not using dark mode scrollbars -> in my current code, I have managed to get it calling recursively (see code example below)wxDialog
resize bitmap does not fit well with the dark mode colourswxStaticLine
colour is too shiny as well (screenshot below)m_pfnAllowDarkModeForWindow(w->GetHandle(), use_dark); SetWindowTheme(w->GetHandle(), use_dark ? L"DarkMode_Explorer" : L"Explorer", nullptr);
Below code is the current code (before your effort for Dark Mode) that I have been using until now and it also
fixes dark scrollbars:
// bfs the windows std::vector<wxWindow*> Q; std::unordered_set<wxWindow*> V; // visited Q.push_back(win); while(!Q.empty()) { wxWindow* w = Q.front(); Q.erase(Q.begin()); if(!V.insert(w).second) { // already visited this window (how can this be true??) continue; } BOOL use_dark = current_theme_is_dark ? TRUE : FALSE; if(dynamic_cast<wxTextCtrl*>(w)) { use_dark = FALSE; // don't allow dark mode for text controls } m_pfnAllowDarkModeForWindow(w->GetHandle(), use_dark); SetWindowTheme(w->GetHandle(), use_dark ? L"DarkMode_Explorer" : L"Explorer", nullptr); if(m_pfnFlushMenuThemes) { m_pfnFlushMenuThemes(); } InvalidateRect(w->GetHandle(), nullptr, FALSE); // HACK const auto& children = w->GetChildren(); for(auto c : children) { Q.push_back(c); } }
Some screenshots to demonstrate most of the problems I mentioned (I have many dialogs in CodeLite, I can post more):
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks a lot for testing, but we probably need to create separate issues for the specific problems as there are so many of them already (here and in another reply which didn't get copied here) that some of them risk getting lost anyhow.
Right now I'm still fixing wxNotebook
, which is painful because apparently I have to draw it entirely on my own to achieve the dark look, but I'm especially interested in the scrollbar part: how exactly did you manage to make this work? Is just setting "DarkMode_Explorer" theme enough? I'm almost sure I've tried doing this and it didn't work, but perhaps I made some mistake, so I'll try again once I finish with the notebook. I'm really confused by how themes work with AllowDarkModeForWindow()
, mostly I don't see any difference between using "DarkMode_Explorer" and "Explorer"...
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@eranif Specifically concerning wxStaticLine
, I can confirm that I don't see any difference between using "DarkMode_Explorer" and "Explorer" theme, i.e. it's still white (0xffffff) for me with the former theme. I guess we could owner-draw it to make it of the expected colour (0xe0e0e0 I'd guess?), but I still don't understand why does it work differently for you.
I'm testing under 10.0.19043.2251, what is your OS version?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I will try and make some changes to the dataview demo and see what I can come up with
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Turns out that another call to AllowDarkModeForWindow
was missing. I thought that you are already doing this internally so I am not sure why the extra call is needed.
Patch:
dataview.patch
By adding a call to AllowDarkModeForWindow
for every wxDataViewCtrl
we have in the sample, gives us dark scrollbars.
With the extra call:
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I did some more digging and I wanted to fix the following:
So what I did is:
SetWindowTheme(win->GetHWND(), useDarkMode ? L"DarkMode_Explorer" : L"Explorer", nullptr);
recursively on all the children of the wxDataViewCtrl
wxHeaderCtrlBase
does not play nice with DarkMode_Explorer
- so I excluded it to get a perfect wxDataViewCtrl
The patch:
dataview.patch
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Sorry, the scrollbars for our own windows can indeed be made dark by just allowing the use of dark mode for them and setting "Explorer" theme ("DarkMode_Explorer" works too, but I still don't see any difference with it compared to "Explorer" and I think that using "Explorer" might be a tad more reliable, i.e. less likely to get broken in some future version of Windows). It's just the scrollbars of the LISTVIEW that are problematic because if we use "Explorer" for it, it uses wrong selection colour, see the comment in wxListCtrl::MSWGetDarkModeSupport()
.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 11 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
I've pushed the latest round of changes. There are still many problems remaining, but I think we should merge what we have already, unless somebody really objects to it, and open separate issues/PRs for the other issues as there are definitely still going to be many of them and we'll never merge this if we wait until everything is fixed.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I've pushed the latest round of changes. There are still many problems remaining, but I think we should merge what we have already, unless somebody really objects to it, and open separate issues/PRs for the other issues as there are definitely still going to be many of them and we'll never merge this if we wait until everything is fixed.
wxStaticBoxSizer inside wxStaticBoxSizer in dark mode not visible at all.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg I can't reproduce this with the following code in the minimal sample:
auto p = new wxPanel(this); auto* s = new wxStaticBoxSizer(wxHORIZONTAL, p, "&Outer"); auto* s2 = new wxStaticBoxSizer(wxVERTICAL, s->GetStaticBox(), "&Inner"); s2->Add(new wxCheckBox(s2->GetStaticBox(), wxID_ANY, "&Check me")); s->Add(s2); p->SetSizer(s);
I've tried using the panel because I couldn't reproduce it without it neither, i.e. if you remove p
and use this
instead of it, everything still looks fine here.
Could you please provide a minimal patch to the minimal sample allowing to reproduce the above? TIA!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I think its a good idea to push the current state into master
. Once merged, I can perform more checks and report back
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg I can't reproduce this with the following code in the minimal sample:
auto p = new wxPanel(this); auto* s = new wxStaticBoxSizer(wxHORIZONTAL, p, "&Outer"); auto* s2 = new wxStaticBoxSizer(wxVERTICAL, s->GetStaticBox(), "&Inner"); s2->Add(new wxCheckBox(s2->GetStaticBox(), wxID_ANY, "&Check me")); s->Add(s2); p->SetSizer(s);I've tried using the panel because I couldn't reproduce it without it neither, i.e. if you remove
p
and usethis
instead of it, everything still looks fine here.Could you please provide a minimal patch to the minimal sample allowing to reproduce the above? TIA!
Just standart widgets.exe from \samples\widgets without any changes from my part:
Also I've found thats some scrollbar again not using dark mode: widgets from \samples\widgets
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
And from our previous mailing list conversation:
https://groups.google.com/g/wx-dev/c/ZkiLFd0zhKc/m/RpOktT6cAwAJ
Resizable border in Dialogs or frames with wxRESIZE_BORDER looks strange
Hmm, I don't see anything obviously wrong here, what exactly do you think
is strange here?
Please take a look at the color of resizeble (dotted) area. I'ts not a really big problem, but anyway.
minimal from \samples\widgets without changes:
Check it please, maybe this is from my part.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
The trouble is that we create a scrollbar control (with SBS_SIZEGRIP
style) ourselves for the dialog, while for the frame we just use the standard status bar which does what it does in dark mode (enabled by using "ExplorerStatusBar" for it) and even though they both seem to work on their own, they are inconsistent.
I also have no idea how is the gripper supposed to look like in dark mode. Explorer itself doesn't use it and I couldn't find any other dark mode application with it.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I would vote for not having a gripper at all if you can not find a suitable dark one
On other platforms, there is no gripper... (and in most Windows native frames)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
It's a style, so if you don't want to use it you already can -- just don't specify wxSTB_SIZEGRIP
, but it's a bit weird not to use it if this style is given. Maybe we shouldn't use it by default...
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg Note that the problems in the widgets sample are specific to using wxRadioBox
and are addressed by #23075 (which is not really dark mode-specific, which is why I created a separate PR for it, but fixes this).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg Note that the problems in the widgets sample are specific to using
wxRadioBox
and are addressed by #23075 (which is not really dark mode-specific, which is why I created a separate PR for it, but fixes this).
I'll try to figure out what's wrong with wxStaticBoxSizer from my part and come back tomorrow with an example (if I figure it out). And thanks again for your excellent work.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 35 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
I've force pushed this branch to apply the fixups and will merge it relatively soon if there are no objections.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Another one: wxRichToolTip painted in default (light) colors.
It's not big problem and easily fixed by:
if (wxMSWDarkMode::IsActive())
{
tip.SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
}
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks, this is indeed easy to fix and I will, but there is also the native tooltip shown for the text control that uses Edit_ShowBalloonTip()
currently and I don't see how can we change the colours used for that one at all, so I'm not sure what to do about it -- we could either keep using the native tip with the wrong colours or use our tooltip with better colours but not quite the same appearance.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 7 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg I can't reproduce this with the following code in the minimal sample:
auto p = new wxPanel(this); auto* s = new wxStaticBoxSizer(wxHORIZONTAL, p, "&Outer"); auto* s2 = new wxStaticBoxSizer(wxVERTICAL, s->GetStaticBox(), "&Inner"); s2->Add(new wxCheckBox(s2->GetStaticBox(), wxID_ANY, "&Check me")); s->Add(s2); p->SetSizer(s);I've tried using the panel because I couldn't reproduce it without it neither, i.e. if you remove
p
and usethis
instead of it, everything still looks fine here.Could you please provide a minimal patch to the minimal sample allowing to reproduce the above? TIA!
Well... I've found a problem,
I've modified vadz samle:
auto p = new wxPanel(this);
auto* s = new wxStaticBoxSizer(wxHORIZONTAL, p, "&Outer");
auto* s2 = new wxStaticBoxSizer(wxVERTICAL, p, "&Inner");
s2->Add(new wxCheckBox(s2->GetStaticBox(), wxID_ANY, "&Check me"));
s->Add(s2);
p->SetSizer(s);
s and s2 disapear, like I said.
I realy don't understand, why s->GetStaticBox(), instead of p.
We use wxStaticBoxSizer(int orient, wxWindow *win, const wxString& label = wxEmptyString); where parent p (should be) the same, for s and s2, isn't?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Nevermind (my mistake), I need to get some sleep, then investigate what's wrong on my part with wxStaticBox.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 8 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz Assert on wxDirPickerCtrl:
src/msw/darkmode.cpp [267]:
if ( FAILED(hr) )
{
wxLogApiError(wxString::Format("SetWindowTheme(%08x, %s, %s)",
hwnd, themeName, themeId), hr);
}
Checked on my own project, and samples\widgets.
Can you confirm?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Yes, thanks. There are several problems here, but they're all minor/not really related to the dark mode, I'll push fixes soon.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 44 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz
I have a question: in my application I'm using wxSystemSettings::GetAppearance().wxSystemAppearance::IsDark()
for checking for system-wide enabled dark mode. When user run application for the first time (and application doesn't have config)
I check system-wide settings like this:
bool isDarkModeDefault = wxSystemSettings::GetAppearance().wxSystemAppearance::IsDark();
//Check application config itself, if entry exists , i.e. user defined this, use config, if not defined use isDarkModeDefault as default value for isDarkMode.
bool isDarkMode = SaveGameProConfig::Get()->GetParameter(wxT("/Appearance"), wxT("DarkMode"), isDarkModeDefault);
if (isDarkMode)
{
EnableDarkMode(isDarkMode);
}
And depend on what IsDark() returned run application in dark or default mode.
Not only frames/dialogs/etc itself, but also icons (I parse svg's and replace colors in runtime, then make bitmaps from svg's).
Also application performs some custom drawing stuff, like dialog headers, depend on colors, that depend on enabled dar mode or not enabled.
Until 32daebe it works like expected: wxSystemAppearance::IsDark() return correct values for system-wide dark mode. And application run as expected in light/dark mode.
But now it always return false, cause this:
"we shouldn't
return true from this function unless the application itself uses dark
mode"
The question is: why we have wxSystemAppearance::IsDark() and wxMSWDarkMode::IsActive() which both pointed us to application dark mode? Is this wxSystemAppearance shouldn't pointed us to system settings, not application?
And second: how we may check system-wide dark mode by API right now (not registry entry "AppsUseLightTheme" Software\Microsoft\Windows\CurrentVersion\Themes\Personalize).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
There is some confusion about what wxSystemAppearance::IsDark()
means. In a lot of code I've seen (I had done code search for it), including our own code in wxGrid
and wxAUI, it was clearly used to check if this application appearance was dark, as it's used to choose the contrasting colours and it doesn't make sense to use e.g. white foreground unless the background of this application is black, irrespectively of what the rest of the system is using.
However there is also your use case that I hadn't thought about (sorry) but which does make sense too.
I see 2 possibilities here:
wxSystemAppearance::IsDark()
if the system appearance is dark, even if the application appearance is light.wxApp::MSWShouldAppsUseDarkMode()
.(1) has the advantage of being backwards-compatible, but doesn't make much sense otherwise, both for the reasons above (most code using this function really wants to check if the application is using dark mode, not the system) and also because this is not how this function behaves under Mac (where it uses NSApp.effectiveAppearance which is also app-specific) nor under all the other platforms (where it uses IsUsingDarkBackground()
which is based on system colours for this application). Also, if we do (1), we need some way of checking whether this application is using dark mode and I have no idea what could we call it without creating a lot of confusion, i.e. how are we going to explain that some wxSystemSettings::IsAppDark()
should be used instead of wxSystemAppearance::IsDark()
.
So I think we need to add another function for querying the system appearance and I think that this function should be MSW-specific because it's the only platform where we can change this (by calling MSWEnableDarkMode()
) anyhow.
What do you think?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
What do you think?
I see solution that not break existing codebase but logically use wxSystemAppearance as expected (from my humble point of view) by adding:
wxSystemAppearance::AppsUseDark()
- for aplicattions (registry entry "AppsUseLightTheme")
and
wxSystemAppearance::SystemUseDark()
- Windows itself (registry entry "SystemUsesLightTheme": taskbar, start menu, etc)
(maybe with MSW prefixes - MSWAppsUseDark()
, MSWSystemUseDark()
respectively).
I think this clearly pointing to the right place without any confusion. Word "Should" not the best (from my taste): in various use case we just check system appearance, not force todo something.
wxApp (again, on my taste), not good place for it: wxApp pointing to something like application behaviour.
Maybe I'm wrong, maybe not, just opinion.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I'm fine with adding new methods to wxSystemAppearance
rather than wxApp
, the real question to me is whether we change the existing IsDark()
in a backwards-incompatible way or not.
So do we all agree on:
IsDark()
: is this application itself using a dark theme.AreAppsDark()
: do the applications use dark theme by default (same as IsDark()
under non-MSW for now but could change if somebody figures out how to do it).IsSystemDark()
: does the system UI use dark theme (same as AreAppsDark()
under non-MSW and will most likely remain this way).?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I don't know what others will say, but it seems pretty acceptable to me.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
You have been asked to test it to make sure it really fixed. 😀
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@vadz pushed 2 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
OK, I've implemented this now and also added wxSysColourChangedEvent
generation on the theme change (still no automatic update of the appearance when this happens though).
Please let me know if anybody has any objections, otherwise I'll finally merge this branch soon.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I'd like to see something that return current mode:
PreferredAppMode wxMSWDarkMode::GetCurrentMode() const
{
return gs_appMode;
}
Yes, we have IsActive()
but doesn't know how it was activated.
And a little change wxApp enum:
// MSW-specific function to enable experimental dark mode support.
enum
{
DarkMode_Auto = 0, // Use dark mode if the system is using it.
DarkMode_Always = 1 // Force using dark mode.
};
// MSW-specific function to enable experimental dark mode support.
enum
{
DarkMode_Off = 0 // Never use dark mode
DarkMode_Auto = 1, // Use dark mode if the system is using it.
DarkMode_Always = 2 // Force using dark mode.
};
Ofcourse it will be done on my own inside app, as I did already:
enum class DarkMode
{
DARK_OFF,
DARK_AUTO,
DARK_ALWAYS
};
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Sorry, but why should it matter how it was activated? The only thing which matters is whether the app is using dark mode or not and wxSystemAppearance::IsDark()
can be used for this and is portable, so I prefer telling people to use it instead of adding another MSW-specific function.
I guess we could add a way to turn off dark mode, but this will only make sense once/if it's ever enabled automatically. As long as it's not the case, I'd rather avoid adding another function when you can just avoid calling MSWEnableDarkMode()
in the first place. And if we add it, I'd rather call it MSWDisableDarkMode()
instead of adding another enum element because MSWEnableDarkMode(DarkMode_Off)
doesn't read well to me.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Sorry, but why should it matter how it was activated?
The first thing that comes to mind:
void OnSysColourChangedEvent(wxSysColourChangedEvent& event)
{
switch (wxMSWDarkMode::GetCurrentMode() )
{
//Should we ignore this, because we force it?
case PreferredAppMode::AppMode_ForceDark:
...
}
}
wxSystemAppearance::IsDark() knows nothing about it, and may change independently at runtime.
instead of adding another enum element because MSWEnableDarkMode(DarkMode_Off) doesn't read well to me.
I'd prefer consider those enum as actual state. But I admit if someone thinks otherwise.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I don't know if using IsDark()
here works currently, i.e. if ShouldAppsUseDarkMode()
already returns true or false by the time this message is generated (have you tested it already by chance?), but it really should, so that the same code would work under all platforms.
As for distinguishing between forcing dark mode or following the system theme, this is your application option, so you already know it and I don't think wx needs to keep track of it.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I don't know if using IsDark() here works currently, i.e. if ShouldAppsUseDarkMode() already returns true or false by the time this message is generated (have you tested it already by chance?), but it really should, so that the same code would work under all platforms.
At first change apps dark mode:
(event processes 6 times, IDK why)
Select Dark->Light:
(27.12.2022 22:47:54) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:47:54) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:47:55) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:47:55) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:47:56) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:47:56) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:47:58) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:47:58) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:47:58) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:47:58) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:48:00) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:48:00) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
Select Light->Dark:
(27.12.2022 22:44:46) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:46) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:44:51) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:51) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:44:52) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:52) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:44:54) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:54) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:44:55) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:55) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:44:56) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:44:56) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
At second and further change apps dark mode:
Select Dark->Light:
(27.12.2022 22:45:59) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:45:59) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:46:01) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:46:01) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:46:04) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:46:04) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:46:05) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:46:05) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:46:06) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:46:06) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:46:08) [14228] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:46:08) [14228] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
Select Light->Dark (pay attention that first "0" and white):
(27.12.2022 22:48:37) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: white
(27.12.2022 22:48:37) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (0) wxSystemAppearance::IsDark(): (0)
(27.12.2022 22:48:38) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:48:38) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:48:41) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:48:41) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:48:42) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:48:42) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:48:43) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:48:43) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
(27.12.2022 22:48:44) [7680] 'OnSysColourChanged' wxSystemSettings::GetColour: rgb(32, 32, 32)
(27.12.2022 22:48:44) [7680] 'OnSysColourChanged' wxMSWDarkMode::IsActive(): (1) wxSystemAppearance::IsDark(): (1)
Code that you may copy in any sample:
Connect(wxID_ANY, wxEVT_SYS_COLOUR_CHANGED, (wxObjectEventFunction)&SaveGameProFrame::OnSysColourChanged);
void MyCoolAppFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
bool isActive = wxMSWDarkMode::IsActive();
bool isDark = wxSystemSettings::GetAppearance().wxSystemAppearance::IsDark();
wxString col = wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).GetAsString();
wxLogDebug("wxSystemSettings::GetColour: %s", col);
wxLogDebug("wxMSWDarkMode::IsActive(): (%i) wxSystemAppearance::IsDark(): (%i)", isActive , isDark);
//event.Skip(true);
}
results may vary, depend on event.Skip()
As for distinguishing between forcing dark mode or following the system theme, this is your application option, so you already know it and I don't think wx needs to keep track of it.
Well, I have nothing more to add, do what you think is right.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Merged #23028 into master.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I've merged it as is for now, we can always add more APIs later (while removing them is much more problematic). Thanks again for your testing and please open new issues for the remaining problems (other than those related to AUI and STC that I'll try to address soon).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks for the effort invested in this - much appreciated!
I will start using it in CodeLite
and will open issues if needed
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@k-serg wrote
At first change apps dark mode: (event processes 6 times, IDK why)
It is odd that so many events are received but it does happen with the current master. In my wxSystemInformationFrame I log some Windows messages and wxWidgets events. When switching the system dark mode for applications from light to dark (after starting the application), I see the message and event 14 times:
13:24:05: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:05: wxSysColourChangedEvent received.
13:24:05: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:05: wxSysColourChangedEvent received.
13:24:05: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:05: wxSysColourChangedEvent received.
13:24:05: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:05: wxSysColourChangedEvent received.
13:24:05: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:05: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
13:24:06: WM_SETTINGCHANGE received: wParam = 0, lParam ="ImmersiveColorSet"
13:24:06: wxSysColourChangedEvent received.
Not sure if this is expected, or something I do wrong in my wxSystemInformationFrame
code, or something not correct in wxWidgets.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
FWIW when I toggle between "Light" and "Dark" in the "Colours" section of the "Settings", I can see 5 WM_SETTINGSCHANGE
s being sent to a trivial Win32-only window in my example using Spy++. 5 is not 14 (as above), but the system clearly does send several messages for a single change and I have no idea why.
We could coalesce multiple consecutive messages into a single one, I guess, but it's still weird that it does it.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
It seems to me that we should not coalesced messages, we need to store the previous state to the event and then the new one, and compare it in the handler.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
More interested to me: why on second Light->Dark selection, as I already wrote, I have different values with one message batch.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Apparently Windows sends the first message before actually changing the colours. I think it's because there are actually several changes as it's an animation and not just an immediate change from white to black, but we don't handle the intermediate messages and just get the "compatible" (?) ones.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
FWIW when I toggle between "Light" and "Dark" in the "Colours" section of the "Settings", I can see 5
WM_SETTINGSCHANGE
s being sent to a trivial Win32-only window in my example using Spy++.
I see 14 messages both in Spy++ and the application, using the simplest possible code (Windows 10 22H2):
#include <wx/wx.h> class MyFrame : public wxFrame { public: MyFrame() : wxFrame(nullptr, wxID_ANY, "Test") {} private: WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override { if ( nMsg == WM_SETTINGCHANGE ) wxLogDebug("WM_SETTINGCHANGE received: wParam = %u, lParam ='%s'", (unsigned)wParam, lParam ? (LPCTSTR)lParam : wxS("")); return wxFrame::MSWWindowProc(nMsg, wParam, lParam); } }; class MyApp : public wxApp { bool OnInit() override { (new MyFrame())->Show(); return true; } }; wxIMPLEMENT_APP(MyApp);
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
It could be nice if it was possible to modify some colours in MSW darkmode, for example with something like wxMSWDarkMode::SetColour(wxSYS_COLOUR_MENUTEXT, wxColour(0xe00000)); to obtain, here, a red menu text, as it appears in some astronomy software when you use their ‘night’ mode. The standard mode exists in those softwares and the global look is quite near the darkmode as it is now, with menus in white (or light gray).
This should be probably called at the beginning of a program, before the build of menus.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
@gerard-durand FYI, this is possible now, see #23275, notably wxDarkModeSettings::GetMenuColour()
. Any feedback on that PR is welcome, please comment there if you'd like to help improving it before it's merged. TIA!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks.
Nevertheless, until now no success to make this work. Certainly because I don't understand how it is made and how to use it in my own work. May be it will be better with a small new samples test case, especially with colored text menus and sub menus.
In this last case, I thought, I could already have them with using wxOwnerDrawn::SetTextColour() as you said in interface\wx\msw\darkmode.h, but here too, I'm not able to set this correctly.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
The example from the documentation should work, i.e. just
class MySettings : public wxDarkModeSettings { public: virtual wxColour GetMenuColour(wxMenuColour which) { if ( which == wxMenuColour::StandardFg ) return *wxRED; return wxDarkModeSettings::GetMenuColour(which); } }; wxTheApp->MSWEnableDarkMode(wxApp::DarkMode_Always, new MySettings());
will use red for the top level menus in dark mode.
Customizing normal menu colours is shown in the ownerdrw sample.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Customizing normal menu colours is shown in the ownerdrw sample.
Ok for a single item, but how to set the color globally for all sub-menus items.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
There is no support for changing this colour globally, sorry.
The goal of these changes was to just allow customizing the hardcoded colours used in the dark mode because they can be wrong.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I have tested your suggested code in the sample ownerdrw.
I have just added :
if (wxSystemSettings::GetAppearance().IsDark()) wxTheApp->MSWEnableDarkMode(wxApp::DarkMode_Always, new MySettings());
before the call to InitMenu();
To obtain the darkmode, I launch ownerdraw.exe in a cmd file containing :
set WX_MSW_DARK_MODE=2
ownerdrw.exe
Like that, only the last sub-menu (Native) has correct colors in darkmode (black background and white text).
To obtain black backgrounds on submenus, I had to comment lines containing :
pItem->SetTextColour`
pItem->SetFont only for sub-menus
and
pAboutItem->SetDisabledBitmap
There is no support for changing this colour globally, sorry.
Will it be possible in the future ? Because, at least internally, this is done in darkmode with white sub-menus on a black background.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I'm surprised that "File" and "Drawn" menus don't use the correct colours. Could you please open a new issue with the exact diff that you use so that I could test it?
Will it be possible in the future ? Because, at least internally, this is done in darkmode with white sub-menus on a black background.
No, normal menus are drawn in dark mode by Windows itself. It doesn't draw the menu bar correctly in the dark mode, which is why we have to use our own hack for it.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Here is a diff file which is OK for me (with commented lines)
ownerdrw.zip
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Just to add something. If I restore only one attribute commented for a sub-menu, it's all the sub-menu which is displayed with standard colors (not darkmode).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
New remark : If as in the doc of wxDarkModeSettings Class Reference, I use the switch as it is, I obtain many warnings of my compiler (msys2 12.2) like this one:
warning: enumeration value 'wxSYS_COLOUR_SCROLLBAR' not handled in switch [-Wswitch]
If I add a default case like:
switch ( index )
{
...
// Default colour used here is 0xe0e0e0.
return *wxRED;
default:
return wxDarkModeSettings::GetColour(index);
}
It works and I have no compiler warning.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Sorry for the delay with replying, but, in any case, I'm afraid I can't say anything really useful: it's clear that owner-drawn menu items can't be used in dark mode, so I can only document this limitation (which I will do, and will also fix the example to avoid triggering -Wswitch
, thanks).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Thanks for your (whole) work.
I have also the feeling that this darkmode problem for sub-menus is not simple. I use commonly Notepad++. They have a darkmode which is customisable for the main menu and/or main toolbar, but not for sub-menus which are still white on a black background. And, they don't use wxWidgets, but directly the Windows API. So, solving that needs probably to dig deeply inside Windows. :-(
Nevertheless, it's possible to set independently colors for each submenu item, but separators are not affected, there is still a white large clear border around the sub-menus. Not a nice look. May be we'll have to wait for a next Windows correction...
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
I continue to test darkmode on Windows.
wxAboutBox, in simple mode as seen in samples\dialogs\dialogs.cpp, is shown with standard Windows colors, even when started with a preceeding set WX_MSW_DARK_MODE=2. Normal: because in this case you use the standard Windows box. All other "about" tests are shown in dark.
In that example, it is possible to force the usage of wxGenericAboutBox in ShowSimpleAboutDialog, line 3458, and it works.
When I try this in my own work, it does not compile because with only #include "wx/aboutdlg.h", wxGenericAboutBox is not found/declared. I have to add explicitely #include "wx/generic/aboutdlgg.h".
Note that in interface/wx/aboutdlg.h, wxGenericAboutBox is declared, but if I understand well, this interface folder is only used for documentation.
It can work in my own work with a simple wxAboutBox if I add a aboutInfo.SetWebSite. In that case, wxAboutBox switches automatically and internally to wxGenericAboutBox.
Nevertheless, in the documentation of wxGenericAboutBox, in one of the windows I have found, it is just stated that we have to use #include "wx/aboutdlg.h":
wxGenericAboutBox()
void wxGenericAboutBox ( const wxAboutDialogInfo & info,
wxWindow * parent = nullptr
)
This function does the same thing as wxAboutBox() except that it always uses the generic wxWidgets version of the dialog instead of the native one.
This is mainly useful if you need to customize the dialog by e.g. adding custom controls to it (customizing the native dialog is not currently supported).
See the Dialogs Sample for an example of about dialog customization.
See also wxAboutDialogInfo
Include file:
#include <wx/aboutdlg.h>
In an other one, it is just stated that we have to use #include "wx/generic/aboutdlgg.h".
But, apparently, both includes are necessary to be able to use directly wxGenericAboutBox, and in my case, obtain a dark about window (even without adding an url).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
About wxProgressDialog:
On Windows, wxProgressDialog does not support darkmode, but wxGenericProgressDialog supports it. You can see this in the samples/dialogs if you set WX_MSW_DARK_MODE=2 before launching dialogs.exe.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
Many (but not all) limitations of MSW dark mode (stemming from the lack of dark mode support in the native controls) are documented, including wxAboutBoxBox()
and wxProgressDialog
, see https://docs.wxwidgets.org/latest/classwx_app.html#af8c93d7e3345e62a58325f3ab1d158d6
Some others are known and reported, so far without a fix...
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.