Open danielkornev opened 1 month ago
Updated workaround:
Added these lines in SingleInstanceApplication's OnStartup override event handler:
#pragma warning disable WPF0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
this.ThemeMode = ThemeMode.Light;
#pragma warning restore WPF0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
Quick glance, this isn't invoked on the dispatcher, while all other calls from SystemThemeFilterMessage
always are.
Hey @danielkornev, can you give a sample repro. I am afraid, I have not worked with Visual Basic a lot and may have missed somethings.
I’ll try to,
But not right now. Got a workaround that seems to work (requiring the system to have only one theme set), it kinda works. Have a lot more stuff to build for a client ☹
Sorry!
Okay, no issues. Just wanted one clarification on the above message. Switching theme while the application is running is also causing the application to crash ?
Precisely.
My understanding is, once the event that changes the theme is fired (you can trigger it by changing all apps color in System Settings), app crashes.
On Windows 10, it seems like this event is also triggered when Spotlight changes the background image.
Get Outlook for Androidhttps://aka.ms/AAb9ysg
If i am not mistaken the code in ThemeManager also ignores the fact that a Window might run on a different dispatcher thread. Has anyone tried that yet?
ThemeManager also seems to ignore the fact that Application.Current might be null. Has anyone tried that yet?
ThemeManager also seems to ignore the fact that Application.Current might be null. Has anyone tried that yet?
Regarding this, I have tried to check everywhere is Application.Current is null or not before performing application wide. In this issue, https://github.com/dotnet/wpf/issues/9373 they have tried using Fluent without creating an Application instance, is that what you are asking about ?
@dipeshmsft That's one part. But I guess the ThemeManager causes a crash as soon as the Windows theme changes as it's trying to access Application.Current in that case.
If i am not mistaken the code in ThemeManager also ignores the fact that a Window might run on a different dispatcher thread. Has anyone tried that yet?
Yep, whole ThemeManager
does not count on that, which doesn't correspond with how the rest is written.
That's one part. But I guess the ThemeManager causes a crash as soon as the Windows theme changes as it's trying to access Application.Current in that case.
Can you send me a sample repro for this issue?
I will try to get it in before the GA happens
@dipeshmsft Just do this somewhere in your project, without having an application object, and then change some windows setting. When having an application object the theme for the threaded window simply doesn't change, which i consider another bug.
private static void StartNewThreadedWindow()
{
var thread = new Thread(StartOnThread);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
private static void StartOnThread(object? obj)
{
var window = new Window
{
ThemeMode = ThemeMode.System
};
window.Show();
Dispatcher.Run();
}
Usage of Application.Current seem to be guarded by calls to IsFluentThemeEnabled
which checks for Application.Current != null
.
So i was wrong with that assumption.
One more issue:
If you are in the situation like mine, and you want to use a custom title area, when theme switches, color of the icons for minimize, maximize/restore, and close buttons (on the right side of the app's custom title area) change to white/invisible (no idea). Curiously, mouse over still registers, custom snap layouts appear, and you can minimize/maximize/close window, but you have to switch visibility off/on in Hot Reload to make icons visible again.
Go figure.
Upd 1: maybe its because of this?
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
Dispatcher.Invoke(() =>
{
if (SystemParameters.HighContrast)
{
MinimizeButton.Visibility = Visibility.Visible;
MaximizeButton.Visibility = Visibility.Visible;
CloseButton.Visibility = Visibility.Visible;
}
else
{
MinimizeButton.Visibility = Visibility.Collapsed;
MaximizeButton.Visibility = Visibility.Collapsed;
CloseButton.Visibility = Visibility.Collapsed;
}
});
}
but if so, then why mouse over still works?
Upd 2: yep, this is precisely the reason. Once I've commented out this above, buttons stopped from disappearing when theme changes (and by theme I mean even a background change). Go figure!
@danielkornev, this is actually a known thing. And seeing the code you have added, I am assuming you are using the WPF Gallery application.
When we use WindowChrome, we can extend the WPF's content into the non-client area of a window, allowing us to use the whole area of the window. However, by setting the CaptionHeight property of the WindowChrome, we allow a rectangular area at the top to be treated as a NON_CLIENT area and receives WM_NCHITTEST messages, irrespective of the Window's background or other elements drawn in that area (until specified otherwise using WindowChrome.IsHitTestVisibleInChrome
property).
When we set UserAeroCaptionButtons
the area which generally behaves as caption buttons, keep doing that, and that's why you are seeing the snap layout and other cursor movements being registered.
Now, regarding the button's not being visibile - in my understanding, Window's background is painted over the window's CompositionTarget, and anything drawn by the OS (like the default title bar buttons) is painted over by Window's background and other elements. In this case, when you said even on background change the buttons are getting invisible, I think the reason for this is that the window's background is opaque.
The code that you are referring above, it was added to show custom title bar buttons when we are in HighContrast mode. In this mode, the background of Window in opaque and we are not able to see the button's drawn by OS.
I hope I have not misunderstood your queries. I am curious about the hot-reload scenario though. I haven't explored the working on CompositionTarget, WindowChrome with Hot-Reload specifically.
My point is that if you want to force specific Fluent theme (e.g., Light), you can avoid using this code from WPF Gallery app and then window management buttons will look ok:
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
Dispatcher.Invoke(() =>
{
if (SystemParameters.HighContrast)
{
MinimizeButton.Visibility = Visibility.Visible;
MaximizeButton.Visibility = Visibility.Visible;
CloseButton.Visibility = Visibility.Visible;
}
else
{
MinimizeButton.Visibility = Visibility.Collapsed;
MaximizeButton.Visibility = Visibility.Collapsed;
CloseButton.Visibility = Visibility.Collapsed;
}
});
}
The code above is to deal with HighContrast theme's only, also when backdrop is disabled using the switch. There are some other scenario's where the code may not work ( like when transparency effects are switched off ). I am taking a look at those scenarios.
Description
This problem appears on two kinds of OS:
Here's the error I've got in the beginning on both machines:
Sadly there was no way to figure out why this error happened. My app showed this message and then crashed. App uses Microsoft.VisualBasic library to get a Single Instance behavior, so catching the exception would get us to app.Run method.
After several experiments, the app now crashes w/o even this error after the theme of the apps in System Settings is changed to Light/Dark.
Reproduction Steps
Expected behavior
Theme changes where expected
Actual behavior
App crashes (initially with an error message and now silently)
Regression?
there were no problems prior to this moment
Known Workarounds
This seems to keep app working.
Impact
App cannot be given to the end users. It crashes every time user changes an app color in System Settings on Windows 11, and it crashes (in general) every time the theme changes on Windows 10/11.
Configuration
.NET 9 (preview, latest) Windows 10: 24H2, amd64 Windows 11: 24H2 Canary, arm64
Other information
No response