mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-17 18:01:26 +08:00
refactor: 重写记住主界面位置功能 (#4666)
This commit is contained in:
@@ -21,6 +21,16 @@ namespace MaaWpfGui.Constants
|
||||
public const string Localization = "GUI.Localization";
|
||||
public const string MinimizeToTray = "GUI.MinimizeToTray";
|
||||
public const string UseNotify = "GUI.UseNotify";
|
||||
public const string WindowPlacement = "GUI.Placement";
|
||||
public const string LoadWindowPlacement = "GUI.Placement.Load";
|
||||
public const string SaveWindowPlacement = "GUI.Placement.SaveOnClosing";
|
||||
public const string UseAlternateStage = "GUI.UseAlternateStage";
|
||||
public const string HideUnavailableStage = "GUI.HideUnavailableStage";
|
||||
public const string CustomStageCode = "GUI.CustomStageCode";
|
||||
public const string InverseClearMode = "GUI.InverseClearMode";
|
||||
public const string WindowTitlePrefix = "GUI.WindowTitlePrefix";
|
||||
public const string DarkMode = "GUI.DarkMode";
|
||||
|
||||
public const string MonitorNumber = "GUI.Monitor.Number";
|
||||
public const string MonitorWidth = "GUI.Monitor.Width";
|
||||
public const string MonitorHeight = "GUI.Monitor.Height";
|
||||
@@ -30,12 +40,6 @@ namespace MaaWpfGui.Constants
|
||||
public const string WindowHeight = "GUI.Size.Height";
|
||||
public const string LoadPositionAndSize = "GUI.PositionAndSize.Load";
|
||||
public const string SavePositionAndSize = "GUI.PositionAndSize.SaveOnClosing";
|
||||
public const string UseAlternateStage = "GUI.UseAlternateStage";
|
||||
public const string HideUnavailableStage = "GUI.HideUnavailableStage";
|
||||
public const string CustomStageCode = "GUI.CustomStageCode";
|
||||
public const string InverseClearMode = "GUI.InverseClearMode";
|
||||
public const string WindowTitlePrefix = "GUI.WindowTitlePrefix";
|
||||
public const string DarkMode = "GUI.DarkMode";
|
||||
|
||||
public const string AddressHistory = "Connect.AddressHistory";
|
||||
public const string AutoDetect = "Connect.AutoDetect";
|
||||
|
||||
@@ -14,11 +14,15 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using MaaWpfGui.Constants;
|
||||
using MaaWpfGui.Models;
|
||||
using MaaWpfGui.Views.UI;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using Stylet;
|
||||
using Screen = System.Windows.Forms.Screen;
|
||||
using Rect = MaaWpfGui.Models.Rect;
|
||||
|
||||
namespace MaaWpfGui.Helper
|
||||
{
|
||||
@@ -29,40 +33,12 @@ namespace MaaWpfGui.Helper
|
||||
{
|
||||
}
|
||||
|
||||
private readonly string ScreenName = ConfigurationHelper.GetValue(ConfigurationKeys.MonitorNumber, string.Empty);
|
||||
private readonly int ScreenWidth = int.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MonitorWidth, "-1"));
|
||||
private readonly int ScreenHeight = int.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MonitorHeight, "-1"));
|
||||
private static readonly ILogger _logger = Log.ForContext<WindowManager>();
|
||||
|
||||
private static readonly double DefaultDouble = -114514;
|
||||
private readonly double Left = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.PositionLeft, DefaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
private readonly double Top = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.PositionTop, DefaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
private readonly double Width = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.WindowWidth, DefaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
private readonly double Height = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.WindowHeight, DefaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>
|
||||
/// Move MaaWpfGui.RootView
|
||||
/// </summary>
|
||||
private void MoveWindowToDisplay(string displayName, Window window)
|
||||
{
|
||||
if (Math.Abs(Left - DefaultDouble) < 0.01f || Math.Abs(Top - DefaultDouble) < 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var screen = Screen.AllScreens.FirstOrDefault(x => x.DeviceName == displayName);
|
||||
if (screen != null)
|
||||
{
|
||||
var screenRect = screen.Bounds;
|
||||
if (screenRect.Height == ScreenHeight && screenRect.Width == ScreenWidth)
|
||||
{
|
||||
window.WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
window.Left = (int)(screenRect.Left + Left);
|
||||
window.Top = (int)(screenRect.Top + Top);
|
||||
window.Width = Width;
|
||||
window.Height = Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
private readonly bool _loadWindowPlacement = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.LoadWindowPlacement, bool.TrueString));
|
||||
private readonly bool _saveWindowPlacement = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.SaveWindowPlacement, bool.TrueString));
|
||||
private readonly bool _minimizeDirectly = bool.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MinimizeDirectly, bool.FalseString));
|
||||
private readonly bool _minimizeToTray = bool.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MinimizeToTray, bool.FalseString));
|
||||
|
||||
/// <summary>
|
||||
/// Center other windows in MaaWpfGui.RootView
|
||||
@@ -85,20 +61,30 @@ namespace MaaWpfGui.Helper
|
||||
Window window = base.CreateWindow(viewModel, isDialog, ownerViewModel);
|
||||
if (window is RootView)
|
||||
{
|
||||
bool needMoveRootView = bool.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.LoadPositionAndSize, bool.TrueString));
|
||||
if (needMoveRootView)
|
||||
if (_loadWindowPlacement && GetConfiguration(out WindowPlacement wp, window))
|
||||
{
|
||||
MoveWindowToDisplay(ScreenName, window);
|
||||
window.SourceInitialized += (s, e) =>
|
||||
{
|
||||
bool success = SetWindowPlacement(window, ref wp);
|
||||
_logger.Information("Whether the window placement was set successfully: {Success}", success);
|
||||
};
|
||||
}
|
||||
|
||||
bool minimizeDirectly = bool.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MinimizeDirectly, bool.FalseString));
|
||||
if (minimizeDirectly)
|
||||
if (_loadWindowPlacement && _saveWindowPlacement)
|
||||
{
|
||||
window.Closing += (s, e) =>
|
||||
{
|
||||
GetWindowPlacement(window, out WindowPlacement wp);
|
||||
SetConfiguration(wp);
|
||||
};
|
||||
}
|
||||
|
||||
if (_minimizeDirectly)
|
||||
{
|
||||
window.WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
bool minimizeToTray = bool.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MinimizeToTray, bool.FalseString));
|
||||
if (minimizeDirectly && minimizeToTray)
|
||||
if (_minimizeDirectly && _minimizeToTray)
|
||||
{
|
||||
window.ShowInTaskbar = false;
|
||||
window.Visibility = Visibility.Hidden;
|
||||
@@ -111,5 +97,155 @@ namespace MaaWpfGui.Helper
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
private bool SetConfiguration(WindowPlacement wp)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 请在配置文件中修改该部分配置,暂不支持从GUI设置
|
||||
// Please modify this part of configuration in the configuration file.
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LoadWindowPlacement, _loadWindowPlacement.ToString());
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.SaveWindowPlacement, _saveWindowPlacement.ToString());
|
||||
|
||||
return ConfigurationHelper.SetValue(ConfigurationKeys.WindowPlacement, JsonConvert.SerializeObject(wp));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Failed to serialize json string to {Key}", ConfigurationKeys.WindowPlacement);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool GetConfiguration(out WindowPlacement wp, Window window)
|
||||
{
|
||||
wp = default;
|
||||
var jsonStr = ConfigurationHelper.GetValue(ConfigurationKeys.WindowPlacement, string.Empty);
|
||||
if (string.IsNullOrEmpty(jsonStr))
|
||||
{
|
||||
SetOldConfiguration(window);
|
||||
DeleteOldConfiguration();
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wp = JsonConvert.DeserializeObject<WindowPlacement?>(jsonStr) ?? throw new Exception("Failed to parse json string");
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Failed to deserialize json string from {Key}", ConfigurationKeys.WindowPlacement);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool SetWindowPlacement(WindowHandle window, ref WindowPlacement wp)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load window placement details for previous application session from application settings
|
||||
// Note - if window was closed on a monitor that is now disconnected from the computer,
|
||||
// SetWindowPlacement will place the window onto a visible monitor.
|
||||
wp.Length = Marshal.SizeOf(typeof(WindowPlacement));
|
||||
wp.Flags = 0;
|
||||
|
||||
// wp.ShowCmd = wp.ShowCmd == SwShowminimized ? SwShownormal : wp.ShowCmd;
|
||||
wp.ShowCmd = _minimizeDirectly ? SwShowminimized : SwShownormal;
|
||||
return SetWindowPlacement(window.Handle, ref wp);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetWindowPlacement(WindowHandle window, out WindowPlacement wp)
|
||||
{
|
||||
if (GetWindowPlacement(window.Handle, out wp))
|
||||
{
|
||||
// get the aero snap position of the window
|
||||
if (wp.ShowCmd == SwShownormal && GetWindowRect(window.Handle, out Rect rect))
|
||||
{
|
||||
wp.NormalPosition = rect;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Win32 API declarations to set and get window placement
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WindowPlacement lpwndpl);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetWindowPlacement(IntPtr hWnd, out WindowPlacement lpwndpl);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
|
||||
|
||||
private const int SwShownormal = 1;
|
||||
private const int SwShowminimized = 2;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Delete this
|
||||
/// 兼容旧配置,过几个版本删(请直接revert)
|
||||
/// </summary>
|
||||
private void SetOldConfiguration(Window window)
|
||||
{
|
||||
// 初始化
|
||||
string screenName = ConfigurationHelper.GetValue(ConfigurationKeys.MonitorNumber, string.Empty);
|
||||
int screenWidth = int.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MonitorWidth, "-1"));
|
||||
int screenHeight = int.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.MonitorHeight, "-1"));
|
||||
|
||||
double defaultDouble = -114514;
|
||||
double left = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.PositionLeft, defaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
double top = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.PositionTop, defaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
double width = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.WindowWidth, defaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
double height = double.Parse(ConfigurationHelper.GetValue(ConfigurationKeys.WindowHeight, defaultDouble.ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||
|
||||
// Move MaaWpfGui.RootView
|
||||
if (Math.Abs(left - defaultDouble) < 0.01f || Math.Abs(top - defaultDouble) < 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var screen = System.Windows.Forms.Screen.AllScreens.FirstOrDefault(x => x.DeviceName == screenName);
|
||||
if (screen != null)
|
||||
{
|
||||
var screenRect = screen.Bounds;
|
||||
if (screenRect.Height == screenHeight && screenRect.Width == screenWidth)
|
||||
{
|
||||
window.WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
window.Left = (int)(screenRect.Left + left);
|
||||
window.Top = (int)(screenRect.Top + top);
|
||||
window.Width = width;
|
||||
window.Height = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Delete this
|
||||
/// 兼容旧配置,过几个版本删(请直接revert)
|
||||
/// </summary>
|
||||
private void DeleteOldConfiguration()
|
||||
{
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.MonitorNumber);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.MonitorWidth);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.MonitorHeight);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.PositionLeft);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.PositionTop);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.WindowWidth);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.WindowHeight);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.LoadPositionAndSize);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.SavePositionAndSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
src/MaaWpfGui/Models/WindowPlacement.cs
Normal file
62
src/MaaWpfGui/Models/WindowPlacement.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
// <copyright file="WindowPlacement.cs" company="MaaAssistantArknights">
|
||||
// MaaWpfGui - A part of the MaaCoreArknights project
|
||||
// Copyright (C) 2021 MistEO and Contributors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MaaWpfGui.Models
|
||||
{
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WindowPlacement
|
||||
{
|
||||
public int Length;
|
||||
public int Flags;
|
||||
public int ShowCmd;
|
||||
public Point MinPosition;
|
||||
public Point MaxPosition;
|
||||
public Rect NormalPosition;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Rect
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
|
||||
public Rect(int left, int top, int right, int bottom)
|
||||
{
|
||||
Left = left;
|
||||
Top = top;
|
||||
Right = right;
|
||||
Bottom = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Point
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
|
||||
public Point(int x, int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2422,96 +2422,6 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
}
|
||||
}
|
||||
|
||||
private bool _loadGUIParameters = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.LoadPositionAndSize, bool.TrueString));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to load GUI parameters.
|
||||
/// </summary>
|
||||
public bool LoadGUIParameters
|
||||
{
|
||||
get => _loadGUIParameters;
|
||||
set
|
||||
{
|
||||
SetAndNotify(ref _loadGUIParameters, value);
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LoadPositionAndSize, value.ToString());
|
||||
if (value)
|
||||
{
|
||||
if (SaveGUIParametersOnClosing)
|
||||
{
|
||||
Application.Current.MainWindow.Closing += SaveGUIParameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveGUIParameters();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveGUIParametersOnClosing = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.SavePositionAndSize, bool.TrueString));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to save GUI parameters on closing main window.
|
||||
/// </summary>
|
||||
public bool SaveGUIParametersOnClosing
|
||||
{
|
||||
get => _saveGUIParametersOnClosing;
|
||||
set
|
||||
{
|
||||
SetAndNotify(ref _saveGUIParametersOnClosing, value);
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.SavePositionAndSize, value.ToString());
|
||||
if (value)
|
||||
{
|
||||
Application.Current.MainWindow.Closing += SaveGUIParameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Current.MainWindow.Closing -= SaveGUIParameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveGUIParameters(object sender, EventArgs e)
|
||||
{
|
||||
SaveGUIParameters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save main window left edge, top edge, width and heigth.
|
||||
/// </summary>
|
||||
public void SaveGUIParameters()
|
||||
{
|
||||
var mainWindow = Application.Current.MainWindow;
|
||||
if (mainWindow.WindowState != WindowState.Normal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mainWindowRect = new Rect(mainWindow.Left + 25, mainWindow.Top + 25, mainWindow.Width - 50, mainWindow.Height - 50);
|
||||
var virtualScreenRect = new Rect(SystemParameters.VirtualScreenLeft, SystemParameters.VirtualScreenTop, SystemParameters.VirtualScreenWidth, SystemParameters.VirtualScreenHeight);
|
||||
if (!virtualScreenRect.IntersectsWith(mainWindowRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 请在配置文件中修改该部分配置,暂不支持从GUI设置
|
||||
// Please modify this part of configuration in the configuration file.
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LoadPositionAndSize, LoadGUIParameters.ToString());
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.SavePositionAndSize, SaveGUIParametersOnClosing.ToString());
|
||||
|
||||
System.Windows.Forms.Screen currentScreen =
|
||||
System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(mainWindow).Handle);
|
||||
var screenRect = currentScreen.Bounds;
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.MonitorNumber, currentScreen.DeviceName);
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.MonitorWidth, screenRect.Width.ToString());
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.MonitorHeight, screenRect.Height.ToString());
|
||||
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.PositionLeft, (mainWindow.Left - screenRect.Left).ToString(CultureInfo.InvariantCulture));
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.PositionTop, (mainWindow.Top - screenRect.Top).ToString(CultureInfo.InvariantCulture));
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.WindowWidth, mainWindow.Width.ToString(CultureInfo.InvariantCulture));
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.WindowHeight, mainWindow.Height.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
private bool _useAlternateStage = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.UseAlternateStage, bool.FalseString));
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -135,11 +135,6 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
LogItemViewModels = new ObservableCollection<LogItemViewModel>();
|
||||
InitializeItems();
|
||||
InitTimer();
|
||||
|
||||
if (Instances.SettingsViewModel.LoadGUIParameters && Instances.SettingsViewModel.SaveGUIParametersOnClosing)
|
||||
{
|
||||
Application.Current.MainWindow!.Closing += Instances.SettingsViewModel.SaveGUIParameters;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user