在我们的项目中,我们保存了窗口大小、位置和最小化/最大化设置,因此当我们重新打开它时,我们可以在完全相同的位置和大小打开窗口。Window-Behavior
使用本文底部的 -class,所有这些都运行良好。
然而,问题是当我们使用 Win 按钮 + 箭头时;这会将屏幕与屏幕的一侧对齐,但这未正确保存在行为中。相反,它保存了我使用Win +箭头对齐它之前的屏幕位置和大小,也就是它再次打开的位置。
我尝试在 - 方法中使用 Window 的,和Left
(Top
注意:在这个方法中是 Window。)但是and似乎偏离了大约 20-40 像素,并使用 , 保存了 Right 和Left并且当前的屏幕宽度/高度(使用多个显示器时)也有点痛苦。ActualWidth
ActualHeight
SaveWindowState
AssociatedObject
Left
Top
ActualWidth
ActualHeight
那么,当用户使用 Win + 箭头对齐窗口然后关闭它时,有什么方法可以在窗口设置中保存正确的位置和大小?
WindowSettingsBehavior
:
using System;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Interop;
namespace NatWa.MidOffice.Behaviors
{
/// <summary>
/// Persists a Window's Size, Location and WindowState to UserScopeSettings
/// </summary>
public class WindowSettingsBehavior : Behavior<Window>
{
[DllImport("user32.dll")]
static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref Windowplacement lpwndpl);
[DllImport("user32.dll")]
static extern bool GetWindowPlacement(IntPtr hWnd, out Windowplacement lpwndpl);
// ReSharper disable InconsistentNaming
const int SW_SHOWNORMAL = 1;
const int SW_SHOWMINIMIZED = 2;
// ReSharper restore InconsistentNaming
internal class WindowApplicationSettings : ApplicationSettingsBase
{
public WindowApplicationSettings(WindowSettingsBehavior windowSettingsBehavior)
: base(windowSettingsBehavior.AssociatedObject.GetType().FullName)
{
}
[UserScopedSetting]
public Windowplacement? Placement
{
get
{
if (this["Placement"] != null)
{
return ((Windowplacement)this["Placement"]);
}
return null;
}
set
{
this["Placement"] = value;
}
}
}
/// <summary>
/// Load the Window Size Location and State from the settings object
/// </summary>
private void LoadWindowState()
{
Settings.Reload();
if (Settings.Placement == null) return;
try
{
// Load window placement details for previous application session from application settings.
// If window was closed on a monitor that is now disconnected from the computer,
// SetWindowPlacement will place the window onto a visible monitor.
var wp = Settings.Placement.Value;
wp.length = Marshal.SizeOf(typeof(Windowplacement));
wp.flags = 0;
wp.showCmd = (wp.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : wp.showCmd);
var hwnd = new WindowInteropHelper(AssociatedObject).Handle;
SetWindowPlacement(hwnd, ref wp);
}
catch (Exception ex)
{
Debug.WriteLine("Failed to load window state:\r\n{0}", ex);
}
}
/// <summary>
/// Save the Window Size, Location and State to the settings object
/// </summary>
private void SaveWindowState()
{
Windowplacement wp;
var hwnd = new WindowInteropHelper(AssociatedObject).Handle;
GetWindowPlacement(hwnd, out wp);
Settings.Placement = wp;
Settings.Save();
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Closing += WindowClosing;
AssociatedObject.SourceInitialized += WindowSourceInitialized;
}
private void WindowSourceInitialized(object sender, EventArgs e)
{
LoadWindowState();
}
private void WindowClosing(object sender, CancelEventArgs e)
{
SaveWindowState();
AssociatedObject.Closing -= WindowClosing;
AssociatedObject.SourceInitialized -= WindowSourceInitialized;
}
private WindowApplicationSettings _windowApplicationSettings;
internal virtual WindowApplicationSettings CreateWindowApplicationSettingsInstance()
{
return new WindowApplicationSettings(this);
}
[Browsable(false)]
internal WindowApplicationSettings Settings
{
get { return _windowApplicationSettings
?? (_windowApplicationSettings = CreateWindowApplicationSettingsInstance()); }
}
}
#region Save position classes
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
private int _left;
private int _top;
private int _right;
private int _bottom;
public Rect(int left, int top, int right, int bottom)
{
_left = left;
_top = top;
_right = right;
_bottom = bottom;
}
public override bool Equals(object obj)
{
if (!(obj is Rect)) return base.Equals(obj);
var rect = (Rect)obj;
return rect._bottom == _bottom &&
rect._left == _left &&
rect._right == _right &&
rect._top == _top;
}
public override int GetHashCode()
{
return _bottom.GetHashCode() ^
_left.GetHashCode() ^
_right.GetHashCode() ^
_top.GetHashCode();
}
public static bool operator ==(Rect a, Rect b)
{
return a._bottom == b._bottom &&
a._left == b._left &&
a._right == b._right &&
a._top == b._top;
}
public static bool operator !=(Rect a, Rect b)
{
return !(a == b);
}
public int Left
{
get { return _left; }
set { _left = value; }
}
public int Top
{
get { return _top; }
set { _top = value; }
}
public int Right
{
get { return _right; }
set { _right = value; }
}
public int Bottom
{
get { return _bottom; }
set { _bottom = value; }
}
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
private int _x;
private int _y;
public Point(int x, int y)
{
_x = x;
_y = y;
}
public int X
{
get { return _x; }
set { _x = value; }
}
public int Y
{
get { return _y; }
set { _y = value; }
}
public override bool Equals(object obj)
{
if (!(obj is Point)) return base.Equals(obj);
var point = (Point)obj;
return point._x == _x && point._y == _y;
}
public override int GetHashCode()
{
return _x.GetHashCode() ^ _y.GetHashCode();
}
public static bool operator ==(Point a, Point b)
{
return a._x == b._x && a._y == b._y;
}
public static bool operator !=(Point a, Point b)
{
return !(a == b);
}
}
[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;
}
#endregion
}