diff --git a/src/Snap.Hutao/SettingsUI/Styles/Button.xaml b/src/Snap.Hutao/SettingsUI/Styles/Button.xaml index 871b51c5..c1827fea 100644 --- a/src/Snap.Hutao/SettingsUI/Styles/Button.xaml +++ b/src/Snap.Hutao/SettingsUI/Styles/Button.xaml @@ -7,7 +7,7 @@ diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/POINT.cs b/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/POINT.cs new file mode 100644 index 00000000..ccdb9103 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/POINT.cs @@ -0,0 +1,10 @@ +namespace Windows.Win32.Foundation; + +public partial struct POINT +{ + public POINT(int x,int y) + { + this.x = x; + this.y = y; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/RECT.cs b/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/RECT.cs new file mode 100644 index 00000000..45fd53b3 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao.Win32/Foundation/RECT.cs @@ -0,0 +1,19 @@ +namespace Windows.Win32.Foundation; +public partial struct RECT +{ + public RECT(int left, int top, int right, int bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public int Size + { + get + { + return (right - left) * (bottom - top); + } + } +} diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/UI/WindowsAndMessaging/WINDOWPLACEMENT.cs b/src/Snap.Hutao/Snap.Hutao.Win32/UI/WindowsAndMessaging/WINDOWPLACEMENT.cs new file mode 100644 index 00000000..0e7f5119 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao.Win32/UI/WindowsAndMessaging/WINDOWPLACEMENT.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; +using Windows.Win32.Foundation; + +namespace Windows.Win32.UI.WindowsAndMessaging; +public partial struct WINDOWPLACEMENT +{ + /// + /// Gets the default (empty) value. + /// + public static WINDOWPLACEMENT Default + { + get + { + return new WINDOWPLACEMENT() + { + length = (uint)Marshal.SizeOf(), + }; + } + } + + /// + /// 构造一个新的 + /// + /// 最大点 + /// 正常位置 + /// 显示命令 + /// 窗体位置 + public static WINDOWPLACEMENT Create(POINT ptMaxPosition, RECT rcNormalPosition, SHOW_WINDOW_CMD showCmd) + { + WINDOWPLACEMENT result = Default; + + result.ptMaxPosition = ptMaxPosition; + result.rcNormalPosition = rcNormalPosition; + result.showCmd = showCmd; + + return result; + } +} diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/Unsafe.cs b/src/Snap.Hutao/Snap.Hutao.Win32/Unsafe.cs new file mode 100644 index 00000000..28a85b6e --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao.Win32/Unsafe.cs @@ -0,0 +1,18 @@ +using Windows.Win32.UI.WindowsAndMessaging; + +namespace Snap.Hutao.Win32; +public class Unsafe +{ + /// + /// 使用指针操作简化封送 + /// + /// + /// + /// + public static unsafe void SetMinTrackSize(nint lPARAM, float minWidth, float minHeight) + { + MINMAXINFO* rect2 = (MINMAXINFO*)lPARAM; + rect2->ptMinTrackSize.x = (int)Math.Max(minWidth, rect2->ptMinTrackSize.x); + rect2->ptMinTrackSize.y = (int)Math.Max(minHeight, rect2->ptMinTrackSize.y); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml b/src/Snap.Hutao/Snap.Hutao/App.xaml index 43009bea..b3b425fb 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml @@ -25,7 +25,6 @@ 6,6,0,0 0,6,6,0 0,0,6,6 - 4 diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/ContentDialogBehavior.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/ContentDialogBehavior.cs new file mode 100644 index 00000000..4f871435 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/ContentDialogBehavior.cs @@ -0,0 +1,34 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.WinUI.UI.Behaviors; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Shapes; + +namespace Snap.Hutao.Control.Behavior; + +/// +/// Make ContentDialog's SmokeLayerBackground dsiplay over custom titleBar +/// +public class ContentDialogBehavior : BehaviorBase +{ + /// + protected override void OnAssociatedObjectLoaded() + { + DependencyObject parent = VisualTreeHelper.GetParent(AssociatedObject); + DependencyObject child = VisualTreeHelper.GetChild(parent, 2); + Rectangle smokeLayerBackground = (Rectangle)child; + + smokeLayerBackground.Margin = new Thickness(0); + smokeLayerBackground.RegisterPropertyChangedCallback(FrameworkElement.MarginProperty, OnMarginChanged); + } + + private static void OnMarginChanged(DependencyObject sender, DependencyProperty property) + { + if (property == FrameworkElement.MarginProperty) + { + sender.ClearValue(property); + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Logging/EventIds.cs b/src/Snap.Hutao/Snap.Hutao/Core/Logging/EventIds.cs index 97c405d1..b0040760 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Logging/EventIds.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Logging/EventIds.cs @@ -78,4 +78,9 @@ internal static class EventIds /// 背景状态 /// public static readonly EventId BackdropState = 200001; + + /// + /// 子类控制 + /// + public static readonly EventId SubClassing = 200002; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/WindowManager.cs b/src/Snap.Hutao/Snap.Hutao/Core/WindowManager.cs index 74c36215..607df41f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/WindowManager.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/WindowManager.cs @@ -5,30 +5,30 @@ using Microsoft.UI.Xaml; using Snap.Hutao.Control.HostBackdrop; using Snap.Hutao.Core.Logging; using Snap.Hutao.Core.Setting; -using System.Runtime.InteropServices; -using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.UI.Shell; using Windows.Win32.UI.WindowsAndMessaging; using WinRT.Interop; +using static Windows.Win32.PInvoke; + namespace Snap.Hutao.Core; /// -/// 窗口状态管理器 -/// 主要包含了各类 P/Inoke 代码 +/// 窗口管理器 +/// 主要包含了针对窗体的 P/Inoke 逻辑 /// internal class WindowManager { - private const int MinWidth = 800; - private const int MinHeight = 600; - + private const int MinWidth = 848; + private const int MinHeight = 524; + private const int SubclassId = 101; private readonly HWND handle; private readonly Window window; private readonly UIElement titleBar; private readonly ILogger logger; - // We have to explictly hold a reference to the SUBCLASSPROC + // We have to explictly hold a reference to the SUBCLASSPROC, // otherwise will casuse System.ExecutionEngineException private SUBCLASSPROC? subClassProc; @@ -53,17 +53,14 @@ internal class WindowManager int right = LocalSetting.GetValueType(SettingKeys.WindowRight); int bottom = LocalSetting.GetValueType(SettingKeys.WindowBottom); - return new() { left = left, top = top, right = right, bottom = bottom }; + return new(left, top, right, bottom); } private static void SaveWindowRect(HWND handle) { - WINDOWPLACEMENT windowPlacement = new() - { - length = (uint)Marshal.SizeOf(), - }; + WINDOWPLACEMENT windowPlacement = WINDOWPLACEMENT.Default; - PInvoke.GetWindowPlacement(handle, ref windowPlacement); + GetWindowPlacement(handle, ref windowPlacement); LocalSetting.Set(SettingKeys.WindowLeft, windowPlacement.rcNormalPosition.left); LocalSetting.Set(SettingKeys.WindowTop, windowPlacement.rcNormalPosition.top); @@ -77,52 +74,42 @@ internal class WindowManager window.SetTitleBar(titleBar); window.Closed += OnWindowClosed; - PInvoke.SetWindowText(handle, "胡桃"); + SetWindowText(handle, "胡桃"); RECT rect = RetriveWindowRect(); - if ((rect.right - rect.left) * (rect.bottom - rect.top) > 0) + if (rect.Size > 0) { - WINDOWPLACEMENT windowPlacement = new() - { - length = (uint)Marshal.SizeOf(), - showCmd = SHOW_WINDOW_CMD.SW_SHOWNORMAL, - ptMaxPosition = new() { x = -1, y = -1 }, - rcNormalPosition = rect, - }; - - PInvoke.SetWindowPlacement(handle, in windowPlacement); + WINDOWPLACEMENT windowPlacement = WINDOWPLACEMENT.Create(new(-1, -1), rect, SHOW_WINDOW_CMD.SW_SHOWNORMAL); + SetWindowPlacement(handle, in windowPlacement); } bool micaApplied = new SystemBackdrop(window).TrySetBackdrop(); logger.LogInformation(EventIds.BackdropState, "Apply {name} : {result}", nameof(SystemBackdrop), micaApplied ? "succeed" : "failed"); - subClassProc = new(OnWindowProcedure); - _ = PInvoke.SetWindowSubclass(handle, subClassProc, 101, 0); + subClassProc = new(OnSubclassProcedure); + bool subClassApplied = SetWindowSubclass(handle, subClassProc, SubclassId, 0); + logger.LogInformation(EventIds.SubClassing, "Apply {name} : {result}", nameof(SUBCLASSPROC), subClassApplied ? "succeed" : "failed"); } private void OnWindowClosed(object sender, WindowEventArgs args) { - PInvoke.RemoveWindowSubclass(handle, subClassProc, 101); + RemoveWindowSubclass(handle, subClassProc, SubclassId); subClassProc = null; SaveWindowRect(handle); } - private LRESULT OnWindowProcedure(HWND hwnd, uint uMsg, WPARAM wParam, LPARAM lParam, nuint uIdSubclass, nuint dwRefData) + private LRESULT OnSubclassProcedure(HWND hwnd, uint uMsg, WPARAM wParam, LPARAM lParam, nuint uIdSubclass, nuint dwRefData) { switch (uMsg) { - case PInvoke.WM_GETMINMAXINFO: + case WM_GETMINMAXINFO: { - uint dpi = PInvoke.GetDpiForWindow(handle); + uint dpi = GetDpiForWindow(handle); float scalingFactor = dpi / 96f; - - MINMAXINFO minMaxInfo = Marshal.PtrToStructure(lParam); - minMaxInfo.ptMinTrackSize.x = (int)Math.Max(MinWidth * scalingFactor, minMaxInfo.ptMinTrackSize.x); - minMaxInfo.ptMinTrackSize.y = (int)Math.Max(MinHeight * scalingFactor, minMaxInfo.ptMinTrackSize.y); - Marshal.StructureToPtr(minMaxInfo, lParam, true); + Win32.Unsafe.SetMinTrackSize(lParam, MinWidth * scalingFactor, MinHeight * scalingFactor); break; } } - return PInvoke.DefSubclassProc(hwnd, uMsg, wParam, lParam); + return DefSubclassProc(hwnd, uMsg, wParam, lParam); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml index b1489dea..5adb851c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml @@ -1,11 +1,12 @@  - + + + + + Margin="0,8,0,0" + Icon="" + Header="手动获取" + Description="进入我们的文档页面并按指示操作" + HorizontalAlignment="Stretch"> + Margin="12,0,0,0" + Padding="4" + Content="立即前往" + NavigateUri="https://www.snapgenshin.com/documents/features/mhy-account-switch.html#%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96-cookie"/> diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs index 683d15c6..49209b54 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Core.Threading; @@ -15,7 +16,7 @@ public sealed partial class UserDialog : ContentDialog /// 构造一个新的添加用户对话框 /// /// 呈现的父窗口 - public UserDialog(Microsoft.UI.Xaml.Window window) + public UserDialog(Window window) { InitializeComponent(); XamlRoot = window.Content.XamlRoot; diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs index f68ebfcf..15a4bb68 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs @@ -29,6 +29,6 @@ public sealed partial class MainView : UserControl navigationService = Ioc.Default.GetRequiredService(); navigationService.Initialize(NavView, ContentFrame); - //navigationService.Navigate(INavigationAwaiter.Default, true); + navigationService.Navigate(INavigationAwaiter.Default, true); } } \ No newline at end of file