From ba58ecf0171ae9ab2142dff6f19464d45c42cd85 Mon Sep 17 00:00:00 2001 From: tom-englert Date: Wed, 5 Apr 2023 16:54:48 +0200 Subject: [PATCH] Alternate approach to #2947 --- ILSpy/ExtensionMethods.cs | 5 ++ ILSpy/NativeMethods.cs | 39 ++++++++++++++ ILSpy/Themes/WindowStyleManagerBehavior.cs | 60 +++++++++++++++++++--- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs index 55339b316b..f08fc8e117 100644 --- a/ILSpy/ExtensionMethods.cs +++ b/ILSpy/ExtensionMethods.cs @@ -161,5 +161,10 @@ public static void SelectItem(this DataGrid view, object item) container.IsSelected = true; view.Focus(); } + + public static double ToGray(this Color? color) + { + return color?.R * 0.3 + color?.G * 0.6 + color?.B * 0.1 ?? 0.0; + } } } diff --git a/ILSpy/NativeMethods.cs b/ILSpy/NativeMethods.cs index 9f9fdb0f00..be6ec0c51d 100644 --- a/ILSpy/NativeMethods.cs +++ b/ILSpy/NativeMethods.cs @@ -193,6 +193,16 @@ public unsafe static string GetProcessNameFromWindow(IntPtr hWnd) return null; } } + + [DllImport("dwmapi.dll", PreserveSig = true)] + public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttribute attr, ref int attrValue, int attrSize); + + public static bool UseImmersiveDarkMode(IntPtr hWnd, bool enable) + { + int darkMode = enable ? 1 : 0; + int hr = DwmSetWindowAttribute(hWnd, DwmWindowAttribute.UseImmersiveDarkMode, ref darkMode, sizeof(int)); + return hr >= 0; + } } [return: MarshalAs(UnmanagedType.Bool)] @@ -212,4 +222,33 @@ public CopyDataStruct(IntPtr padding, int size, IntPtr buffer) this.Buffer = buffer; } } + + public enum DwmWindowAttribute : uint + { + NCRenderingEnabled = 1, + NCRenderingPolicy, + TransitionsForceDisabled, + AllowNCPaint, + CaptionButtonBounds, + NonClientRtlLayout, + ForceIconicRepresentation, + Flip3DPolicy, + ExtendedFrameBounds, + HasIconicBitmap, + DisallowPeek, + ExcludedFromPeek, + Cloak, + Cloaked, + FreezeRepresentation, + PassiveUpdateMode, + UseHostBackdropBrush, + UseImmersiveDarkMode = 20, + WindowCornerPreference = 33, + BorderColor, + CaptionColor, + TextColor, + VisibleFrameBorderThickness, + SystemBackdropType, + Last + } } diff --git a/ILSpy/Themes/WindowStyleManagerBehavior.cs b/ILSpy/Themes/WindowStyleManagerBehavior.cs index e9f20ebd2f..55d0c2c9b4 100644 --- a/ILSpy/Themes/WindowStyleManagerBehavior.cs +++ b/ILSpy/Themes/WindowStyleManagerBehavior.cs @@ -16,11 +16,16 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.ComponentModel; using System.Windows; +using System.Windows.Controls; +using System.Windows.Interop; +using System.Windows.Media; using ICSharpCode.ILSpy.Options; +using TomsToolbox.Essentials; using TomsToolbox.Wpf; using TomsToolbox.Wpf.Interactivity; @@ -30,32 +35,46 @@ public class WindowStyleManagerBehavior : FrameworkElementBehavior { private static readonly DispatcherThrottle restartNotificationThrottle = new DispatcherThrottle(ShowRestartNotification); + private INotifyChanged _foreground; + private INotifyChanged _background; + protected override void OnAttached() { base.OnAttached(); MainWindow.Instance.CurrentDisplaySettings.PropertyChanged += DisplaySettings_PropertyChanged; - UpdateWindowStyle(); + _foreground = AssociatedObject.Track(Control.ForegroundProperty); + _background = AssociatedObject.Track(Control.BackgroundProperty); + _foreground.Changed += Color_Changed; + _background.Changed += Color_Changed; + + UpdateWindowStyle(); + ApplyThemeToWindowCaption(); } protected override void OnDetaching() { base.OnDetaching(); + _foreground.Changed -= Color_Changed; + _background.Changed -= Color_Changed; + MainWindow.Instance.CurrentDisplaySettings.PropertyChanged -= DisplaySettings_PropertyChanged; } - private void UpdateWindowStyle() + private void Color_Changed(object sender, EventArgs e) { - if (!MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar) - { - return; - } + ApplyThemeToWindowCaption(); + } + private void UpdateWindowStyle() + { var window = AssociatedObject; - window.Style = (Style)window.FindResource(TomsToolbox.Wpf.Styles.ResourceKeys.WindowStyle); + + if (MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar) + window.Style = (Style)window.FindResource(TomsToolbox.Wpf.Styles.ResourceKeys.WindowStyle); } private static void ShowRestartNotification() @@ -76,5 +95,32 @@ private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEvent UpdateWindowStyle(); } } + + private void ApplyThemeToWindowCaption() + { + var window = AssociatedObject; + + IntPtr hwnd = new WindowInteropHelper(window).Handle; + + if (hwnd != IntPtr.Zero) + { + var foreground = ((window.Foreground as SolidColorBrush)?.Color).ToGray(); + var background = ((window.Background as SolidColorBrush)?.Color).ToGray(); + + var isDarkTheme = background < foreground; + + NativeMethods.UseImmersiveDarkMode(hwnd, isDarkTheme); + } + else + { + void Initialized(object o, EventArgs eventArgs) + { + ApplyThemeToWindowCaption(); + window.SourceInitialized -= Initialized; + } + + window.SourceInitialized += Initialized; + } + } } }