Skip to content
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

Show a dark title bar when a dark theme in ILSpy is selected #2948

Merged
merged 1 commit into from
Apr 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ILSpy/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
39 changes: 39 additions & 0 deletions ILSpy/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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
}
}
60 changes: 53 additions & 7 deletions ILSpy/Themes/WindowStyleManagerBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -30,32 +35,46 @@ public class WindowStyleManagerBehavior : FrameworkElementBehavior<Window>
{
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()
Expand All @@ -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;
}
}
}
}