如何實現(xiàn)C#保存窗體狀態(tài)
當(dāng)窗體大小和位置被用戶更改后,如何保存更改后的狀態(tài),確保用戶再次打開窗體時的狀態(tài)和最后一次更改保持一致?下面介紹兩種有代表性的方法:
c#保存窗體狀態(tài)——利用與注冊表的信息交互實現(xiàn)
在《Pro.dot.NET.2.0.Windows.Forms.and.Custom.Controls.in.C.Sharp》書上介紹了這種方法,具體的可以參見這本書,有電子版下載的。定義一個類FormPositionHelper用來設(shè)置和保存當(dāng)前窗體的大小和位置信息。類設(shè)計代碼如下:
- using Microsoft.Win32;//這個需加上
 - .......
 - class FormPositionHelper
 - {
 - // 在HKEY_CURRENT_USER 設(shè)置注冊表的路徑
 - 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");
 - }
 - }
 - }
 
然后分別在窗體第一次加載和關(guān)閉之前調(diào)用上述類中的兩個方法,具體如下:
- private void Form1_Load(object sender, EventArgs e)
 - {
 - FormPositionHelper.SetSize(this);
 - }
 - private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 - {
 - //必須加上這個判斷,否則窗體最小化后無法恢復(fù)和還原了
 - if (this.WindowState != FormWindowState.Minimized)
 - FormPositionHelper.SaveSize(this);
 - }
 
c#保存窗體狀態(tài)——利用Settings(設(shè)置)完成
這個是在codeproject上講解到的另一種方法,地址是http://www.codeproject.com/KB/cs/UserSettings.aspx 當(dāng)然是英文的啦~
注意:在Settings.settings文件中定義配置字段。把作用范圍定義為:User則運行時可更改,Applicatiion則運行時不可更改。當(dāng)設(shè)置scope為User時他的配置放在 C:\Documents and Settings\LocalService\Local Settings\Application Data\在這個目錄下或子目錄user.config 配置文件中。
具體實現(xiàn)方法如下:
a.打開項目屬性-》設(shè)置 如下圖:
b.在需要保存狀態(tài)的窗體頂部添加using CtrlStudy.Properties;//CtrlStudy為項目名稱
c.代碼設(shè)計:
- 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()方法將屬性值還原為默認(rèn)值,即在上圖中手動設(shè)置的值。
上面介紹到的方法雖然能夠解決我們所提出的問題,但是不夠理想,對窗體的兩個特殊狀態(tài)(最大化和最小化)實則做了偷懶處理,即對于非正常狀態(tài)下的狀態(tài)更改不予以保存。所以解決不了窗體在最小化時能夠還原和最大化時能夠最小的轉(zhuǎn)換處理。
針對這個問題,提出一種新的解決方案,即采用WIN32中的GetWindowPlacement()和SetWindowPlacement()方法,兩個方法的定義大家可以查下資料,這里就不再作介紹了。當(dāng)然這個方法也是我在前面提到的電子書《Pro.dot.NET.2.0.Windows.Forms.and.Custom.Controls.in.C.Sharp》上發(fā)現(xiàn)的,覺得不錯,趕緊總結(jié)總結(jié)記錄下來了。順道在這里推薦在下這本關(guān)于控件開發(fā)的書,有VB和C#版本的,它從控件、窗體的基礎(chǔ)講起,直到向大家講解如何開發(fā)一個滿足自己需求的控件,當(dāng)然里面也介紹到了控件和組件編程的其他知識,還是很不錯的一本書,可惜只有英文的啦,目前正在研讀中。。。。
轉(zhuǎn)入正題,同前,合理應(yīng)用上面GetWindowPlacement()和SetWindowPlacement()方法設(shè)計設(shè)置和保存窗體狀態(tài)的類如下:
- 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] //必須加上,否則后面會提示為非可序列化標(biāo)記
 - 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);
 - }
 - }
 - }
 - }
 
這個方法比較完善,其實序列在很早就提出來了。有時間還得專門研究研究這個序列化的問題,后面還會不斷研究并總結(jié)的。
好了,C#保存窗體狀態(tài)的方法就給大家介紹到這里。
【編輯推薦】
















 
 
 
 
 
 
 