2008-09-18 31 views
10

Trong ứng dụng WinForms 2.0 C#, phương pháp điển hình được sử dụng để lưu và khôi phục vị trí và kích thước của biểu mẫu trong một ứng dụng là gì?Lưu và Khôi phục Vị trí và Kích cỡ của Biểu mẫu

Có liên quan, có thể thêm cài đặt ứng dụng Phạm vi người dùng mới AT RUNTIME không? Tôi hoàn toàn thấy làm thế nào để thêm các thiết lập tại thời điểm thiết kế, đó không phải là một vấn đề. Nhưng nếu tôi muốn tạo một cái lúc chạy?

Chi tiết khác:

Ứng dụng của tôi là chuyển đổi của ứng dụng Visual FoxPro hiện có. Tôi đã cố gắng đọc nhiều nhất có thể về cài đặt ứng dụng, cài đặt người dùng, v.v. và hiểu rõ về cách .Net đang làm việc, nhưng vẫn còn một số điều tôi đang bối rối.

Trong ứng dụng Fox, các cài đặt đã lưu được lưu trong sổ đăng ký. Biểu mẫu của tôi được phân lớp và tôi có mã lớp cơ sở tự động lưu vị trí và kích thước biểu mẫu trong sổ đăng ký được khóa trên tên biểu mẫu. Bất cứ khi nào tôi tạo ra một hình thức mới, tôi không phải làm bất cứ điều gì đặc biệt để có được hành vi này; nó được xây dựng trong lớp cơ sở. Các dạng .Net của tôi cũng được phân lớp, phần đó hoạt động tốt.

Trong .Net, tôi nhận được hiển thị mà tôi cho rằng phải sử dụng cài đặt Phạm vi người dùng cho những thứ như tùy chọn của người dùng. Kích thước và vị trí của biểu mẫu chắc chắn có vẻ giống như sở thích của người dùng. Nhưng, tôi không thể thấy bất kỳ cách nào để tự động thêm các cài đặt này vào dự án. Nói cách khác, mỗi lần tôi thêm một biểu mẫu mới vào dự án của mình (và 100 biểu mẫu của họ), tôi phải nhớ thêm một cài đặt ứng dụng người dùng và đảm bảo đặt tên giống như biểu mẫu, nghĩa là " FormMySpecialSizePosition "để giữ kích thước và vị trí. Tôi không muốn phải nhớ điều đó. Đây có phải là may mắn không? Hoặc tôi hoàn toàn sủa cây sai bằng cách cố gắng sử dụng cài đặt Phạm vi người dùng? Tôi có cần tạo tệp XML của riêng mình để giữ các cài đặt, để tôi có thể làm bất cứ điều gì tôi muốn (tức là, thêm một cài đặt mới khi chạy)? Hay cái gì khác?

Chắc chắn đây là điều rất phổ biến và ai đó có thể nói cách "đúng" để thực hiện. Cảm ơn trước!

+0

Bạn có thể tìm thấy câu hỏi mà tôi đã hỏi trước đây hữu ích. Nó có một giải pháp hoàn chỉnh một phần cho một cơ sở biểu mẫu bạn có thể kế thừa từ để làm cho một biểu mẫu tồn tại giới hạn và vị trí của nó. Bạn có lẽ sẽ chỉ cần làm cho nó lưu trữ các thiết lập của nó trong một tập tin xml hoặc một cái gì đó như thế. – Svish

Trả lời

0

Bạn có thể tạo lớp biểu mẫu cơ sở có chức năng chung như ghi nhớ vị trí và kích thước và kế thừa từ lớp cơ sở đó.

public class myForm : Form { 
protected override void OnLoad(){ 
    //load the settings and apply them 
    base.OnLoad(); 
} 

protected override void OnClose(){ 
    //save the settings 
    base.OnClose(); 
} 
} 
then for the other forms: 

public class frmMainScreen : myForm { 
// you get the settings for free ;) 
}

Vâng, một cái gì đó như thế;)

+0

Mã làm việc thực tế sẽ hữu ích hơn nhiều. Đã bỏ phiếu! –

0

Tôi đang ở thuyền giống như bạn, trong đó tôi có một số hình thức (MDI trẻ em, trong trường hợp của tôi) mà tôi muốn giữ gìn vị trí và kích thước của từng người dùng. Từ nghiên cứu của tôi, việc tạo cài đặt ứng dụng trong thời gian chạy không được hỗ trợ. (xem this blog entry) Tuy nhiên, bạn không phải gắn mọi thứ trong tệp cài đặt chính. Bạn có thể thêm tệp Cài đặt vào dự án của mình (explained here in the MSDN) và sử dụng nó thông qua đối tượng Properties.Settings. Điều này sẽ không làm giảm bớt nỗi đau khi phải nhớ tạo các mẫu mới cho từng biểu mẫu, nhưng ít nhất nó sẽ giữ chúng lại với nhau và không làm lộn xộn các cài đặt ứng dụng chính của bạn.

Theo như sử dụng lớp cơ sở để truy xuất cài đặt ... Tôi không biết liệu bạn có thể làm điều đó ở đó hay không. Những gì tôi sẽ (và có lẽ sẽ) làm là đặt tên cho mỗi thuộc tính, sau đó sử dụng Me.GetType(). ToString() (Tôi đang làm việc trong VB) để tổng hợp tên của các thuộc tính mà tôi muốn lấy trong sự kiện Load() của từng biểu mẫu.

8
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

Giải pháp này có vấn đề nếu bạn đóng cửa sổ ở trạng thái được thu nhỏ. – robsch

+0

Giải pháp này cũng không hoạt động nếu bạn không viết một ứng dụng, ví dụ: nếu bạn đang viết một plugin. Nó cũng không đề cập đến cách thiết lập hoặc cấu hình các thuộc tính không rõ ràng và yêu cầu tìm kiếm tài liệu. –

0

tôi chỉ dòng nó ra vào một tập tin xml riêng biệt - nhanh chóng và dơ bẩn và có lẽ không phải những gì bạn đang sau:

 Dim winRect As String() = util.ConfigFile.GetUserConfigInstance().GetValue("appWindow.rect").Split(",") 
     Dim winState As String = util.ConfigFile.GetUserConfigInstance().GetValue("appWindow.state") 
     ' 
     Me.WindowState = FormWindowState.Normal 
     ' 
     Me.Left = CType(winRect(0), Integer) 
     Me.Top = CType(winRect(1), Integer) 
     Me.Width = CType(winRect(2), Integer) 
     Me.Height = CType(winRect(3), Integer) 
     ' 
     If winState = "maximised" Then 
      Me.WindowState = FormWindowState.Maximized 
     End If 

 Dim winState As String = "normal" 
     If Me.WindowState = FormWindowState.Maximized Then 
      winState = "maximised" 
     ElseIf Me.WindowState = FormWindowState.Minimized Then 
      winState = "minimised" 
     End If 
     ' 
     If Me.WindowState = FormWindowState.Normal Then 
      ' 
      Dim winRect As String = CType(Me.Left, String) & "," & CType(Me.Top, String) & "," & CType(Me.Width, String) & "," & CType(Me.Height, String) 
      ' only save window rectangle if its not maximised/minimised 
      util.ConfigFile.GetUserConfigInstance().SetValue("appWindow.rect", winRect) 
     End If 
     ' 
     util.ConfigFile.GetUserConfigInstance().SetValue("appWindow.state", winState) 
0
+0

Hầu hết các liên kết này quản lý một bộ cài đặt, vị trí và kích thước cho một biểu mẫu. Nếu bạn có nhiều biểu mẫu, nó trở nên tệ hơn và bạn muốn giữ nó đơn giản trong lớp cơ sở cho biểu mẫu. Bài viết này xử lý nhiều biểu mẫu: http://www.code-magazine.com/article.aspx?quickid=0607031 –

2

Tôi có mã này từ nơi nào đó, nhưng tiếc là lúc (lâu rồi) đã không làm cho một lời nhận xét về nơi tôi đã nhận nó từ.

này giúp tiết kiệm các hình thức thông tin để HKCU registry của người dùng:

using System; 
using System.Windows.Forms; 
using Microsoft.Win32; 

/// <summary>Summary description for FormPlacement.</summary> 
public class PersistentForm : System.Windows.Forms.Form 
{ 
    private const string DIALOGKEY = "Dialogs"; 

    /// <summary></summary> 
    protected override void OnCreateControl() 
    { 
     LoadSettings(); 
     base.OnCreateControl(); 
    } 

    /// <summary></summary> 
    protected override void OnClosing(System.ComponentModel.CancelEventArgs e) 
    { 
     SaveSettings(); 
     base.OnClosing(e); 
    } 

    /// <summary>Saves the form's settings.</summary> 
    public void SaveSettings() 
    { 
     RegistryKey dialogKey = Application.UserAppDataRegistry.CreateSubKey(DIALOGKEY); 
     if (dialogKey != null) 
     { 
      RegistryKey formKey = dialogKey.CreateSubKey(this.GetType().ToString()); 
      if (formKey != null) 
      { 
       formKey.SetValue("Left", this.Left); 
       formKey.SetValue("Top", this.Top); 
       formKey.Close(); 
      } 
      dialogKey.Close(); 
     } 
    } 

    /// <summary></summary> 
    public void LoadSettings() 
    { 
     RegistryKey dialogKey = Application.UserAppDataRegistry.OpenSubKey(DIALOGKEY); 
     if (dialogKey != null) 
     { 
      RegistryKey formKey = dialogKey.OpenSubKey(this.GetType().ToString()); 
      if (formKey != null) 
      { 
       this.Left = (int)formKey.GetValue("Left"); 
       this.Top = (int)formKey.GetValue("Top"); 
       formKey.Close(); 
      } 
      dialogKey.Close(); 
     } 
    } 
} 
2

Có thật là một thiếu thực tế của một đĩa đơn, "chỉ hoạt động" giải pháp cho bất cứ nơi nào trên internet, vì vậy đây là sáng tạo của riêng tôi:

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()[email protected]"\"+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(); 
    } 
} 

thi này lưu trữ các vị trí và kích thước của một hình thức trong HKCU/Phần mềm/< CompanyId() >/< AppID() >/Window Tiểu bang/< tên hình thức >. Nó sẽ không khôi phục lại các thiết lập nếu cấu hình màn hình thay đổi như vậy để ngăn chặn các cửa sổ được khôi phục khỏi màn hình.

Rõ ràng điều này không thể xử lý nhiều phiên bản của cùng một biểu mẫu. Tôi cũng đặc biệt vô hiệu hóa khôi phục giảm thiểu nhưng đó là một sửa chữa dễ dàng của nguồn.

Ở trên được thiết kế để được thả vào tệp .cs của riêng nó và không bao giờ chạm lại. Bạn cần phải tạo một bản sao cục bộ không gian tên như thế này (trong Program.cs hoặc plugin file .cs chính của bạn hoặc bất cứ nơi nào):

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

Bây giờ bạn có một instantiation phi trừu tượng trong không gian tên chính. Vì vậy, để sử dụng, thêm video này vào các hình thức mà bạn muốn lưu và phục hồi:

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

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

Rõ ràng cảm thấy tự do để tùy chỉnh để mục đích riêng của mình. Không có sự bảo hành được ngụ ý hay ám chỉ. Sử dụng rủi ro của riêng bạn - Tôi từ chối mọi bản quyền.

Niall

0

Đây là mã tôi đã sử dụng.

private void SaveWindowPosition() 
{ 
    Rectangle rect = (WindowState == FormWindowState.Normal) ? 
     new Rectangle(DesktopBounds.Left, DesktopBounds.Top, DesktopBounds.Width, DesktopBounds.Height) : 
     new Rectangle(RestoreBounds.Left, RestoreBounds.Top, RestoreBounds.Width, RestoreBounds.Height); 
    RegistrySettings.SetSetting("WindowPosition", String.Format("{0},{1},{2},{3},{4}", 
     (int)this.WindowState, 
     rect.Left, rect.Top, rect.Width, rect.Height)); 
} 

private void RestoreWindowPosition() 
{ 
    try 
    { 
     string s = RegistrySettings.GetSetting("WindowPosition", String.Empty) as string; 
     if (s != null) 
     { 
      List<int> settings = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) 
            .Select(v => int.Parse(v)).ToList(); 
      if (settings.Count == 5) 
      { 
       this.SetBounds(
        settings[1], 
        settings[2], 
        settings[3], 
        settings[4]); 
       this.WindowState = (FormWindowState)settings[0]; 
      } 
     } 
    } 
    catch { /* Just leave current position if error */ } 
} 

Tôi cũng đã trình bày mã này trong bài viết Saving and Restoring a Form's Window Position.

Các vấn đề liên quan