mirror of
https://github.com/babalae/better-genshin-impact
synced 2025-01-07 03:17:16 +08:00
introducing high dpi awareness controller
This commit is contained in:
parent
e4cb3e78e9
commit
3b5220dcf6
@ -1,10 +1,5 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
[assembly: DisableDpiAwareness]
|
||||
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
|
@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
namespace BetterGenshinImpact.Helpers.DpiAwareness;
|
||||
|
||||
/// <summary>
|
||||
/// 高分辨率适配器
|
||||
/// </summary>
|
||||
internal class DpiAwarenessController
|
||||
{
|
||||
private readonly Window window;
|
||||
|
||||
private HwndSource? hwndSource;
|
||||
private HWND? hwnd;
|
||||
private double currentDpiRatio;
|
||||
|
||||
static DpiAwarenessController()
|
||||
{
|
||||
SHCore.SetProcessDpiAwareness(SHCore.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE).ThrowIfFailed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的高分辨率适配器
|
||||
/// </summary>
|
||||
/// <param name="window">目标窗体</param>
|
||||
public DpiAwarenessController(Window window)
|
||||
{
|
||||
this.window = window;
|
||||
window.Loaded += (_, _) => OnAttached();
|
||||
window.Closing += (_, _) => OnDetaching();
|
||||
}
|
||||
|
||||
private void OnAttached()
|
||||
{
|
||||
if (window.IsInitialized)
|
||||
{
|
||||
AddHwndHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.SourceInitialized += AssociatedWindowSourceInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDetaching()
|
||||
{
|
||||
RemoveHwndHook();
|
||||
}
|
||||
|
||||
private void AddHwndHook()
|
||||
{
|
||||
hwndSource = PresentationSource.FromVisual(window) as HwndSource;
|
||||
hwndSource?.AddHook(HwndHook);
|
||||
hwnd = new WindowInteropHelper(window).Handle;
|
||||
}
|
||||
|
||||
private void RemoveHwndHook()
|
||||
{
|
||||
window.SourceInitialized -= AssociatedWindowSourceInitialized;
|
||||
hwndSource?.RemoveHook(HwndHook);
|
||||
hwnd = null;
|
||||
}
|
||||
|
||||
private void AssociatedWindowSourceInitialized(object? sender, EventArgs e)
|
||||
{
|
||||
AddHwndHook();
|
||||
|
||||
currentDpiRatio = GetScaleRatio(window);
|
||||
UpdateDpiScaling(currentDpiRatio, true);
|
||||
}
|
||||
|
||||
private unsafe nint HwndHook(nint hWnd, int message, nint wParam, nint lParam, ref bool handled)
|
||||
{
|
||||
if (message is 0x02E0)
|
||||
{
|
||||
RECT rect = *(RECT*)&lParam;
|
||||
|
||||
User32.SetWindowPosFlags flag =
|
||||
User32.SetWindowPosFlags.SWP_NOZORDER
|
||||
| User32.SetWindowPosFlags.SWP_NOACTIVATE
|
||||
| User32.SetWindowPosFlags.SWP_NOOWNERZORDER;
|
||||
User32.SetWindowPos(hWnd, default, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, flag);
|
||||
|
||||
// we modified this fragment to correct the wrong behaviour
|
||||
double newDpiRatio = GetScaleRatio(window) * currentDpiRatio;
|
||||
if (newDpiRatio != currentDpiRatio)
|
||||
{
|
||||
UpdateDpiScaling(newDpiRatio);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private void UpdateDpiScaling(double newDpiRatio, bool useSacleCenter = false)
|
||||
{
|
||||
currentDpiRatio = newDpiRatio;
|
||||
Debug.WriteLine($"Set dpi scaling to {currentDpiRatio:p2}");
|
||||
FrameworkElement firstChild = (FrameworkElement)VisualTreeHelper.GetChild(window, 0);
|
||||
ScaleTransform transform;
|
||||
if (useSacleCenter)
|
||||
{
|
||||
double centerX = window.Left + (window.Width / 2);
|
||||
double centerY = window.Top + (window.Height / 2);
|
||||
|
||||
transform = new ScaleTransform(currentDpiRatio, currentDpiRatio, centerX, centerY);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = new ScaleTransform(currentDpiRatio, currentDpiRatio);
|
||||
}
|
||||
|
||||
firstChild.LayoutTransform = transform;
|
||||
}
|
||||
private static double GetScaleRatio(Window window)
|
||||
{
|
||||
PresentationSource hwndSource = PresentationSource.FromVisual(window);
|
||||
|
||||
// TODO: verify use hwndSource there
|
||||
double wpfDpi = 96.0 * hwndSource.CompositionTarget.TransformToDevice.M11;
|
||||
|
||||
HMONITOR hMonitor = User32.MonitorFromWindow(((HwndSource)hwndSource).Handle, User32.MonitorFlags.MONITOR_DEFAULTTONEAREST);
|
||||
_ = SHCore.GetDpiForMonitor(hMonitor, SHCore.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out uint dpiX, out uint _);
|
||||
return dpiX / wpfDpi;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace BetterGenshinImpact.Helpers.DpiAwareness;
|
||||
|
||||
internal static class DpiAwarenessExtension
|
||||
{
|
||||
public static void InitializeDpiAwareness(this Window window)
|
||||
{
|
||||
_ = new DpiAwarenessController(window);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using BetterGenshinImpact.Helpers.DpiAwareness;
|
||||
using BetterGenshinImpact.ViewModel;
|
||||
using System.Windows.Navigation;
|
||||
using System;
|
||||
using Wpf.Ui;
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
@ -18,6 +18,7 @@ public partial class MainWindow : INavigationWindow
|
||||
DataContext = ViewModel = viewModel;
|
||||
|
||||
InitializeComponent();
|
||||
this.InitializeDpiAwareness();
|
||||
|
||||
SetPageService(pageService);
|
||||
navigationService.SetNavigationControl(RootNavigation);
|
||||
|
@ -1,19 +1,18 @@
|
||||
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||||
using BetterGenshinImpact.GameTask;
|
||||
using BetterGenshinImpact.Helpers;
|
||||
using BetterGenshinImpact.Helpers.DpiAwareness;
|
||||
using BetterGenshinImpact.View.Drawable;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using Vanara.PInvoke;
|
||||
using FontFamily = System.Windows.Media.FontFamily;
|
||||
@ -78,6 +77,8 @@ namespace BetterGenshinImpact.View
|
||||
_maskWindow = this;
|
||||
this.SetResourceReference(StyleProperty, typeof(MaskWindow));
|
||||
InitializeComponent();
|
||||
this.InitializeDpiAwareness();
|
||||
|
||||
LogTextBox.TextChanged += LogTextBoxTextChanged;
|
||||
//AddAreaSettingsControl("测试识别窗口");
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
using OpenCvSharp.Internal;
|
||||
using BetterGenshinImpact.Helpers.DpiAwareness;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
@ -22,6 +20,7 @@ namespace BetterGenshinImpact.View
|
||||
public PickerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.InitializeDpiAwareness();
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user