New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable DarkMode Theming #10985
base: main
Are you sure you want to change the base?
Enable DarkMode Theming #10985
Conversation
Test failures are caused by white space analyzer errors.
|
if (this is (Button | ||
or Label | ||
or GroupBox | ||
or Panel | ||
or SplitterPanel | ||
or ListBox | ||
or CheckedListBox | ||
or MaskedTextBox | ||
or NumericUpDown | ||
or CheckBox | ||
or RadioButton | ||
or TreeView | ||
or DataGridView | ||
or TextBox | ||
or RichTextBox | ||
or TabControl | ||
or Form)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[maintenability] please order this list as well or provide clear guidance how this list is to be maintained
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never spent thought about sorting this, since I was in the process of experimenting with what controls do have what effect.
But I think this list maybe should be sorted by inheritance level?
Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure an average Igor "the Windows Forms developer" would know what right inheritance level order is, but I may be mistaken. Personally, I'd sort this alphabetically, as this is the easiest option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add apply "DarkMode_Explorer" Theme to MdiClient Control also
if (IsDarkModeEnabled)
{
if (this is
// Controls with 4 levels of inheritance, sorted alphabetically by type name
DomainUpDown // Inherits from UpDownBase, ContainerControl, ScrollableControl, Control
or NumericUpDown // Inherits from UpDownBase, ContainerControl, ScrollableControl, Control
// Controls with 3 levels of inheritance, sorted alphabetically by type name
or CheckedListBox // Inherits from ListBox, ListControl, Control
or Form // Excluded - too invasive.
or FlowLayoutPanel // Inherits from Panel, ScrollableControl, Control
or SplitContainer // Inherits from ContainerControl, ScrollableControl, Control
or TabPage // Inherits from Panel, ScrollableControl, Control
or TableLayoutPanel // Inherits from Panel, ScrollableControl, Control
// Controls with 2 levels of inheritance, sorted alphabetically by type name
// or ComboBox // Excluded - directly handled.
or ListBox // Inherits from ListControl, Control
or Button // Inherits from ButtonBase, Control
or CheckBox // Inherits from ButtonBase, Control
or MaskedTextBox // Inherits from TextBoxBase, Control
or Panel // Inherits from ScrollableControl, Control
or RadioButton // Inherits from ButtonBase, Control
or RichTextBox // Inherits from TextBoxBase, Control
or TextBox // Inherits from TextBoxBase, Control
or HScrollBar // Inherits from ScrollBar, Control
or VScrollBar // Inherits from ScrollBar, Control
// Base classes and controls with direct inheritance from Control, sorted alphabetically by type name
or ButtonBase // Inherits from Control
or DateTimePicker // Inherits from Control
// or GroupBox // Inherits from Control directly, but behaves like a container
or Label // Inherits from Control
or LinkLabel // Inherits from Label, Control
// or ListView // Excluded - directly handled.
or MonthCalendar // Inherits from Control
or PictureBox // Inherits from Control
or ProgressBar // Inherits from Control
or ScrollableControl // Inherits from Control
// or TextBoxBase // Excluded - probably too invasive.
or TrackBar // Inherits from Control
or TreeView // Inherits from Control
or UpDownBase
or MdiClient
) // Inherits from Control
// Base class for all UI controls in WinForms
// or Control // Excluded.
{
_ = PInvoke.SetWindowTheme(HWND, "DarkMode_Explorer", null);
}
This will Apply Dark Theme to mdi Scrollbar that appear When mdi Child Form move out of MdiClient rectangle
before
after
@@ -10853,6 +10991,17 @@ private protected void SetTopLevelInternal(bool value) | |||
} | |||
} | |||
|
|||
private static unsafe void PrepareDarkMode(HWND hwnd, bool darkModeEnabled) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static unsafe void PrepareDarkMode(HWND hwnd, bool darkModeEnabled) | |
private static unsafe void PrepareDarkMode(HWND hwnd, BOOL darkModeEnabled) |
...and perfrom the cast at the callsite. This makes the intent obvious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sold on the method name either, it doesn't feel like it belongs to the vocabulary of this codebase (i.e., it's not very customary to call methods "PerpareXyz" here). It's probably more appropriate to call this SetDarkMode
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a public method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is part of the codebase, and it needs to be maintained. The more cohesive the codebase is, the less mental tax is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take a look.
@@ -3361,8 +3361,8 @@ private unsafe bool QuickActivate() | |||
} | |||
else | |||
{ | |||
qaContainer.colorFore = GetOleColorFromColor(SystemColors.WindowText); | |||
qaContainer.colorBack = GetOleColorFromColor(SystemColors.Window); | |||
qaContainer.colorFore = GetOleColorFromColor(Application.SystemColors.WindowText); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change looks like noise, and it makes viewing the actual change much more difficult. Can this be reverted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because it would change the meaning? Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I totally missed that there's a new property at the Application
type. This is not very good. It'd be better if the new property name wasn't clashing with the existing type name as it will introduce clashes in user code, and it that will need to be reconciled by introducing aliases. This is never pretty.
src/System.Windows.Forms/src/System/Windows/Forms/Controls/ListView/ListView.cs
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/Controls/ToolStrips/ToolStripManager.cs
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
public static bool SetDefaultDarkMode(DarkMode darkMode) => darkMode switch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the naming here is fine. Another potential name could be to use ColorMode e.g. SetDefaultColorMode
. This seems to match the language windows settings use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not go with ColorSomething
in the name, since my language feeling would imply theming. Per our first internal discussion, this should not go in that direction, as we would most likely overpromise.
|
||
namespace System.Windows.Forms | ||
{ | ||
internal class ForcedLightThemedSystemColors : ThemedSystemColors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious why we have both ForcedLightThemedSystemColors
and LightThemedSystemColors
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question!
I wanted to capture the palette settings for the light mode somewhere, so, if folks want to experiment with deriving/inversing them, not each of us need to do that investigation in a silo. I'll add a comment what's this for!
@KlausLoeffelmann
I understand that I've already annoyed everyone with this question, but still... At this stage, what can you say about Theming and MDI (#3691)? |
That it's not at all likely that it will be addressed in the underlaying layer, which WinForms "just" wraps around. I know it's a disappointing condition, and we're affected ourselves: namely the Designer document (Form) Window. We might be able to brush-up the rendering of the Window title in the WinForms Designer, but it'll only be possible with NC-custom painting. That might work in this case, because the Window is pretty static. But I wouldn't touch it, to be honest, for moving parts. |
5b767df
to
038bcbf
Compare
038bcbf
to
3701417
Compare
I personally do not like the extensive usage of Also if by default the non-client area used said type derived from Also having it like this would promote people to ship special nuget packages that people can install and pass in to their application to use a theme they created using a type derived from |
Please read my comments on theming in the respective issue. Thanks! |
The |
fbc724b
to
5e189d3
Compare
5e189d3
to
8d3b64e
Compare
8d3b64e
to
aaa457e
Compare
I still would prefer if the changes were ONLY made to ProfessionalColorTable and for that to detect if it should use dark mod or not with a subclass of it that is meant for applications who want to always use the dark colors in their application for everything (including the scrollbars and non-client area stuffs. Also with it using a user provided |
aaa457e
to
51a20b9
Compare
Please migrate from Also it would allow for me to have very minimal changes to my code to allow using it globally as well as remove any code that needed to be provided to manually dark theme my program (most of it copied from ShareX btw). https://github.com/Elskom/Els_kom_new/blob/main/Els_kom/Themes/DarkColorTable.cs Basically applications can then do this and register it using |
I am starting to think that with dark theme support, it might be better to have it mature a bit more and have it be slated for .NET 10, also with more of that time being invested would mean a much deeper integrated dark theme support and with it perhaps support for all controls + the default scrollbars in the |
I don't think there's a reason to delay the API, if those are believed to be usable. Those API, however, must be marked as |
💯 |
I agree with Igor here. And again: we have no plans to go down the theming route. That has way too much potential to mess with existing APIs and screw up existing theming concepts. With Application.SystemColors you have an easy way to implement DarkMode, but you can also easily break the Ambient Ancestor DarkMode chain at any point and take over manually with your own palette. Or just opt out of it at the beginning, if you think your third party's theming is doing a visually more compatible job for your target audience. Thanks Klaus |
I am referring to very simple "themes" provided only by specific colors using the existing |
* Take HighContrast settings into account for dark mode availability assessment.
* Enable PropertyGrid * Fix some code formatting issues * Try easy fixes for Calendar.
Work in Progress. Fixes #7641.
[Draft Disclaimer]: This is NOT at all in a state for a formal review. I very much want to start a creative discussion about functionality - my overloaded ADHD brain would like to concentrate on that and postpone taking care of formatting and indention issues after we know where we're going with this. I'll be ignoring those comments for now, and address them later, should they still apply.