1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-02 04:29:28 +00:00
6502bench/CommonWPF/WindowPlacement.cs
Andy McFadden ea6125ea82 Save and restore grid column widths
Now preserving column widths for the three DataGrids and the main
ListView.  In theory the various grids would conveniently auto-size
to the content, but in practice that doesn't work well with
virtualization.

There is, of course, no simple "the width has changed" event
provided by the control.  On the plus side, you can attach a
property-change event handler to pretty much anything, so once you
know the trick it's possible to make everything work.  Yay WPF.
2019-06-20 15:10:35 -07:00

130 lines
4.7 KiB
C#

/*
* This comes from a blog entry, posted by RandomEngy on March 8 2010:
* https://blogs.msdn.microsoft.com/davidrickard/2010/03/08/saving-window-size-and-location-in-wpf-and-winforms/
* (see https://stackoverflow.com/a/2406604/294248 for discussion)
*
* Saving and restoring a window's size and position can be tricky when there are multiple
* displays involved. This uses the Win32 system functions to do the job properly and
* consistently. (In theory.)
*
* The code works for WinForms (save on FormClosing, restore on Load, using the native handle
* from the Handle property) and WPF (use the Window extension methods provided below, in
* Closing and SourceInitialized). Besides convenience, it has the added benefit of being able
* to capture the non-maximized values for a maximized window.
*/
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Xml;
using System.Xml.Serialization;
namespace CommonWPF {
// RECT structure required by WINDOWPLACEMENT structure
[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) {
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
// POINT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct POINT {
public int X;
public int Y;
public POINT(int x, int y) {
this.X = x;
this.Y = y;
}
}
// WINDOWPLACEMENT stores the position, size, and state of a window
[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;
}
public static class WindowPlacement {
private static Encoding encoding = new UTF8Encoding();
private static XmlSerializer serializer = new XmlSerializer(typeof(WINDOWPLACEMENT));
[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);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
public static void SetPlacement(IntPtr windowHandle, string placementXml) {
if (string.IsNullOrEmpty(placementXml)) {
return;
}
WINDOWPLACEMENT placement;
byte[] xmlBytes = encoding.GetBytes(placementXml);
try {
using (MemoryStream memoryStream = new MemoryStream(xmlBytes)) {
placement = (WINDOWPLACEMENT)serializer.Deserialize(memoryStream);
}
placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
placement.flags = 0;
placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
SetWindowPlacement(windowHandle, ref placement);
} catch (InvalidOperationException) {
// Parsing placement XML failed. Fail silently.
}
}
public static string GetPlacement(IntPtr windowHandle) {
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
GetWindowPlacement(windowHandle, out placement);
using (MemoryStream memoryStream = new MemoryStream()) {
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8)) {
serializer.Serialize(xmlTextWriter, placement);
byte[] xmlBytes = memoryStream.ToArray();
return encoding.GetString(xmlBytes);
}
}
}
//
// Extension methods for WPF.
//
// Call from Closing event. Returns XML string with placement info.
public static string GetPlacement(this Window window) {
return GetPlacement(new WindowInteropHelper(window).Handle);
}
// Call from SourceInitialized event, passing in string from GetPlacement().
public static void SetPlacement(this Window window, string placementXml) {
SetPlacement(new WindowInteropHelper(window).Handle, placementXml);
}
}
}