在我们的项目中,我们保存了窗口大小,位置和最小化/最大化设置,因此我们可以在重新打开窗口时以完全相同的点和大小打开窗口.所有这一切都运行得很好,使用了本文底部的Window-Behavior-class.
但问题是,当我们使用Win-button箭头时;这会将屏幕与屏幕一侧对齐,但这并未正确保存在行为中.相反,它在我使用Win箭头对齐它之前保存了屏幕的位置和大小,这就是它再次打开的位置.
我试图在SaveWindowState方法中使用Window的Left,Top,ActualWidth和ActualHeight(注意:此方法中的AssociatedObject是Window.)但是Left和Top似乎关闭了大约20-40像素,并且使用ActualWidth,ActualHeight和当前屏幕宽度/高度(使用多个显示器时)保存Right和Left也有点痛苦.
那么,当用户使用Win箭头对齐Window然后关闭它时,有没有办法在窗口设置中保存正确的位置和大小?
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 }
解决方法
您是否尝试过System.Windows.Window实例而不是p / invoke?
我使用两个简单的方法来保存和设置窗口位置使用这个类,它可以在不同的应用程序,架构,客户端,Windows操作系统,有或没有Aero的情况下完美地工作…
我使用两个简单的方法来保存和设置窗口位置使用这个类,它可以在不同的应用程序,架构,客户端,Windows操作系统,有或没有Aero的情况下完美地工作…
void SetWindowPosition() { this.Left = Settings.Default.WindowPositionLeft; this.Top = Settings.Default.WindowPositionTop; } void SaveWindowPosition() { Settings.Default.WindowPositionTop = this.Top; Settings.Default.WindowPositionLeft = this.Left; Settings.Default.Save(); }
或者我错过了什么?