Domanda

Aggiornamento:Risolto, con il codice

Ho funzionato, vedi la mia risposta qui sotto per il codice ...

Posta originale

Come ha sottolineato Tundey in la sua risposta al mio ultima domanda, puoi associare quasi tutto ciò che riguarda il controllo di un modulo Windows a ApplicationSettings senza alcuno sforzo.Quindi non c'è davvero alcun modo per farlo con la dimensione del modulo? Questo tutorial dice che devi gestire le dimensioni in modo esplicito in modo da poter salvare RestoreBounds invece delle dimensioni se la finestra è ingrandita o ridotta a icona.Tuttavia, speravo di poter semplicemente utilizzare una proprietà come:

public Size RestoreSize
{
    get
    {
        if (this.WindowState == FormWindowState.Normal)
        {
            return this.Size;
        }
        else
        {
            return this.RestoreBounds.Size;
        }
    }
    set
    {
        ...
    }
}

Ma non riesco a vedere un modo per associarlo nella finestra di progettazione (dimensione in particolare manca dall'elenco PropertyBinding).

È stato utile?

Soluzione

Alla fine ho creato una sottoclasse Form che risolve questo problema, una volta per tutte.Per usarlo:

  1. Eredita da RestorableForm anziché da Form.
  2. Aggiungere un'associazione in (ApplicationSettings) -> (PropertyBinding) a WindowRestoreState.
  3. Chiama Properties.Settings.Default.Save() quando la finestra sta per chiudersi.

Ora la posizione e lo stato della finestra verranno ricordati tra una sessione e l'altra.Seguendo i suggerimenti di altri utenti di seguito, ho incluso una funzione ConstrainToScreen che assicura che la finestra si adatti perfettamente ai display disponibili durante il ripristino.

Codice

// Consider this code public domain. If you want, you can even tell
// your boss, attractive women, or the other guy in your cube that
// you wrote it. Enjoy!

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace Utilities
{
    public class RestorableForm : Form, INotifyPropertyChanged
    {
        // We invoke this event when the binding needs to be updated.
        public event PropertyChangedEventHandler PropertyChanged;

        // This stores the last window position and state
        private WindowRestoreStateInfo windowRestoreState;

        // Now we define the property that we will bind to our settings.
        [Browsable(false)]        // Don't show it in the Properties list
        [SettingsBindable(true)]  // But do enable binding to settings
        public WindowRestoreStateInfo WindowRestoreState
        {
            get { return windowRestoreState; }
            set
            {
                windowRestoreState = value;
                if (PropertyChanged != null)
                {
                    // If anybody's listening, let them know the
                    // binding needs to be updated:
                    PropertyChanged(this,
                        new PropertyChangedEventArgs("WindowRestoreState"));
                }
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            WindowRestoreState = new WindowRestoreStateInfo();
            WindowRestoreState.Bounds
                = WindowState == FormWindowState.Normal ?
                  Bounds : RestoreBounds;
            WindowRestoreState.WindowState = WindowState;

            base.OnClosing(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (WindowRestoreState != null)
            {
                Bounds = ConstrainToScreen(WindowRestoreState.Bounds);
                WindowState = WindowRestoreState.WindowState;
            }
        }

        // This helper class stores both position and state.
        // That way, we only have to set one binding.
        public class WindowRestoreStateInfo
        {
            Rectangle bounds;
            public Rectangle Bounds
            {
                get { return bounds; }
                set { bounds = value; }
            }

            FormWindowState windowState;
            public FormWindowState WindowState
            {
                get { return windowState; }
                set { windowState = value; }
            }
        }

        private Rectangle ConstrainToScreen(Rectangle bounds)
        {
            Screen screen = Screen.FromRectangle(WindowRestoreState.Bounds);
            Rectangle workingArea = screen.WorkingArea;

            int width = Math.Min(bounds.Width, workingArea.Width);
            int height = Math.Min(bounds.Height, workingArea.Height);

            // mmm....minimax
            int left = Math.Min(workingArea.Right - width,
                                Math.Max(bounds.Left, workingArea.Left));
            int top = Math.Min(workingArea.Bottom - height,
                                Math.Max(bounds.Top, workingArea.Top));

            return new Rectangle(left, top, width, height);
        }
    }
}

Impostazioni Riferimenti di associazioni

Altri suggerimenti

Il motivo per cui la proprietà Form.Size non è disponibile nell'interfaccia utente di associazione delle impostazioni è perché questa proprietà è contrassegnata DesignerSerializationVisibility.Hidden.Ciò significa che il progettista non sa come serializzarlo, né tanto meno come generare un'associazione dati per esso.Invece il Form.ClientSize La proprietà è quella che viene serializzata.

Se provi a diventare furbo legandoti Posizione E Dimensione cliente, vedrai un altro problema.Quando provi a ridimensionare il modulo dal bordo sinistro o superiore, vedrai un comportamento strano.Ciò è apparentemente correlato al modo in cui funziona l'associazione dati bidirezionale nel contesto di insiemi di proprietà che si influenzano reciprocamente.Entrambi Posizione E Dimensione cliente eventualmente richiamare un metodo comune, SetBoundsCore().

Inoltre, associazione dati a proprietà come Posizione E Misurare semplicemente non è efficiente.Ogni volta che l'utente sposta o ridimensiona il modulo, Windows invia centinaia di messaggi al modulo, facendo sì che la logica di associazione dei dati esegua molta elaborazione, quando tutto ciò che realmente desideri è memorizzare l'ultima posizione e dimensione prima che il modulo venga chiuso.

Questa è una versione molto semplificata di ciò che faccio:

private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
    Properties.Settings.Default.MyState = this.WindowState;
    if (this.WindowState == FormWindowState.Normal)
    {
       Properties.Settings.Default.MySize = this.Size;
       Properties.Settings.Default.MyLoc = this.Location;
    }
    else
    {
       Properties.Settings.Default.MySize = this.RestoreBounds.Size;
       Properties.Settings.Default.MyLoc = this.RestoreBounds.Location;
    }
    Properties.Settings.Default.Save();
}

private void MyForm_Load(object sender, EventArgs e)
{
    this.Size = Properties.Settings.Default.MySize;
    this.Location = Properties.Settings.Default.MyLoc;
    this.WindowState = Properties.Settings.Default.MyState;
} 

Perché questa è una versione molto semplificata?Perché farlo correttamente lo è molto più complicato di quanto sembri :-)

Beh, ho giocato velocemente con questo e hai ragione, anche se non c'è modo di farlo direttamente legamento la dimensione del modulo su AppSettings, puoi aggiungere i tuoi valori e modificare la dimensione al caricamento.

Forse consiglierei, se questa è una funzionalità comune, di creare una sottoclasse di Form e di eseguire automaticamente il controllo di App.Config per le impostazioni delle dimensioni dei moduli.

(Oppure potresti creare il tuo file..Ottienilo per interrogare un file Xml "formname.settings.xml" o qualcosa del genere?- Pensare ad alta voce!)..

Ecco cosa ho riscontrato (molto approssimativo, nessun controllo degli errori, ecc.).

App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key ="FormHeight" value="500" />
        <add key ="FormWidth" value="200"/>
    </appSettings>
</configuration>

Codice modulo

    private void Form1_Load(object sender, EventArgs e)
    {
        string height = ConfigurationManager.AppSettings["FormHeight"];
        int h = int.Parse(height);
        string width = ConfigurationManager.AppSettings["FormWidth"];
        int w = int.Parse(width);
        this.Size = new Size(h, w);
    }

Uno dei motivi per cui immagino che l'associazione delle dimensioni non sia consentita è perché lo schermo potrebbe cambiare tra una sessione e l'altra.

Ricaricare le dimensioni quando la risoluzione è stata ridotta potrebbe far sì che la barra del titolo superi i limiti dello schermo.

È inoltre necessario prestare attenzione alle configurazioni di più monitor, in cui i monitor potrebbero non essere più disponibili alla successiva esecuzione dell'app.

Sono d'accordo con la risposta di Rob Cooper.Ma penso che Martin abbia ragione.Non c'è niente di meglio che far sì che gli utenti aprano la tua applicazione e l'app sia fuori schermo!

Quindi, in realtà, ti consigliamo di combinare entrambe le risposte e tenere presente le dimensioni attuali dello schermo prima di impostare la dimensione del modulo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top