读书笔记:窗口位置的保存和恢复
这个保存和恢复指的不同的执行之间,如果想要程序在下一次运行的时候显示在本次运行的相同位置,那么就需要通过一个合适的方法将这些信息保存在合适的位置,虽然保存到文件也不错,不过注册表似乎更方便一点。
直接保存高度、宽度和位置很简单,只是,如果进行保存操作的时候,窗口处于最大化或最小化的状态,那么,下一次进行恢复的时候,可能就无法以正确的并且正常的尺寸显示了,这里还是需要使用两个Windows API函数:
[DllImport("user32.dll")] private static extern bool GetWindowPlacement(IntPtr handle, ref ManagedWindowPlacement placement); [DllImport("user32.dll")] private static extern bool SetWindowPlacement(IntPtr handle, ref ManagedWindowPlacement placement);
只是,这一次有一点麻烦:这两个函数的参数中包含有一个结构。在能够使用这两个函数之前,先要正确地定义好这个结构:
[Serializable] [StructLayout(LayoutKind.Sequential)] private class ManagedPt { public int X = 0; public int Y = 0; public ManagedPt() { } public ManagedPt(int x, int y) { X = x; Y = y; } } [Serializable] [StructLayout(LayoutKind.Sequential)] private class ManagedRect { public int X = 0; public int Y = 0; public int Right = 0; public int Bottom = 0; public ManagedRect() { } public ManagedRect(int x, int y, int right, int bottom) { X = x; Y = y; Right = right; Bottom = bottom; } } [Serializable] [StructLayout(LayoutKind.Sequential)] private class ManagedWindowPlacement { public uint Length = 0; public uint Flags = 0; public uint ShowCmd = 0; public ManagedPt MinPosition = null; public ManagedPt MaxPosition = null; public ManagedRect NormalPosition = null; public ManagedWindowPlacement() { Length = (uint)Marshal.SizeOf(this); } }
现在只剩下了最后一个问题:序列化与反序列化。既然是保存的对象,要恢复的自然也是对象:
ManagedWindowPlacement placement = new ManagedWindowPlacement(); GetWindowPlacement(frm.Handle, ref placement); // 序列化 MemoryStream ms = new MemoryStream(); BinaryFormatter f = new BinaryFormatter(); f.Serialize(ms, placement); //将ms的内容保存就是了 ... MemoryStream ms = new MemoryStream((byte[])key.GetValue("Placement")); //这个是从注册表中提取的,也可以是其他位置 BinaryFormatter f = new BinaryFormatter(); ManagedWindowPlacement placement = (ManagedWindowPlacement) f.Deserialize(ms);//反序列化 SetWindowPlacement(frm.Handle, ref placement);