如何實現(xiàn)C#保存窗體狀態(tài)
當窗體大小和位置被用戶更改后,如何保存更改后的狀態(tài),確保用戶再次打開窗體時的狀態(tài)和最后一次更改保持一致?下面介紹兩種有代表性的方法:
c#保存窗體狀態(tài)——利用與注冊表的信息交互實現(xiàn)
在《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#保存窗體狀態(tài)——利用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 配置文件中。
具體實現(xiàn)方法如下:
a.打開項目屬性-》設置 如下圖:
b.在需要保存狀態(tài)的窗體頂部添加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()方法將屬性值還原為默認值,即在上圖中手動設置的值。
上面介紹到的方法雖然能夠解決我們所提出的問題,但是不夠理想,對窗體的兩個特殊狀態(tài)(最大化和最小化)實則做了偷懶處理,即對于非正常狀態(tài)下的狀態(tài)更改不予以保存。所以解決不了窗體在最小化時能夠還原和最大化時能夠最小的轉換處理。
針對這個問題,提出一種新的解決方案,即采用WIN32中的GetWindowPlacement()和SetWindowPlacement()方法,兩個方法的定義大家可以查下資料,這里就不再作介紹了。當然這個方法也是我在前面提到的電子書《Pro.dot.NET.2.0.Windows.Forms.and.Custom.Controls.in.C.Sharp》上發(fā)現(xiàn)的,覺得不錯,趕緊總結總結記錄下來了。順道在這里推薦在下這本關于控件開發(fā)的書,有VB和C#版本的,它從控件、窗體的基礎講起,直到向大家講解如何開發(fā)一個滿足自己需求的控件,當然里面也介紹到了控件和組件編程的其他知識,還是很不錯的一本書,可惜只有英文的啦,目前正在研讀中。。。。
轉入正題,同前,合理應用上面GetWindowPlacement()和SetWindowPlacement()方法設計設置和保存窗體狀態(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] //必須加上,否則后面會提示為非可序列化標記
- 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#保存窗體狀態(tài)的方法就給大家介紹到這里。
【編輯推薦】