Save and Restore Form Position and Size

前端 未结 8 2149
说谎
说谎 2020-12-14 04:36

In a WinForms 2.0 C# application, what is the typical method used for saving and restoring form position and size in an application?

Related, is it possible to add n

相关标签:
8条回答
  • 2020-12-14 05:39
    private void Form1_Load( object sender, EventArgs e )
    {
        // restore location and size of the form on the desktop
        this.DesktopBounds =
            new Rectangle(Properties.Settings.Default.Location,
        Properties.Settings.Default.Size);
        // restore form's window state
        this.WindowState = ( FormWindowState )Enum.Parse(
            typeof(FormWindowState),
            Properties.Settings.Default.WindowState);
    }
    
    private void Form1_FormClosing( object sender, FormClosingEventArgs e )
    {
        System.Drawing.Rectangle bounds = this.WindowState != FormWindowState.Normal ? this.RestoreBounds : this.DesktopBounds;
        Properties.Settings.Default.Location = bounds.Location;
        Properties.Settings.Default.Size = bounds.Size;
        Properties.Settings.Default.WindowState =
            Enum.GetName(typeof(FormWindowState), this.WindowState);
        // persist location ,size and window state of the form on the desktop
        Properties.Settings.Default.Save();
    }
    
    0 讨论(0)
  • 2020-12-14 05:39

    There is actually a real lack of a single, "just works" solution to this anywhere on the internet, so here's my own creation:

    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();
        }
    }
    

    This implementation stores the position and size of a form in HKCU/Software/<CompanyId()>/<AppId()>/Window State/<form name>. It won't restore settings if the monitor configuration changes as so to prevent windows being restored off screen.

    Obviously this can't handle multiple instances of the same form. I also specifically disabled restoring minimised but that's an easy fix of the source.

    The above is designed to be dropped into its own .cs file and never touched again. You have to instantiate a local namespace copy like this (in Program.cs or your plugin main .cs file or wherever):

    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>"; }
        }
        ....
    

    Now you have a non-abstract instantiation in the main namespace. So, to use, add this to the forms you want saved and restored:

        private void IssuesForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            new WindowSettings(this).save();
        }
    
        private void IssuesForm_Load(object sender, EventArgs e)
        {
            new WindowSettings(this).load();
        }
    

    Obviously feel free to customise to your own purposes. No warranty is expressed or implied. Use at your own risk - I disclaim any copyright.

    Niall

    0 讨论(0)
提交回复
热议问题