实际上,互联网上任何地方都没有一个单一的“有效”解决方案,所以这是我自己的创作:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;
using System.ComponentModel;
using System.Security.Cryptography;
namespace nedprod
{
abstract public class WindowSettings
{
private Form form;
public FormWindowState state;
public Point location;
public Size size;
public WindowSettings(Form _form)
{
this.form = _form;
}
internal class MD5Sum
{
static MD5CryptoServiceProvider engine = new MD5CryptoServiceProvider();
private byte[] sum = engine.ComputeHash(BitConverter.GetBytes(0));
public MD5Sum() { }
public MD5Sum(string s)
{
for (var i = 0; i < sum.Length; i++)
sum[i] = byte.Parse(s.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
public void Add(byte[] data)
{
byte[] temp = new byte[sum.Length + data.Length];
var i=0;
for (; i < sum.Length; i++)
temp[i] = sum[i];
for (; i < temp.Length; i++)
temp[i] = data[i - sum.Length];
sum=engine.ComputeHash(temp);
}
public void Add(int data)
{
Add(BitConverter.GetBytes(data));
}
public void Add(string data)
{
Add(Encoding.UTF8.GetBytes(data));
}
public static bool operator ==(MD5Sum a, MD5Sum b)
{
if (a.sum == b.sum) return true;
if (a.sum.Length != b.sum.Length) return false;
for (var i = 0; i < a.sum.Length; i++)
if (a.sum[i] != b.sum[i]) return false;
return true;
}
public static bool operator !=(MD5Sum a, MD5Sum b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
try
{
return (bool)(this == (MD5Sum)obj);
}
catch
{
return false;
}
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
for (var i = 0; i < sum.Length; i++)
sb.Append(sum[i].ToString("x2"));
return sb.ToString();
}
}
private MD5Sum screenconfig()
{
MD5Sum md5=new MD5Sum();
md5.Add(Screen.AllScreens.Length); // Hash the number of screens
for(var i=0; i<Screen.AllScreens.Length; i++)
{
md5.Add(Screen.AllScreens[i].Bounds.ToString()); // Hash the dimensions of this screen
}
return md5;
}
public void load()
{
using (RegistryKey r = Registry.CurrentUser.OpenSubKey(@"Software\" + CompanyId() + @"\" + AppId() + @"\Window State\" + form.Name))
{
if (r != null)
{
try
{
string _location = (string)r.GetValue("location"), _size = (string)r.GetValue("size");
state = (FormWindowState)r.GetValue("state");
location = (Point)TypeDescriptor.GetConverter(typeof(Point)).ConvertFromInvariantString(_location);
size = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFromInvariantString(_size);
// Don't do anything if the screen config has since changed (otherwise windows vanish off the side)
if (screenconfig() == new MD5Sum((string) r.GetValue("screenconfig")))
{
form.Location = location;
form.Size = size;
// Don't restore if miminised (it's unhelpful as the user misses the fact it's opened)
if (state != FormWindowState.Minimized)
form.WindowState = state;
}
}
catch (Exception)
{
}
}
}
}
public void save()
{
state = form.WindowState;
if (form.WindowState == FormWindowState.Normal)
{
size = form.Size;
location = form.Location;
}
else
{
size = form.RestoreBounds.Size;
location = form.RestoreBounds.Location;
}
using (RegistryKey r = Registry.CurrentUser.CreateSubKey(@"Software\" + CompanyId()+@"\"+AppId() + @"\Window State\" + form.Name, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
r.SetValue("state", (int) state, RegistryValueKind.DWord);
r.SetValue("location", location.X.ToString() + "," + location.Y.ToString(), RegistryValueKind.String);
r.SetValue("size", size.Width.ToString()+","+size.Height.ToString(), RegistryValueKind.String);
r.SetValue("screenconfig", screenconfig().ToString(), RegistryValueKind.String);
}
}
abstract protected string CompanyId();
abstract protected string AppId();
}
}
此实现将表单的位置和大小存储在 HKCU/Software/<CompanyId()>/<AppId()>/Window State/<form name> 中。如果显示器配置发生更改,它不会恢复设置,以防止窗口在屏幕外恢复。
显然这不能处理同一表单的多个实例。我还专门禁用了还原最小化,但这是源的简单修复。
上面的内容旨在放入其自己的 .cs 文件中,并且再也不会被触及。您必须像这样实例化一个本地命名空间副本(在 Program.cs 或您的插件主 .cs 文件或任何地方):
namespace <your app/plugin namespace name>
{
public class WindowSettings : nedprod.WindowSettings
{
public WindowSettings(Form form) : base(form) { }
protected override string CompanyId() { return "<your company name>"; }
protected override string AppId() { return "<your app name>"; }
}
....
现在您在主命名空间中有一个非抽象实例化。因此,要使用,请将其添加到您要保存和恢复的表单中:
private void IssuesForm_FormClosing(object sender, FormClosingEventArgs e)
{
new WindowSettings(this).save();
}
private void IssuesForm_Load(object sender, EventArgs e)
{
new WindowSettings(this).load();
}
显然,您可以根据自己的目的随意定制。没有任何明示或暗示的保证。使用风险自负 - 我否认任何版权。
尼尔