当窗体大小和位置被用户更改后,如何保存更改后的状态,确保用户再次打开窗体时的状态和最后一次更改保持一致?下面介绍两种有代表性的方法:
c#保存窗体状态——利用与注册表的信息交互实现
在《Pro.dot.NET.2.0.Windows.Forms.and.Custom.Controls.in.C.Sharp》书上介绍了这种方法,具体的可以参见这本书,有电子版下载的。定义一个类FormPositionHelper用来设置和保存当前窗体的大小和位置信息。类设计代码如下:
- using Microsoft.Win32;//这个需加上
- .......
- class FormPositionHelper
- {
- // 在HKEY_CURRENT_USER 设置注册表的路径
- public static string RegPath = @"Software\App\";
- public static void SaveSize(System.Windows.Forms.Form frm)
- {
- //Create or retrieve a reference to a key where the settings
- //will be stored.
- RegistryKey key;
- key = Registry.LocalMachine.CreateSubKey(RegPath + frm.Name);
- key.SetValue("Height", frm.Height);
- key.SetValue("Width", frm.Width);
- key.SetValue("Left", frm.Left);
- key.SetValue("Top", frm.Top);
- }
- public static void SetSize(System.Windows.Forms.Form frm)
- {
- RegistryKey key;
- key=Registry.LocalMachine.OpenSubKey(RegPath+frm.Name);
- if(key!=null)
- {
- frm.Height=(int)key.GetValue("Height");
- frm.Width=(int)key.GetValue("Width");
- frm.Left=(int)key.GetValue("Left");
- frm.Top=(int)key.GetValue("Top");
- }
- }
- }
然后分别在窗体第一次加载和关闭之前调用上述类中的两个方法,具体如下:
- private void Form1_Load(object sender, EventArgs e)
- {
- FormPositionHelper.SetSize(this);
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- //必须加上这个判断,否则窗体最小化后无法恢复和还原了
- if (this.WindowState != FormWindowState.Minimized)
- FormPositionHelper.SaveSize(this);
- }
c#保存窗体状态——利用Settings(设置)完成
这个是在codeproject上讲解到的另一种方法,地址是http://www.codeproject.com/KB/cs/UserSettings.aspx 当然是英文的啦~
注意:在Settings.settings文件中定义配置字段。把作用范围定义为:User则运行时可更改,Applicatiion则运行时不可更改。当设置scope为User时他的配置放在 C:\Documents and Settings\LocalService\Local Settings\Application Data\在这个目录下或子目录user.config 配置文件中。
具体实现方法如下:
a.打开项目属性-》设置 如下图:
b.在需要保存状态的窗体顶部添加using CtrlStudy.Properties;//CtrlStudy为项目名称
c.代码设计:
- private void Form1_Load(object sender, EventArgs e)
- {
- if (Settings.Default.WindowLocation != null)
- {
- this.Location = Settings.Default.WindowLocation;
- }
- if (Settings.Default.WindowSize != null)
- {
- this.Size = Settings.Default.WindowSize;
- }
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- Settings.Default.WindowLocation = this.Location;
- if (this.WindowState == FormWindowState.Normal)
- {
- Settings.Default.WindowSize = this.Size;
- }
- else
- {
- Settings.Default.WindowSize = this.RestoreBounds.Size;
- }
- if (this.WindowState != FormWindowState.Minimized)
- Settings.Default.Save();//使用Save方法保存更改
- }
需要的时候可以采用Settings.Default.Reset()方法将属性值还原为默认值,即在上图中手动设置的值。
上面介绍到的方法虽然能够解决我们所提出的问题,但是不够理想,对窗体的两个特殊状态(最大化和最小化)实则做了偷懒处理,即对于非正常状态下的状态更改不予以保存。所以解决不了窗体在最小化时能够还原和最大化时能够最小的转换处理。
针对这个问题,提出一种新的解决方案,即采用WIN32中的GetWindowPlacement()和SetWindowPlacement()方法,两个方法的定义大家可以查下资料,这里就不再作介绍了。当然这个方法也是我在前面提到的电子书《Pro.dot.NET.2.0.Windows.Forms.and.Custom.Controls.in.C.Sharp》上发现的,觉得不错,赶紧总结总结记录下来了。顺道在这里推荐在下这本关于控件开发的书,有VB和C#版本的,它从控件、窗体的基础讲起,直到向大家讲解如何开发一个满足自己需求的控件,当然里面也介绍到了控件和组件编程的其他知识,还是很不错的一本书,可惜只有英文的啦,目前正在研读中。。。。
转入正题,同前,合理应用上面GetWindowPlacement()和SetWindowPlacement()方法设计设置和保存窗体状态的类如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Runtime.InteropServices; //注意这几个命名空间的引入
- using Microsoft.Win32;
- using System.IO;
- using System.Runtime.Serialization.Formatters.Binary;
- namespace CtrlStudy
- {
- class FormPositionHelper2
- {
- [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] //必须加上,否则后面会提示为非可序列化标记
- public struct ManagedWindowPlacement
- {
- public int length;
- public int flags;
- public int showCmd;
- public Point ptMinPosition;
- public Point ptMaxPosition;
- public Rectangle rcNormalPosition;
- }
- public static string RegPath = @"Software\App\";
- public static void SaveSize(System.Windows.Forms.Form frm)
- {
- RegistryKey key;
- key = Registry.LocalMachine.CreateSubKey(RegPath + frm.Name);
- // Get the window placement.
- ManagedWindowPlacement placement = new ManagedWindowPlacement();
- GetWindowPlacement(frm.Handle, ref placement);
- // Serialize it.
- MemoryStream ms = new MemoryStream();
- BinaryFormatter f = new BinaryFormatter();
- f.Serialize(ms, placement);
- // Store it as a byte array.
- key.SetValue("Placement", ms.ToArray());
- }
- public static void SetSize(System.Windows.Forms.Form frm)
- {
- RegistryKey key;
- key = Registry.LocalMachine.OpenSubKey(RegPath + frm.Name);
- if (key != null)
- {
- MemoryStream ms = new MemoryStream((byte[])key.GetValue("Placement"));
- BinaryFormatter f = new BinaryFormatter();
- ManagedWindowPlacement placement = (ManagedWindowPlacement)
- f.Deserialize(ms);
- SetWindowPlacement(frm.Handle, ref placement);
- }
- }
- }
- }
这个方法比较完善,其实序列在很早就提出来了。有时间还得专门研究研究这个序列化的问题,后面还会不断研究并总结的。
好了,C#保存窗体状态的方法就给大家介绍到这里。
【编辑推荐】