diff --git a/dnSpy/dnSpy.Contracts.DnSpy/Controls/MetroWindow.cs b/dnSpy/dnSpy.Contracts.DnSpy/Controls/MetroWindow.cs
index df40e5c0de..998b6ea05f 100644
--- a/dnSpy/dnSpy.Contracts.DnSpy/Controls/MetroWindow.cs
+++ b/dnSpy/dnSpy.Contracts.DnSpy/Controls/MetroWindow.cs
@@ -19,10 +19,12 @@ You should have received a copy of the GNU General Public License
using System;
using System.Diagnostics;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
@@ -104,21 +106,33 @@ static Size GetDpi_Win81(IntPtr hWnd) {
return new Size(dpiX, dpiY);
}
- struct RECT {
- public int left, top, right, bottom;
- RECT(bool dummy) => left = top = right = bottom = 0;// disable compiler warning
- }
-
[DllImport("user32", SetLastError = true)]
static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
[DllImport("shcore", SetLastError = true)]
static extern int GetDpiForMonitor(IntPtr hmonitor, int dpiType, out int dpiX, out int dpiY);
+ static readonly DependencyPropertyKey uiElementIsMouseOverPropertyKey =
+ (DependencyPropertyKey)typeof(UIElement).GetField("IsMouseOverPropertyKey", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null)!;
+ static readonly DependencyPropertyKey buttonIsPressedPropertyKey =
+ (DependencyPropertyKey)typeof(ButtonBase).GetField("IsPressedPropertyKey", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null)!;
+
+ private Visual? minimizeButton;
+ private Visual? maximizeButton;
+ private Visual? closeButton;
+
int WM_DPICHANGED_counter = 0;
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
const int WM_DPICHANGED = 0x02E0;
const int WM_MOUSEHWHEEL = 0x020E;
const int WM_NCHITTEST = 0x0084;
+ const int WM_NCMOUSELEAVE = 0x02A2;
+ const int WM_NCLBUTTONDOWN = 0x00A1;
+ const int WM_NCLBUTTONUP = 0x00A2;
+ const int WM_MOUSELEAVE = 0x02A3;
+
+ const nint HTCLOSE = 20;
+ const nint HTMAXBUTTON = 9;
+ const nint HTMINBUTTON = 8;
if (msg == WM_DPICHANGED) {
if (WM_DPICHANGED_counter != 0)
@@ -162,6 +176,139 @@ IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool hand
}
}
+ var hitPoint = new Point((short)lParam, (short)((uint)lParam >> 16));
+
+ var result = IntPtr.Zero;
+ if (minimizeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(minimizeButton, minimizeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ minimizeButton.SetValue(uiElementIsMouseOverPropertyKey, true);
+ handled = true;
+ result = HTMINBUTTON;
+ }
+ else {
+ minimizeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (minimizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+ }
+ if (maximizeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(maximizeButton, maximizeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ maximizeButton.SetValue(uiElementIsMouseOverPropertyKey, true);
+ handled = true;
+ result = HTMAXBUTTON;
+ }
+ else {
+ maximizeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (maximizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+ }
+ if (closeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(closeButton, closeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ closeButton.SetValue(uiElementIsMouseOverPropertyKey, true);
+ handled = true;
+ result = HTCLOSE;
+ }
+ else {
+ closeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (closeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+
+ }
+ return result;
+ }
+
+ if (msg == WM_NCLBUTTONDOWN) {
+ var hitPoint = new Point((short)lParam, (short)((uint)lParam >> 16));
+
+ if (minimizeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(minimizeButton, minimizeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ if (minimizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, true);
+ handled = true;
+ return IntPtr.Zero;
+ }
+ }
+ if (maximizeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(maximizeButton, maximizeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ if (maximizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, true);
+ handled = true;
+ return IntPtr.Zero;
+ }
+ }
+ if (closeButton is not null) {
+ var hitResult = VisualTreeHelper.HitTest(closeButton, closeButton.PointFromScreen(hitPoint));
+ if (hitResult is not null) {
+ if (closeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, true);
+ handled = true;
+ return IntPtr.Zero;
+ }
+ }
+ return IntPtr.Zero;
+ }
+
+ if (msg == WM_NCLBUTTONUP) {
+ if (minimizeButton is ButtonBase minBtn) {
+ bool shouldClick = (bool)minBtn.GetValue(buttonIsPressedPropertyKey.DependencyProperty);
+ minBtn.SetValue(buttonIsPressedPropertyKey, false);
+ if (shouldClick) {
+ minBtn.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, minBtn));
+ ExecuteCommand(minBtn);
+ }
+
+ handled = true;
+ }
+ if (maximizeButton is ButtonBase maxBtn) {
+ bool shouldClick = (bool)maxBtn.GetValue(buttonIsPressedPropertyKey.DependencyProperty);
+ maxBtn.SetValue(buttonIsPressedPropertyKey, false);
+ if (shouldClick) {
+ maxBtn.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, maxBtn));
+ ExecuteCommand(maxBtn);
+ }
+
+ handled = true;
+ }
+ if (closeButton is ButtonBase closeBtn) {
+ bool shouldClick = (bool)closeBtn.GetValue(buttonIsPressedPropertyKey.DependencyProperty);
+ closeBtn.SetValue(buttonIsPressedPropertyKey, false);
+ if (shouldClick) {
+ closeBtn.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, closeBtn));
+ ExecuteCommand(closeBtn);
+ }
+
+ handled = true;
+ }
+
+ return IntPtr.Zero;
+ }
+
+ if (msg == WM_NCMOUSELEAVE || msg == WM_MOUSELEAVE) {
+ if (minimizeButton is not null) {
+ minimizeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (minimizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+
+ if (maximizeButton is not null) {
+ maximizeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (maximizeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+
+ if (closeButton is not null) {
+ closeButton.SetValue(uiElementIsMouseOverPropertyKey, false);
+ if (closeButton is ButtonBase button)
+ button.SetValue(buttonIsPressedPropertyKey, false);
+ }
+
return IntPtr.Zero;
}
@@ -193,6 +340,20 @@ private protected virtual bool HandleHorizontalScroll(IInputElement element, sho
return false;
}
+ private static void ExecuteCommand(ICommandSource commandSource) {
+ var command = commandSource.Command;
+ if (command is null)
+ return;
+ object commandParameter = commandSource.CommandParameter;
+ if (command is RoutedCommand routedCommand) {
+ var target = commandSource.CommandTarget ?? commandSource as IInputElement;
+ if (routedCommand.CanExecute(commandParameter, target))
+ routedCommand.Execute(commandParameter, target);
+ }
+ else if (command.CanExecute(commandParameter))
+ command.Execute(commandParameter);
+ }
+
///
/// Gets the DPI
///
@@ -266,6 +427,90 @@ public ImageReference SystemMenuImage {
set => SetValue(SystemMenuImageProperty, value);
}
+ ///
+ /// The DependencyProperty of IsMinimumButton property
+ ///
+ public static readonly DependencyProperty IsMinimizeButtonProperty =
+ DependencyProperty.RegisterAttached("IsMinimizeButton", typeof(bool), typeof(MetroWindow), new FrameworkPropertyMetadata(false, OnIsMinimizeButtonChanged));
+
+ ///
+ /// Get value of IsMinimumButton property
+ ///
+ ///
+ ///
+ public static bool GetIsMinimizeButton(DependencyObject obj) => (bool)obj.GetValue(IsMinimizeButtonProperty);
+
+ ///
+ /// Set value of IsMinimumButton property
+ ///
+ ///
+ ///
+ public static void SetIsMinimizeButton(DependencyObject obj, bool value) => obj.SetValue(IsMinimizeButtonProperty, value);
+
+ static void OnIsMinimizeButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
+ if (d is not Visual v)
+ return;
+ if (GetWindow(d) is not MetroWindow win)
+ return;
+ win.minimizeButton = v;
+ }
+
+ ///
+ /// The DependencyProperty of IsMaximumButton property
+ ///
+ public static readonly DependencyProperty IsMaximizeButtonProperty =
+ DependencyProperty.RegisterAttached("IsMaximizeButton", typeof(bool), typeof(MetroWindow), new FrameworkPropertyMetadata(false, OnIsMaximizeButtonChanged));
+
+ ///
+ /// Get value of IsMaximumButton property
+ ///
+ ///
+ ///
+ public static bool GetIsMaximizeButton(DependencyObject obj) => (bool)obj.GetValue(IsMaximizeButtonProperty);
+
+ ///
+ /// Set value of IsMaximumButton property
+ ///
+ ///
+ ///
+ public static void SetIsMaximizeButton(DependencyObject obj, bool value) => obj.SetValue(IsMaximizeButtonProperty, value);
+
+ static void OnIsMaximizeButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
+ if (d is not Visual v)
+ return;
+ if (GetWindow(d) is not MetroWindow win)
+ return;
+ win.maximizeButton = v;
+ }
+
+ ///
+ /// The DependencyProperty of IsCloseButton property
+ ///
+ public static readonly DependencyProperty IsCloseButtonProperty =
+ DependencyProperty.RegisterAttached("IsCloseButton", typeof(bool), typeof(MetroWindow), new FrameworkPropertyMetadata(false, OnIsCloseButtonChanged));
+
+ ///
+ /// Get value of IsCloseButton property
+ ///
+ ///
+ ///
+ public static bool GetIsCloseButton(DependencyObject obj) => (bool)obj.GetValue(IsCloseButtonProperty);
+
+ ///
+ /// Set value of IsCloseButton property
+ ///
+ ///
+ ///
+ public static void SetIsCloseButton(DependencyObject obj, bool value) => obj.SetValue(IsCloseButtonProperty, value);
+
+ static void OnIsCloseButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
+ if (d is not Visual v)
+ return;
+ if (GetWindow(d) is not MetroWindow win)
+ return;
+ win.closeButton = v;
+ }
+
///
/// Maximized element property
///
diff --git a/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.NativeMethods.cs b/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.NativeMethods.cs
deleted file mode 100644
index 38df140a63..0000000000
--- a/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.NativeMethods.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace EleCho.WpfSuite {
- public partial class WindowOption {
- internal static class NativeDefinition {
- public const nint WM_NCHITTEST = 0x0084;
- public const nint WM_NCMOUSELEAVE = 0x02A2;
- public const nint WM_NCLBUTTONDOWN = 0x00A1;
- public const nint WM_NCLBUTTONUP = 0x00A2;
- public const nint WM_MOUSEMOVE = 0x0200;
-
- public const nint HTCLOSE = 20;
- public const nint HTMAXBUTTON = 9;
- public const nint HTMINBUTTON = 8;
- }
- }
-}
diff --git a/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.cs b/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.cs
deleted file mode 100644
index 7ff483a145..0000000000
--- a/dnSpy/dnSpy/Lib/EleCho.WpfSuite/Utilities/WindowOption.cs
+++ /dev/null
@@ -1,588 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Interop;
-using System.Windows.Media;
-using System.Windows.Shell;
-using System.Xml.Linq;
-using static EleCho.WpfSuite.WindowOption.NativeDefinition;
-
-namespace EleCho.WpfSuite {
- ///
- /// Window options
- ///
- public partial class WindowOption {
- static readonly Version s_versionWindows10_1809 = new Version(10, 0, 17763);
- static readonly Version s_versionWindows10 = new Version(10, 0);
-
- ///
- /// DWM Supports Corner, BorderColor, CaptionColor, TextColor
- ///
- static readonly Version s_versionWindows11_22000 = new Version(10, 0, 22000);
-
- ///
- /// DWM Supports Dark mode and Backdrop property
- ///
- static readonly Version s_versionWindows11_22621 = new Version(10, 0, 22621);
-
- static readonly Version s_versionCurrentWindows = Environment.OSVersion.Version;
-
- static Dictionary? s_maximumButtons;
- static Dictionary? s_minimumButtons;
- static Dictionary? s_closeButtons;
-
- static DependencyPropertyKey s_uiElementIsMouseOverPropertyKey =
- (DependencyPropertyKey)typeof(UIElement).GetField("IsMouseOverPropertyKey", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null)!;
-
- static DependencyPropertyKey s_buttonIsPressedPropertyKey =
- (DependencyPropertyKey)typeof(ButtonBase).GetField("IsPressedPropertyKey", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null)!;
-
- ///
- /// Get value of IsMaximumButton property
- ///
- ///
- ///
- public static bool GetIsMaximumButton(DependencyObject obj) {
- return (bool)obj.GetValue(IsMaximumButtonProperty);
- }
-
- ///
- /// Set value of IsMaximumButton property
- ///
- ///
- ///
- public static void SetIsMaximumButton(DependencyObject obj, bool value) {
- obj.SetValue(IsMaximumButtonProperty, value);
- }
-
- ///
- /// Get value of IsMinimumButton property
- ///
- ///
- ///
- public static bool GetIsMinimumButton(DependencyObject obj) {
- return (bool)obj.GetValue(IsMinimumButtonProperty);
- }
-
- ///
- /// Set value of IsMinimumButton property
- ///
- ///
- ///
- public static void SetIsMinimumButton(DependencyObject obj, bool value) {
- obj.SetValue(IsMinimumButtonProperty, value);
- }
-
- ///
- /// Get value of IsCloseButton property
- ///
- ///
- ///
- public static bool GetIsCloseButton(DependencyObject obj) {
- return (bool)obj.GetValue(IsCloseButtonProperty);
- }
-
- ///
- /// Set value of IsCloseButton property
- ///
- ///
- ///
- public static void SetIsCloseButton(DependencyObject obj, bool value) {
- obj.SetValue(IsCloseButtonProperty, value);
- }
-
- ///
- /// The DependencyProperty of IsMaximumButton property
- ///
- public static readonly DependencyProperty IsMaximumButtonProperty =
- DependencyProperty.RegisterAttached("IsMaximumButton", typeof(bool), typeof(WindowOption), new FrameworkPropertyMetadata(false, OnIsMaximumButtonChanged));
-
- ///
- /// The DependencyProperty of IsMinimumButton property
- ///
- public static readonly DependencyProperty IsMinimumButtonProperty =
- DependencyProperty.RegisterAttached("IsMinimumButton", typeof(bool), typeof(WindowOption), new FrameworkPropertyMetadata(false, OnIsMinimumButtonChanged));
-
- ///
- /// The DependencyProperty of IsCloseButton property
- ///
- public static readonly DependencyProperty IsCloseButtonProperty =
- DependencyProperty.RegisterAttached("IsCloseButton", typeof(bool), typeof(WindowOption), new FrameworkPropertyMetadata(false, OnIsCloseButtonChanged));
-
- #region DependencyProperty Callbacks
-
- private static void OnIsMaximumButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
- if (d is not FrameworkElement frameworkElement) {
- throw new InvalidOperationException("Target DependencyObject is not FrameworkElement");
- }
-
- if (DesignerProperties.GetIsInDesignMode(d)) {
- return;
- }
-
- if (Window.GetWindow(d) is Window window) {
- DoAfterWindowSourceInitialized(window, () => {
- ApplyIsMaximumButton(window, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- DoAfterElementLoaded(frameworkElement, () => {
- if (Window.GetWindow(frameworkElement) is Window loadedWindow) {
- DoAfterWindowSourceInitialized(loadedWindow, () => {
- ApplyIsMaximumButton(loadedWindow, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- throw new InvalidOperationException("Cannot find Window of Visual");
- }
- });
- }
- }
-
- private static void OnIsMinimumButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
- if (d is not FrameworkElement frameworkElement) {
- throw new InvalidOperationException("Target DependencyObject is not FrameworkElement");
- }
-
- if (DesignerProperties.GetIsInDesignMode(d)) {
- return;
- }
-
- if (Window.GetWindow(d) is Window window) {
- DoAfterWindowSourceInitialized(window, () => {
- ApplyIsMinimumButton(window, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- DoAfterElementLoaded(frameworkElement, () => {
- if (Window.GetWindow(frameworkElement) is Window loadedWindow) {
- DoAfterWindowSourceInitialized(loadedWindow, () => {
- ApplyIsMinimumButton(loadedWindow, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- throw new InvalidOperationException("Cannot find Window of Visual");
- }
- });
- }
- }
-
- private static void OnIsCloseButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
- if (d is not FrameworkElement frameworkElement) {
- throw new InvalidOperationException("Target DependencyObject is not FrameworkElement");
- }
-
- if (DesignerProperties.GetIsInDesignMode(d)) {
- return;
- }
-
- if (Window.GetWindow(d) is Window window) {
- DoAfterWindowSourceInitialized(window, () => {
- ApplyIsCloseButton(window, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- DoAfterElementLoaded(frameworkElement, () => {
- if (Window.GetWindow(frameworkElement) is Window loadedWindow) {
- DoAfterWindowSourceInitialized(loadedWindow, () => {
- ApplyIsCloseButton(loadedWindow, frameworkElement, (bool)e.NewValue);
- });
- }
- else {
- throw new InvalidOperationException("Cannot find Window of Visual");
- }
- });
- }
- }
-
- private static IntPtr WindowCaptionButtonsInteropHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
- if (handled) {
- return IntPtr.Zero;
- }
-
- switch ((nint)msg) {
- case NativeDefinition.WM_NCHITTEST: {
- var x = (int)((ulong)lParam & 0x0000FFFF);
- var y = (int)((ulong)lParam & 0xFFFF0000) >> 16;
- var result = default(IntPtr);
-
- if (s_maximumButtons is not null &&
- s_maximumButtons.TryGetValue(hwnd, out var maximumButtonVisual)) {
- var relativePoint = maximumButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(maximumButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- maximumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, true);
-
- handled = true;
- result = NativeDefinition.HTMAXBUTTON;
- }
- else {
- maximumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (maximumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
- }
-
- if (s_minimumButtons is not null &&
- s_minimumButtons.TryGetValue(hwnd, out var minimumButtonVisual)) {
- var relativePoint = minimumButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(minimumButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- minimumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, true);
-
- handled = true;
- result = NativeDefinition.HTMINBUTTON;
- }
- else {
- minimumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (minimumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
- }
-
- if (s_closeButtons is not null &&
- s_closeButtons.TryGetValue(hwnd, out var closeButtonVisual)) {
- var relativePoint = closeButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(closeButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- closeButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, true);
-
- handled = true;
- result = NativeDefinition.HTCLOSE;
- }
- else {
- closeButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (closeButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
- }
-
- return result;
- }
-
- case NativeDefinition.WM_NCLBUTTONDOWN: {
- var x = (int)((ulong)lParam & 0x0000FFFF);
- var y = (int)((ulong)lParam & 0xFFFF0000) >> 16;
-
- if (s_maximumButtons is not null &&
- s_maximumButtons.TryGetValue(hwnd, out var maximumButtonVisual)) {
- var relativePoint = maximumButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(maximumButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- if (maximumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, true);
- }
-
- handled = true;
- }
- }
-
- if (s_minimumButtons is not null &&
- s_minimumButtons.TryGetValue(hwnd, out var minimumButtonVisual)) {
- var relativePoint = minimumButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(minimumButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- if (minimumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, true);
- }
-
- handled = true;
- }
- }
-
- if (s_closeButtons is not null &&
- s_closeButtons.TryGetValue(hwnd, out var closeButtonVisual)) {
- var relativePoint = closeButtonVisual.PointFromScreen(new Point(x, y));
- var hitResult = VisualTreeHelper.HitTest(closeButtonVisual, relativePoint);
-
- if (hitResult is not null) {
- if (closeButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, true);
- }
-
- handled = true;
- }
- }
-
- break;
- }
-
- case NativeDefinition.WM_NCLBUTTONUP: {
- var x = (int)((ulong)lParam & 0x0000FFFF);
- var y = (int)((ulong)lParam & 0xFFFF0000) >> 16;
-
- if (s_maximumButtons is not null &&
- s_maximumButtons.TryGetValue(hwnd, out var maximumButtonVisual)) {
- if (maximumButtonVisual is ButtonBase button) {
- bool shouldClick = false;
- if ((bool)button.GetValue(s_buttonIsPressedPropertyKey.DependencyProperty)) {
- shouldClick = true;
- }
-
- button.SetValue(s_buttonIsPressedPropertyKey, false);
-
- if (shouldClick) {
- button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, button));
- button.Command?.Execute(button.CommandParameter);
- }
-
- handled = true;
- }
- }
-
- if (s_minimumButtons is not null &&
- s_minimumButtons.TryGetValue(hwnd, out var minimumButtonVisual)) {
- if (minimumButtonVisual is ButtonBase button) {
- bool shouldClick = false;
- if ((bool)button.GetValue(s_buttonIsPressedPropertyKey.DependencyProperty)) {
- shouldClick = true;
- }
-
- button.SetValue(s_buttonIsPressedPropertyKey, false);
-
- if (shouldClick) {
- button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, button));
- button.Command?.Execute(button.CommandParameter);
- }
-
- handled = true;
- }
- }
-
- if (s_closeButtons is not null &&
- s_closeButtons.TryGetValue(hwnd, out var closeButtonVisual)) {
- if (closeButtonVisual is ButtonBase button) {
- bool shouldClick = false;
- if ((bool)button.GetValue(s_buttonIsPressedPropertyKey.DependencyProperty)) {
- shouldClick = true;
- }
-
- button.SetValue(s_buttonIsPressedPropertyKey, false);
-
- if (shouldClick) {
- button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, button));
- button.Command?.Execute(button.CommandParameter);
- }
-
- handled = true;
- }
- }
-
- break;
- }
-
- case NativeDefinition.WM_NCMOUSELEAVE: {
- var x = (int)((ulong)lParam & 0x0000FFFF);
- var y = (int)((ulong)lParam & 0xFFFF0000) >> 16;
-
- if (s_maximumButtons is not null &&
- s_maximumButtons.TryGetValue(hwnd, out var maximumButtonVisual)) {
- maximumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (maximumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
-
- if (s_minimumButtons is not null &&
- s_minimumButtons.TryGetValue(hwnd, out var minimumButtonVisual)) {
- minimumButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (minimumButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
-
- if (s_closeButtons is not null &&
- s_closeButtons.TryGetValue(hwnd, out var closeButtonVisual)) {
- closeButtonVisual.SetValue(s_uiElementIsMouseOverPropertyKey, false);
-
- if (closeButtonVisual is ButtonBase button) {
- button.SetValue(s_buttonIsPressedPropertyKey, false);
- }
- }
-
- break;
- }
- }
-
- return IntPtr.Zero;
- }
-
- #endregion
-
- #region Utilities
-
- private static void DoAfterWindowSourceInitialized(Window window, Action action) {
- var eventHandler = default(EventHandler);
-
- eventHandler = (s, e) => {
- action?.Invoke();
- window.SourceInitialized -= eventHandler;
- };
-
- window.SourceInitialized += eventHandler;
- }
-
- private static void DoAfterElementLoaded(FrameworkElement element, Action action) {
- var eventHandler = default(RoutedEventHandler);
-
- eventHandler = (s, e) => {
- action?.Invoke();
- element.Loaded -= eventHandler;
- };
-
- element.Loaded += eventHandler;
- }
-
- private static bool HasWindowCaptionButton(nint hwnd) {
- if (s_minimumButtons is not null && s_minimumButtons.ContainsKey(hwnd))
- return true;
- if (s_maximumButtons is not null && s_maximumButtons.ContainsKey(hwnd))
- return true;
- if (s_closeButtons is not null && s_closeButtons.ContainsKey(hwnd))
- return true;
-
- return false;
- }
-
- #endregion
-
- #region Final Logic
-
- private static unsafe void ApplyIsMaximumButton(Window window, Visual visual, bool isMaximumButton) {
- var windowInteropHelper = new WindowInteropHelper(window);
- var windowHandle = windowInteropHelper.EnsureHandle();
-
- var hwndSource = HwndSource.FromHwnd(windowHandle);
-
- if (isMaximumButton) {
- if (s_maximumButtons is null) {
- s_maximumButtons = new();
- }
-
- if (HasWindowCaptionButton(windowHandle)) {
- hwndSource.AddHook(WindowCaptionButtonsInteropHook);
- }
-
- if (s_maximumButtons.ContainsKey(windowHandle)) {
- throw new InvalidOperationException("MaximumButton is already set to another Visual");
- }
-
- s_maximumButtons[windowHandle] = visual;
- }
- else {
- if (s_maximumButtons is null) {
- return;
- }
-
- s_maximumButtons.Remove(windowHandle);
-
- if (s_maximumButtons.Count == 0) {
- s_maximumButtons = null;
- }
-
- if (!HasWindowCaptionButton(windowHandle)) {
- hwndSource.RemoveHook(WindowCaptionButtonsInteropHook);
- }
- }
- }
-
- private static unsafe void ApplyIsMinimumButton(Window window, Visual visual, bool isMinimumButton) {
- var windowInteropHelper = new WindowInteropHelper(window);
- var windowHandle = windowInteropHelper.EnsureHandle();
-
- var hwndSource = HwndSource.FromHwnd(windowHandle);
-
- if (isMinimumButton) {
- if (s_minimumButtons is null) {
- s_minimumButtons = new();
- }
-
- if (HasWindowCaptionButton(windowHandle)) {
- hwndSource.AddHook(WindowCaptionButtonsInteropHook);
- }
-
- if (s_minimumButtons.ContainsKey(windowHandle)) {
- throw new InvalidOperationException("MinimumButton is already set to another Visual");
- }
-
- s_minimumButtons[windowHandle] = visual;
- }
- else {
- if (s_minimumButtons is null) {
- return;
- }
-
- s_minimumButtons.Remove(windowHandle);
-
- if (s_minimumButtons.Count == 0) {
- s_minimumButtons = null;
- }
-
- if (!HasWindowCaptionButton(windowHandle)) {
- hwndSource.RemoveHook(WindowCaptionButtonsInteropHook);
- }
- }
- }
-
- private static unsafe void ApplyIsCloseButton(Window window, Visual visual, bool isCloseButton) {
- var windowInteropHelper = new WindowInteropHelper(window);
- var windowHandle = windowInteropHelper.EnsureHandle();
-
- var hwndSource = HwndSource.FromHwnd(windowHandle);
-
- if (isCloseButton) {
- if (s_closeButtons is null) {
- s_closeButtons = new();
- }
-
- if (HasWindowCaptionButton(windowHandle)) {
- hwndSource.AddHook(WindowCaptionButtonsInteropHook);
- }
-
- if (s_closeButtons.ContainsKey(windowHandle)) {
- throw new InvalidOperationException("MinimumButton is already set to another Visual");
- }
-
- s_closeButtons[windowHandle] = visual;
- }
- else {
- if (s_closeButtons is null) {
- return;
- }
-
- s_closeButtons.Remove(windowHandle);
-
- if (s_closeButtons.Count == 0) {
- s_closeButtons = null;
- }
-
- if (!HasWindowCaptionButton(windowHandle)) {
- hwndSource.RemoveHook(WindowCaptionButtonsInteropHook);
- }
- }
- }
-
- #endregion
- }
-}
diff --git a/dnSpy/dnSpy/MainApp/App.xaml.cs b/dnSpy/dnSpy/MainApp/App.xaml.cs
index 35d2fff675..3cb60206ee 100644
--- a/dnSpy/dnSpy/MainApp/App.xaml.cs
+++ b/dnSpy/dnSpy/MainApp/App.xaml.cs
@@ -95,6 +95,8 @@ static void ShowException(Exception? ex) {
Task initializeMEFTask;
Stopwatch? startupStopwatch;
public App(bool readSettings, Stopwatch startupStopwatch) {
+ WineFixes.Initialize();
+
resourceManagerTokenCacheImpl = new ResourceManagerTokenCacheImpl();
args = new AppCommandLineArgs();
@@ -106,7 +108,6 @@ public App(bool readSettings, Stopwatch startupStopwatch) {
ResourceHelper.SetResourceManagerTokenCache(resourceManagerTokenCacheImpl);
AppDirectories.SetSettingsFilename(args.SettingsFilename);
- WineFixes.Initialize();
AddAppContextFixes();
InstallExceptionHandlers();
InitializeComponent();
diff --git a/dnSpy/dnSpy/Themes/wpf.styles.templates.xaml b/dnSpy/dnSpy/Themes/wpf.styles.templates.xaml
index 22538ebd82..d9e2882c6f 100644
--- a/dnSpy/dnSpy/Themes/wpf.styles.templates.xaml
+++ b/dnSpy/dnSpy/Themes/wpf.styles.templates.xaml
@@ -22,8 +22,7 @@
xmlns:disasmsettingsx86="clr-namespace:dnSpy.Disassembly.X86"
xmlns:disasmviewersettings="clr-namespace:dnSpy.Disassembly.Viewer"
xmlns:bm="clr-namespace:dnSpy.Bookmarks.Settings"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:ws="clr-namespace:EleCho.WpfSuite">
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">