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