2008-09-19 16 views
23

यह एक मानक आवश्यकता की तरह लगता है: अगली बार जब उपयोगकर्ता एप्लिकेशन लॉन्च करता है, तो उसी स्थिति में विंडो खोलें और जैसा कि पहले था। यहाँ मेरी इच्छा सूची है:विंडोज फॉर्म में विंडो स्थिति को रिकॉर्ड करने के लिए कैसे करें एप्लिकेशन सेटिंग्स

  • विंडो स्थिति में एक ही रूप में यह
    • था जब तक स्क्रीन आकार दिया गया है और पुराने स्थिति स्क्रीन के बाहर है।
  • स्प्लिटर्स अपनी स्थिति को बनाए रखने चाहिए
  • टैब कंटेनर उनके चयन
  • कुछ ड्रॉपडाउन उनके चयन
  • विंडो स्थिति (अधिकतम कम से कम, सामान्य) से संपर्क करना चाहिए बनाए रखना होगा एक ही रूप में यह किया गया है।
    • शायद आपको कभी भी कम से कम शुरू नहीं करना चाहिए, मैंने फैसला नहीं किया है।

मैं सीमाओं के साथ एक जवाब के रूप में मेरे वर्तमान समाधान जोड़ देंगे।

उत्तर

18

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

कमियां:

  • अधिक कोड लिखने के लिए।
  • बहुत विचित्र रूप से। फ़ॉर्मलोड पर गुण सेट करने का ऑर्डर भ्रमित है। उदाहरण के लिए, आपको यह सुनिश्चित करना होगा कि आपने स्प्लिटर दूरी सेट करने से पहले विंडो आकार सेट कर दिया है।

अभी, यह मेरा पसंदीदा समाधान है, लेकिन ऐसा लगता है कि यह बहुत अधिक काम है। काम को कम करने के लिए, मैंने एक विंडोसेटिंग क्लास बनाई है जो विंडो स्थान, आकार, स्थिति और किसी भी स्प्लिटर स्थिति को एक ही एप्लिकेशन सेटिंग में क्रमबद्ध करता है।फिर मैं अपने आवेदन में प्रत्येक फॉर्म के लिए उस प्रकार की सेटिंग बना सकता हूं, बंद पर सहेज सकता हूं, और लोड पर पुनर्स्थापित कर सकता हूं।

मैंने the source code पोस्ट किया, जिसमें विंडोसेटिंग क्लास और कुछ फॉर्म इसका उपयोग करते हैं। इसे किसी प्रोजेक्ट में जोड़ने पर निर्देश WindowSettings.cs फ़ाइल में शामिल हैं। सबसे कठिन हिस्सा यह पता लगा रहा था कि कस्टम प्रकार के साथ एप्लिकेशन सेटिंग कैसे जोड़ना है। आप ब्राउज़ ड्रॉप ... प्रकार ड्रॉपडाउन से चुनें, और फिर मैन्युअल रूप से नामस्थान और कक्षा का नाम दर्ज करें। आपकी परियोजना के प्रकार सूची में दिखाई नहीं देते हैं।

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

private void MyForm_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     Settings.Default.CustomWindowSettings = WindowSettings.Record(
      Settings.Default.CustomWindowSettings, 
      this, 
      splitContainer1); 
    } 

    private void MyForm_Load(object sender, EventArgs e) 
    { 
     WindowSettings.Restore(
      Settings.Default.CustomWindowSettings, 
      this, 
      splitContainer1); 
    } 
+0

ग्रेट नमूना कोड! –

+1

दुर्भाग्यवश, डोनकिर्बी परियोजना का लाइसेंस जिसके तहत नमूना बाध्य है, कोड के सरल मुक्त उपयोग के लिए अनुमति नहीं दे सकता है। इसे फिर से प्रकाशित करने पर विचार करें। –

+0

अब मैं एमआईटी लाइसेंस में बदल गया हूं; मेरा मतलब कोड के उपयोग को प्रतिबंधित करने का नहीं था। बेशक, एट्रिब्यूशन की सराहना की जाती है। यहां पोस्ट करने के लिए कोड थोड़ा लंबा है। –

5

मुझे मिला सबसे सरल समाधान एप्लिकेशन सेटिंग्स के साथ बाध्यकारी डेटा का उपयोग करना है। मैं स्प्लिटर पर स्प्लिटर डिस्टेंस के साथ खिड़की पर स्थान और क्लाइंट आकार गुणों को बांधता हूं।

कमियां:

  • आप विंडो को बंद करते हुए कम से कम है, यह अगली बार छिपा खुलता है। खिड़की वापस पाने के लिए वास्तव में मुश्किल है।
  • यदि आप अधिकतम होने पर विंडो बंद करते हैं, तो यह पूरी स्क्रीन भरता है, लेकिन अधिकतम नहीं (मामूली समस्या)।
  • शीर्ष-दाएं कोने या नीचे-बाएं कोने का उपयोग करके विंडो का आकार बदलना सिर्फ बदसूरत है। मुझे लगता है कि दो डाटाबाउंड गुण एक-दूसरे से लड़ रहे हैं।

यदि आप अजीब व्यवहार के साथ प्रयोग करना चाहते हैं, तो मैंने इस तकनीक का उपयोग करके sample solution पोस्ट किया है।

+0

एक विंडोस्टेट संपत्ति है जिसे आप न्यूनतम या अधिकतम विंडो की जांच के लिए संदर्भित कर सकते हैं। हालांकि, मैं उन दो राज्यों में से एक में खिड़की के आकार के बारे में टिप्पणी नहीं कर सकता हूं। –

+0

हां, मैंने विंडोस्टेट संपत्ति के साथ प्रयोग किया। यह बहुत अजीब व्यवहार किया। शायद आकार बदलने वाले के लिए एक समान मुद्दा, जहां एक ही समय में एक से अधिक डाटाबेस संपत्ति को बदलना विवाद और झटके का कारण बनता है। –

2

एक हैक आप उस जानकारी को संग्रहीत करने के लिए सेटिंग्स का उपयोग कर सकते हैं। आपको बस वांछित संपत्ति (पूर्व फॉर्म। आकार और फॉर्म। स्थान) को एक विशिष्ट सेटिंग में बांधना है और यह स्वचालित रूप से सहेजा और अपडेट हो जाता है।

2

आप डिस्क के लिए इन लिखने के लिए आपको है स्थापित करने के लिए जो गुण नियंत्रण Form_closed घटना में, कायम हो जाएगा आवेदन सेटिंग्स का उपयोग कर सकते हैं आवेदन सेटिंग्स पर विधि बचाने के उपयोग करने के लिए:

Properties.Settings.Default.Save(); 
2

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

private void MainForm_Load(object sender, EventArgs e) { 
    RestoreState(); 
} 

private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { 
    SaveState(); 
} 

private void SaveState() { 
    if (WindowState == FormWindowState.Normal) { 
    Properties.Settings.Default.MainFormLocation = Location; 
    Properties.Settings.Default.MainFormSize = Size; 
    } else { 
    Properties.Settings.Default.MainFormLocation = RestoreBounds.Location; 
    Properties.Settings.Default.MainFormSize = RestoreBounds.Size; 
    } 
    Properties.Settings.Default.MainFormState = WindowState; 
    Properties.Settings.Default.SplitterDistance = splitContainer1.SplitterDistance; 
    Properties.Settings.Default.Save(); 
} 

private void RestoreState() { 
    if (Properties.Settings.Default.MainFormSize == new Size(0, 0)) { 
    return; // state has never been saved 
    } 
    StartPosition = FormStartPosition.Manual; 
    Location = Properties.Settings.Default.MainFormLocation; 
    Size = Properties.Settings.Default.MainFormSize; 
    // I don't like an app to be restored minimized, even if I closed it that way 
    WindowState = Properties.Settings.Default.MainFormState == 
    FormWindowState.Minimized ? FormWindowState.Normal : Properties.Settings.Default.MainFormState; 
    splitContainer1.SplitterDistance = Properties.Settings.Default.SplitterDistance; 
} 

ध्यान रखें कि कंपाइल जहां सेटिंग्स जमा हो जाती है कॉन्फ़िग फ़ाइल मिट जाता है, तो यह परीक्षण:

Size size; 
int x; 
int y; 
if (WindowState.Equals(FormWindowState.Normal)) 
{ 
    size = Size; 
    if (Location.X + size.Width > Screen.PrimaryScreen.Bounds.Width) 
     x = Screen.PrimaryScreen.Bounds.Width - size.Width; 
    else 
     x = Location.X; 
    if (Location.Y + Size.Height > Screen.PrimaryScreen.Bounds.Height) 
     y = Screen.PrimaryScreen.Bounds.Height - size.Height; 
    else 
     y = Location.Y; 
} 
else 
{ 
size = RestoreBounds.Size; 
x = (Screen.PrimaryScreen.Bounds.Width - size.Width)/2; 
y = (Screen.PrimaryScreen.Bounds.Height - size.Height)/2; 
} 
Properties.Settings.Position.AsPoint = new Point(x, y); // Property setting is type of Point 
Properties.Settings.Size.AsSize = size;     // Property setting is type of Size 
Properties.Settings.SplitterDistance.Value = splitContainer1.SplitterDistance; // Property setting is type of int 
Properties.Settings.IsMaximized = WindowState == FormWindowState.Maximized; // Property setting is type of bool 
Properties.Settings.DropDownSelection = DropDown1.SelectedValue; 
Properties.Settings.Save(); 
+0

हां, यह एक दूसरे प्रकार का कस्टम कोड है जिसके बारे में मैं अपने दूसरे उत्तर में बात कर रहा हूं। जैसा कि मैंने कहा, यह सही हो गया है। मुझे उम्मीद है कि एक आसान तरीका है। धन्यवाद, हालांकि, मुझे AsSize और AsPoint गुणों के बारे में पता नहीं था। मैं उनको देख लूंगा। –

5

मैं इस तरह प्रत्येक मान मैं सहेजना चाहते के लिए एक सेटिंग है, और उपयोग कोड बनाने के सहेजने और पुनर्स्थापित करने के बीच कोड परिवर्तन किए बिना।

6

नीचे दिए गए नमूना दिखाता है कि कैसे मैं यह कर

  • SavePreferences जब प्रपत्र बंद करने और फार्म के आकार की बचत होती है, और अगर यह अधिकतम है एक ध्वज का संकेत (इस संस्करण में अगर यह मैं नहीं सहेजते कहा जाता है कम से कम - यह अगली बार बहाल या अधिकतम किया जाएगा)।

  • लोडप्र्रेन्स ऑनलोड से कॉल किया जाता है।

  • पहले डिज़ाइन-टाइम विंडोस्टेट को सहेजें और इसे सामान्य पर सेट करें। यदि आप विंडोस्टेट सामान्य हैं तो आप केवल फॉर्म आकार को सफलतापूर्वक सेट कर सकते हैं।

  • अगला अपनी स्थायी सेटिंग्स से आकार को पुनर्स्थापित करें।

  • अब सुनिश्चित करें कि फ़ॉर्म आपकी स्क्रीन पर फिट बैठता है (फिटटस्क्रीन पर कॉल करें)। पिछली बार एप्लिकेशन चलाने के बाद से स्क्रीन रेज़ोल्यूशन बदल सकता है।

  • अंततः विंडोस्टेट को अधिकतम (यदि ऐसा होता है), या पहले डिज़ाइन किए गए डिज़ाइन-टाइम मान पर सेट करें।

यह स्पष्ट रूप से प्रारंभ स्थिति जारी रहती है अनुकूलित किया जा सकता है और क्या प्रपत्र जब आप बंद हो कम से कम किया गया था - मुझे लगता है कि क्या करने की जरूरत नहीं किया। आपके फॉर्म पर नियंत्रण के लिए अन्य सेटिंग्स जैसे स्प्लिटर स्थिति और टैब कंटेनर सरल हैं।

private void FitToScreen() 
{ 
    if (this.Width > Screen.PrimaryScreen.WorkingArea.Width) 
    { 
     this.Width = Screen.PrimaryScreen.WorkingArea.Width; 
    } 
    if (this.Height > Screen.PrimaryScreen.WorkingArea.Height) 
    { 
     this.Height = Screen.PrimaryScreen.WorkingArea.Height; 
    } 
} 
private void LoadPreferences() 
{ 
    // Called from Form.OnLoad 

    // Remember the initial window state and set it to Normal before sizing the form 
    FormWindowState initialWindowState = this.WindowState; 
    this.WindowState = FormWindowState.Normal; 
    this.Size = UserPreferencesManager.LoadSetting("_Size", this.Size); 
    _currentFormSize = Size; 
    // Fit to the current screen size in case the screen resolution 
    // has changed since the size was last persisted. 
    FitToScreen(); 
    bool isMaximized = UserPreferencesManager.LoadSetting("_Max", initialWindowState == FormWindowState.Maximized); 
    WindowState = isMaximized ? FormWindowState.Maximized : FormWindowState.Normal; 
} 
private void SavePreferences() 
{ 
    // Called from Form.OnClosed 
    UserPreferencesManager.SaveSetting("_Size", _currentFormSize); 
    UserPreferencesManager.SaveSetting("_Max", this.WindowState == FormWindowState.Maximized); 
    ... save other settings 
} 

एक्स

+0

मैंने कोशिश की, और UserPreferencesManager संदर्भ में परेशानी थी। Google इंगित करता है कि यह जावा क्लास है, सी # नहीं! –

+0

मैं बहुत स्पष्ट नहीं था I. इस नमूने में, UserPreferencesManager एक वर्ग मैंने लिखा है, जो एक सतत माध्यम पर सेटिंग्स लोड करने और सहेजने का काम करता है। यह .NET 1.1 के लिए था, इन दिनों आप दृढ़ता के लिए .NET 2.0 सेटिंग्स आर्किटेक्चर का उपयोग करेंगे। ध्यान दें कि इस नमूने का ध्यान वह क्रम था जिसमें सेटिंग लोड करते समय गुण सेट किए जाते हैं, इसके विवरण के विवरण के बजाय, उन्हें कैसे सहेजा/बहाल किया जाता है। – Joe

+0

कोड टिप्पणी कहती है "वर्तमान स्क्रीन आकार के लिए फिट करें ..." लेकिन वास्तविक कोड स्क्रीन का उपयोग करता है। प्राथमिक स्क्रीन: वर्तमान स्क्रीन बहु-मॉनीटर सेटअप में प्राथमिकस्क्रीन नहीं हो सकती है! – onedaywhen

3

डॉन Kirkby द्वारा स्वीकार कर लिया जवाब और WindowSettings वर्ग उन्होंने लिखा है के आधार पर, आप मानक एक से एक CustomForm निकाले जाते हैं और हर रूप के लिए लिखा समान कोड की मात्रा को कम करने के लिए कर सकता है, शायद इस तरह:

using System; 
using System.Configuration; 
using System.Reflection; 
using System.Windows.Forms; 

namespace CustomForm 
{ 
    public class MyCustomForm : Form 
    { 
    private ApplicationSettingsBase _appSettings = null; 
    private string _settingName = ""; 

    public Form() : base() { } 

    public Form(ApplicationSettingsBase settings, string settingName) 
     : base() 
    { 
     _appSettings = settings; 
     _settingName = settingName; 

     this.Load += new EventHandler(Form_Load); 
     this.FormClosing += new FormClosingEventHandler(Form_FormClosing); 
    } 

    private void Form_Load(object sender, EventArgs e) 
    { 
     if (_appSettings == null) return; 

     PropertyInfo settingProperty = _appSettings.GetType().GetProperty(_settingName); 
     if (settingProperty == null) return; 

     WindowSettings previousSettings = settingProperty.GetValue(_appSettings, null) as WindowSettings; 
     if (previousSettings == null) return; 

     previousSettings.Restore(this); 
    } 

    private void Form_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     if (_appSettings == null) return; 

     PropertyInfo settingProperty = _appSettings.GetType().GetProperty(_settingName); 
     if (settingProperty == null) return; 

     WindowSettings previousSettings = settingProperty.GetValue(_appSettings, null) as WindowSettings; 
     if (previousSettings == null) 
     previousSettings = new WindowSettings(); 

     previousSettings.Record(this); 

     settingProperty.SetValue(_appSettings, previousSettings, null); 

     _appSettings.Save(); 
    } 
    } 
} 

इस का उपयोग करने के लिए, निर्माता में अपने आवेदन सेटिंग्स वर्ग और स्थापित करने के नाम पारित:

CustomForm.MyCustomForm f = new CustomForm.MyCustomForm(Properties.Settings.Default, "formSettings"); 

यह पिछली सेटिंग्स को सेटिंग्स वर्ग से/सेट करने के लिए प्रतिबिंब का उपयोग करता है। सहेजें कॉल को Form_Closing दिनचर्या में रखने के लिए इष्टतम नहीं हो सकता है, कोई भी इसे हटा सकता है और जब भी मुख्य ऐप निकलता है तो सेटिंग्स फ़ाइल को सहेज सकता है।

इसे नियमित रूप से उपयोग करने के लिए, पैरामीटर रहित कन्स्ट्रक्टर का उपयोग करें।

+0

बॉयलरप्लेट कोड को कम करना एक दिलचस्प विचार है। मैं इसे विंडोसेटिंग क्लास पर एक स्थिर विधि में अनुकूलित कर सकता हूं जो विंडोसेटिंग ऑब्जेक्ट को रेफ पैरामीटर के रूप में लेता है। मुझे लगता है कि प्रतिबिंब के उपयोग से बच सकते हैं। –

+0

टिप्पणी के लिए धन्यवाद। मुझे यकीन नहीं है कि यह प्रतिबिंब का उपयोग करने के आसपास कैसे काम करेगा। आपको कुछ प्रकार को पास करना होगा जो एक सेटिंग ऑब्जेक्ट का प्रतिनिधित्व करता है। चूंकि सेटिंग वाले ऑब्जेक्ट में प्रोजेक्ट से प्रोजेक्ट में भिन्नता है, इसलिए मुझे नहीं पता था कि प्रतिबिंब का उपयोग किए बिना सेटिंग्स को कैसे सेट और निकालना है, क्योंकि संपत्ति के नाम प्रत्येक मामले के लिए भिन्न होते हैं। सरलीकरण के लिए मैंने अधिक सामान्य सेटिंग नाम बनाने के लिए _this.Name_ का उपयोग करने का भी प्रयास किया, लेकिन यह काम नहीं किया गया क्योंकि फॉर्म नाम प्रारंभिक कॉम्पोनेंट कॉल के भीतर सेट किया गया है, जो बेस कन्स्ट्रक्टर को कॉल के बाद होता है। – takrl

+0

ठीक है, मैंने नमूना कोड में स्थिर विधियों को जोड़ा: http://code.google.com/p/donkirkby/source/browse/trunk/WindowSettings/WindowSettings.cs आप देख सकते हैं कि उन्हें स्निपेट में कैसे कहा जाता है उपरोक्त स्वीकृत उत्तर। विचार के लिए धन्यवाद। –

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

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