2008-09-18 11 views
10

WinForms 2.0 सी # एप्लिकेशन में, किसी विधि में फ़ॉर्म स्थिति और आकार को सहेजने और पुनर्स्थापित करने के लिए उपयोग की जाने वाली सामान्य विधि क्या होती है?फॉर्म स्थिति और आकार को सहेजें और पुनर्स्थापित करें

संबंधित, क्या नई उपयोगकर्ता स्कॉप्ड एप्लिकेशन सेटिंग्स को RUNTIME में जोड़ना संभव है? मैं पूरी तरह से डिजाइन समय पर सेटिंग्स जोड़ने के लिए कैसे देखता हूं, यह कोई समस्या नहीं है। लेकिन अगर मैं रनटाइम पर एक बनाना चाहता हूं तो क्या होगा?

अधिक विवरण:

मेरा आवेदन एक मौजूदा विजुअल फॉक्सप्रो आवेदन की एक रूपांतरण है। मैं एप्लिकेशन सेटिंग्स, उपयोगकर्ता सेटिंग्स इत्यादि के बारे में जितना भी कर सकता हूं उसे पढ़ने की कोशिश कर रहा हूं और चीजों को करने के नेट तरीके पर खुद को स्पष्ट कर रहा हूं, लेकिन अभी भी कई चीजें हैं जिन पर मैं उलझन में हूं।

फॉक्स ऐप में, सहेजी गई सेटिंग्स रजिस्ट्री में संग्रहीत हैं। मेरे रूपों को उप-वर्गीकृत किया गया है, और मेरे पास बेस क्लास कोड है जो फॉर्म नाम पर कुंजी की रजिस्ट्री में फॉर्म स्थिति और आकार को स्वचालित रूप से सहेजता है। जब भी मैं एक नया रूप बनाता हूं, मुझे इस व्यवहार को पाने के लिए कुछ भी विशेष करने की ज़रूरत नहीं है; यह बेस क्लास में बनाया गया है। मेरे .NET रूपों को भी उपclassed हैं, वह हिस्सा अच्छी तरह से काम कर रहा है।

नेट में, मुझे लगता है कि मुझे उपयोगकर्ता वरीयताओं जैसे चीजों के लिए उपयोगकर्ता स्कोप्ड सेटिंग्स का उपयोग करना है। एक फॉर्म का आकार और स्थान निश्चित रूप से उपयोगकर्ता वरीयता की तरह प्रतीत होता है। लेकिन, मैं परियोजना में इन सेटिंग्स को स्वचालित रूप से जोड़ने का कोई तरीका नहीं देख सकता। दूसरे शब्दों में, हर बार जब मैं अपने प्रोजेक्ट में एक नया फॉर्म जोड़ता हूं (और उनके 100 रूपों के रूप में होते हैं), मुझे उपयोगकर्ता स्कोप्ड एप्लिकेशन सेटिंग को जोड़ना याद रखना होगा और इसे फॉर्म के समान नाम देना होगा, यानी " आकार और स्थिति को पकड़ने के लिए FormMySpecialSizePosition "। मुझे ऐसा करने की याद नहीं रखना पड़ेगा। क्या यह सिर्फ कठिन भाग्य है? या क्या मैं पूरी तरह से उपयोगकर्ता स्कोप्ड सेटिंग्स का उपयोग करके गलत पेड़ को भड़क रहा हूं? क्या मुझे सेटिंग्स रखने के लिए अपनी खुद की एक्सएमएल फाइल बनाने की ज़रूरत है, ताकि मैं जो भी चाहूं कर सकूं (यानी, रनटाइम पर एक नई सेटिंग जोड़ें)? या कुछ और?

निश्चित रूप से यह एक बहुत आम है और कोई इसे करने के लिए "सही" तरीका बता सकता है। अग्रिम में धन्यवाद!

+0

आपको एक प्रश्न मिल सकता है जिसे मैंने थोड़ी देर पहले उपयोगी बताया था। यह एक फॉर्म बेस के लिए आंशिक रूप से पूर्ण समाधान है जिसका आप एक फॉर्म बनाने के लिए अपनी सीमा और स्थान बना सकते हैं। आपको शायद इसे अपनी सेटिंग्स को किसी XML फ़ाइल या उस तरह से कुछ स्टोर करने की आवश्यकता होगी। – Svish

उत्तर

0

आप सामान्य कार्यक्षमता के साथ बेस फॉर्म क्लास बना सकते हैं जैसे स्थिति और आकार को याद रखना और उस बेस क्लास से प्राप्त करना।

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 ;) 
}

ठीक है, ऐसा ही कुछ;)

+0

वास्तविक कामकाजी कोड अधिक उपयोगी होगा। Downvoted! –

0

मैं तुम्हें रूप में एक ही नाव में हूँ, कि मैं रूपों (एमडीआई बच्चों, मेरे मामले में की एक संख्या है) कि मैं सुरक्षित रखना चाहते हैं प्रत्येक उपयोगकर्ता के लिए स्थिति और आकार। मेरे शोध से, रनटाइम पर एप्लिकेशन सेटिंग्स बनाना समर्थित नहीं है। (this blog entry देखें) हालांकि, आपको मुख्य सेटिंग्स फ़ाइल में सब कुछ छड़ी नहीं है। आप अपनी प्रोजेक्ट में एक सेटिंग फ़ाइल जोड़ सकते हैं (explained here in the MSDN) और Properties.Settings ऑब्जेक्ट के माध्यम से इसका उपयोग करें। यह प्रत्येक रूप के लिए नए निपटान बनाने के लिए याद रखने के दर्द को कम नहीं करेगा, लेकिन कम से कम यह उन्हें एक साथ रखेगा, और आपकी मुख्य एप्लिकेशन सेटिंग्स को अव्यवस्थित नहीं करेगा।

सेटिंग्स को पुनर्प्राप्त करने के लिए बेस क्लास का उपयोग करने तक ... मुझे नहीं पता कि आप इसे वहां कर सकते हैं या नहीं। मैं क्या करूंगा (और शायद होगा) प्रत्येक विशेषता का नाम है, फिर लोड() ईवेंट में पुनर्प्राप्त करने के लिए इच्छित विशेषताओं के नामों को मिश्रित करने के लिए Me.GetType()। ToString() (मैं VB में काम कर रहा हूं) का उपयोग करें। प्रत्येक रूप का।

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

यदि आप एक छोटा राज्य में विंडो बंद करते हैं तो इस समाधान में कोई समस्या है। – robsch

+0

यह समाधान तब भी काम नहीं करता है जब आप कोई एप्लिकेशन नहीं लिख रहे हैं उदा। अगर आप एक प्लगइन लिख रहे हैं। यह भी उल्लेख नहीं करता है कि उन गुणों को कैसे सेट अप या कॉन्फ़िगर करना है जो स्पष्ट नहीं हैं और एक दस्तावेज़ खोज की आवश्यकता है। –

0

मैं सिर्फ यह एक अलग xml फ़ाइल के लिए बाहर धारा - त्वरित और गंदी और शायद नहीं क्या आप के बाद:

 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

यहाँ कुछ प्रासंगिक लिंक की जाँच कर रहे हैं आउट:

Saving out a Form's Size and Location using the Application Settings feature

Any good examples of how to use Applications settings

Exploring Secrets of Persistent Application Settings

+0

इनमें से अधिकतर लिंक एक रूप के लिए सेटिंग्स, स्थान और आकार के एक सेट का प्रबंधन करते हैं। यदि आपके पास कई रूप हैं तो यह बदतर हो जाता है और आप फॉर्म के लिए बेस क्लास में इसे सरल रखना चाहते हैं। यह आलेख एकाधिक रूपों को संभालता है: http://www.code-magazine.com/article.aspx?quickid=0607031 –

2

मैंने कहीं से इस कोड को मिला, लेकिन दुर्भाग्य से (बहुत पहले) समय के बारे में जहां मैं इसे से मिला एक टिप्पणी नहीं की।

यह उपयोगकर्ता की HKCU रजिस्ट्री करने के लिए प्रपत्र की जानकारी सहेजता है:

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

वहाँ वास्तव में एक भी की एक वास्तविक कमी है, इंटरनेट पर इस कहीं का हल "सिर्फ काम करता है", तो यहाँ मेरी अपनी रचना है:

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(); 
    } 
} 

इस कार्यान्वयन संग्रहीत करता है स्थिति और HKCU में/सॉफ्टवेयर/< CompanyId() >/< AppId() >/खिड़की राज्य/< प्रपत्र नामएक रूप का आकार। यदि मॉनीटर कॉन्फ़िगरेशन स्क्रीन को पुनर्स्थापित करने से रोकने के लिए मॉनिटर कॉन्फ़िगरेशन बदलता है तो यह सेटिंग्स को पुनर्स्थापित नहीं करेगा।

स्पष्ट रूप से यह एक ही रूप के कई उदाहरणों को संभाल नहीं सकता है। मैंने विशेष रूप से कम से कम बहाल करने को अक्षम कर दिया लेकिन यह स्रोत का एक आसान फिक्स है।

उपर्युक्त को अपनी स्वयं की .cs फ़ाइल में गिरा दिया गया है और कभी भी स्पर्श नहीं किया गया है।

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

अब आप मुख्य नाम स्थान में एक गैर-सार इन्स्टेन्शियशन हैं: आप एक स्थानीय नाम स्थान (या Program.cs में अपने प्लगइन मुख्य .cs फ़ाइल या जहाँ भी) इस तरह की नकल का दृष्टांत किया है। तो, उपयोग करने के लिए, रूपों आप को बचाया और बहाल करना चाहते हैं से जोड़ें:

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

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

जाहिर है अपने स्वयं के प्रयोजनों के लिए अनुकूलित करने के लिए स्वतंत्र लग रहा है। किसी तरह की वॉरंटी के बारे में नहीं बताया गया है या लागू है। अपने जोखिम पर प्रयोग करें - मैं किसी भी कॉपीराइट को अस्वीकार करता हूं।

निएल

0

यहां कोड का उपयोग किया गया है।

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 */ } 
} 

मैंने इस आलेख को मेरे लेख Saving and Restoring a Form's Window Position में भी प्रस्तुत किया।

संबंधित मुद्दे