wake-up-neo.net

.NET/Windows Forms: Speichern Sie die Größe und Position der Fenster

Ich habe eine Windows Forms-Anwendung mit einem normalen Fenster. Wenn ich nun die Anwendung schließe und neu starte, möchte ich, dass das Hauptfenster an der gleichen Stelle auf dem Bildschirm mit der gleichen Größe wie der Zeitpunkt des Schließens angezeigt wird.

Gibt es in Windows Forms eine einfache Möglichkeit, den Bildschirmstandort und die Fenstergröße (und wenn möglich den Fensterstatus) zu merken, oder muss alles von Hand erledigt werden?

38
clamp

Sie müssen den Ort und die Größe des Fensters in den Anwendungseinstellungen speichern. Hier ist ein guter C # Artikel , der Ihnen zeigt, wie.

EDIT

In den Anwendungseinstellungen können Sie so ziemlich alles speichern, was Sie möchten. In der Spalte Typ des Einstellungsrasters können Sie zu jedem .NET-Typ navigieren. WindowState befindet sich in System.Windows.Forms und wird als FormWindowState aufgeführt. Es gibt auch eine Eigenschaft für FormStartPosition.

32
Walter

Wenn Sie diesen Code zu Ihrem FormClosing-Ereignishandler hinzufügen:

if (WindowState == FormWindowState.Maximized)
{
    Properties.Settings.Default.Location = RestoreBounds.Location;
    Properties.Settings.Default.Size = RestoreBounds.Size;
    Properties.Settings.Default.Maximised = true;
    Properties.Settings.Default.Minimised = false;
}
else if (WindowState == FormWindowState.Normal)
{
    Properties.Settings.Default.Location = Location;
    Properties.Settings.Default.Size = Size;
    Properties.Settings.Default.Maximised = false;
    Properties.Settings.Default.Minimised = false;
}
else
{
    Properties.Settings.Default.Location = RestoreBounds.Location;
    Properties.Settings.Default.Size = RestoreBounds.Size;
    Properties.Settings.Default.Maximised = false;
    Properties.Settings.Default.Minimised = true;
}
Properties.Settings.Default.Save();

Der aktuelle Zustand wird gespeichert.

Fügen Sie diesen Code dann zum OnLoad-Handler Ihres Formulars hinzu:

if (Properties.Settings.Default.Maximised)
{
    WindowState = FormWindowState.Maximized;
    Location = Properties.Settings.Default.Location;
    Size = Properties.Settings.Default.Size;
}
else if (Properties.Settings.Default.Minimised)
{
    WindowState = FormWindowState.Minimized;
    Location = Properties.Settings.Default.Location;
    Size = Properties.Settings.Default.Size;
}
else
{
    Location = Properties.Settings.Default.Location;
    Size = Properties.Settings.Default.Size;
}

Der letzte Status wird wiederhergestellt.

Es merkt sich sogar, auf welchen Monitor in einem Multi-Monitor-Setup die Anwendung maximiert wurde.

55
ChrisF

Bisherige Lösungen funktionierten nicht für mich. Nachdem ich eine Weile gespielt hatte, endete ich mit folgendem Code:

  • bewahrt maximierten und normalen Zustand
  • ersetzt den minimierten Zustand durch die Standardposition
  • bei Änderungen der Bildschirmgröße (getrennter Monitor, Remote-Verbindung, ...) wird der Benutzer nicht in einen frustrierenden Zustand versetzt, wenn die Anwendung außerhalb des Bildschirms geöffnet ist.

    private void MyForm_Load(object sender, EventArgs e)
    {
        if (Properties.Settings.Default.IsMaximized)
            WindowState = FormWindowState.Maximized;
        else if (Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(Properties.Settings.Default.WindowPosition)))
        {
            StartPosition = FormStartPosition.Manual;
            DesktopBounds = Properties.Settings.Default.WindowPosition;
            WindowState = FormWindowState.Normal;
        }
    }
    
    private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        Properties.Settings.Default.IsMaximized = WindowState == FormWindowState.Maximized;
        Properties.Settings.Default.WindowPosition = DesktopBounds;
        Properties.Settings.Default.Save();
    }
    

benutzereinstellungen:

    <userSettings>
    <WindowsFormsApplication2.Properties.Settings>
        <setting name="WindowPosition" serializeAs="String">
            <value>0, 0, -1, -1</value>
        </setting>
        <setting name="IsMaximized" serializeAs="String">
            <value>False</value>
        </setting>
    </WindowsFormsApplication2.Properties.Settings>
</userSettings>

Hinweis: WindowsPosition ist absichtlich falsch, daher verwendet die Anwendung beim ersten Start den Standardspeicherort.

3
jing

Ich habe verschiedene Methoden ausprobiert. Dies ist, was am Ende für mich gearbeitet hat. (In diesem Fall - beim ersten Start - wurden die Standardeinstellungen noch nicht beibehalten, sodass das Formular die im Designer festgelegten Werte verwendet.)

  1. Fügen Sie die Einstellungen zum Projekt hinzu (manuell - verlassen Sie sich nicht auf Visual Studio):  Properties.Settings

  2. Fügen Sie Ihrem Formular den folgenden Code hinzu:

    private void Form1_Load(object sender, EventArgs e)
    {
        this.RestoreWindowPosition();
    }
    
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        this.SaveWindowPosition();
    }
    
    private void RestoreWindowPosition()
    {
        if (Settings.Default.HasSetDefaults)
        {
            this.WindowState = Settings.Default.WindowState;
            this.Location = Settings.Default.Location;
            this.Size = Settings.Default.Size;
        }
    }
    
    private void SaveWindowPosition()
    {
        Settings.Default.WindowState = this.WindowState;
    
        if (this.WindowState == FormWindowState.Normal)
        {
            Settings.Default.Location = this.Location;
            Settings.Default.Size = this.Size;
        }
        else
        {
            Settings.Default.Location = this.RestoreBounds.Location;
            Settings.Default.Size = this.RestoreBounds.Size;
        }
    
        Settings.Default.HasSetDefaults = true;
    
        Settings.Default.Save();
    }
    
3
darksider474

Wenn Sie mehr als ein Formular haben, können Sie so etwas verwenden ...

Fügen Sie dieses Teil alle aus dem Formular ungültig

var AbbA = Program.LoadFormLocationAndSize(this);
            this.Location = new Point(AbbA[0], AbbA[1]);
            this.Size = new Size(AbbA[2], AbbA[3]);
            this.FormClosing += new FormClosingEventHandler(Program.SaveFormLocationAndSize);

Speichern Sie den Speicherort und die Größe des Formulars in app.config xml

public static void SaveFormLocationAndSize(object sender, FormClosingEventArgs e)
{
    Form xForm = sender as Form;
    Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
    if (ConfigurationManager.AppSettings.AllKeys.Contains(xForm.Name))
        config.AppSettings.Settings[xForm.Name].Value = String.Format("{0};{1};{2};{3}", xForm.Location.X, xForm.Location.Y, xForm.Size.Width, xForm.Size.Height);
    else
        config.AppSettings.Settings.Add(xForm.Name, String.Format("{0};{1};{2};{3}", xForm.Location.X, xForm.Location.Y, xForm.Size.Width, xForm.Size.Height));
    config.Save(ConfigurationSaveMode.Full);
}

Laden Sie die Position und Größe des Formulars aus der XML-Datei app.config

public static int[] LoadFormLocationAndSize(Form xForm)
{
    int[] LocationAndSize = new int[] { xForm.Location.X, xForm.Location.Y, xForm.Size.Width, xForm.Size.Height };
    //---//
    try
    {
        Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
        var AbbA = config.AppSettings.Settings[xForm.Name].Value.Split(';');
        //---//
        LocationAndSize[0] = Convert.ToInt32(AbbA.GetValue(0));
        LocationAndSize[1] = Convert.ToInt32(AbbA.GetValue(1));
        LocationAndSize[2] = Convert.ToInt32(AbbA.GetValue(2));
        LocationAndSize[3] = Convert.ToInt32(AbbA.GetValue(3));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    //---//
    return LocationAndSize;
}
2
user1751206

Matt - Um den WindowState als Benutzereinstellung zu speichern, scrollen Sie im Einstellungsdialogfeld im Dropdown-Menü "Typ" nach unten und wählen Sie "Durchsuchen". 

Erweitern Sie im Dialogfeld "Typ auswählen" System.Windows.Forms, und Sie können "FormWindowState" als Typ auswählen.

(Sorry, ich sehe keine Schaltfläche, mit der ich den Kommentar kommentieren kann ...)

2
JohnForDummies

Sie müssen die Informationen irgendwo manuell speichern. Ich würde vorschlagen, dies als Anwendungseinstellungen vorzunehmen und diese in einem benutzerspezifischen isolierten Speicher zu speichern.

Lesen Sie nach dem Laden die Einstellungen, ändern Sie die Größe und verschieben Sie das Formular.

1
Ian

Wenn Sie die fabelhafte Open-Source-Bibliothek - Jot verwenden, können Sie die langweiligen .settings-Dateien vergessen und tun dies einfach:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

Es gibt auch ein Nuget-Paket, und Sie können so ziemlich alles konfigurieren, wie/wann/wo Daten gespeichert werden. 

Haftungsausschluss: Ich bin der Autor, aber die Bibliothek ist vollständig Open Source (unter MIT Lizenz).

0
anakic

Sie könnten es auch in Ihrer (sagen wir) config.xml speichern, wenn Sie das Formular schließen:

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    XmlDocument docConfigPath = new XmlDocument();
    docConfigPath.Load(XML_Config_Path);

    WriteNode(new string[] { "config", "Size", "Top", Top.ToString() }, docConfigPath);
    WriteNode(new string[] { "config", "Size", "Left", Left.ToString() }, docConfigPath);
    WriteNode(new string[] { "config", "Size", "Height", Height.ToString() }, docConfigPath);
    WriteNode(new string[] { "config", "Size", "Width", Width.ToString() }, docConfigPath);

    docConfigPath.Save(XML_Config_Path);
}

public static XmlNode WriteNode(string[] sNode, XmlDocument docConfigPath)
{
    int cnt = sNode.Length;
    int iNode = 0;
    string sNodeNameLast = "/" + sNode[0];
    string sNodeName = "";
    XmlNode[] xN = new XmlNode[cnt];

    for (iNode = 1; iNode < cnt - 1; iNode++)
    {
        sNodeName = "/" + sNode[iNode];
        xN[iNode] = docConfigPath.SelectSingleNode(sNodeNameLast + sNodeName);
        if (xN[iNode] == null)
        {
            xN[iNode] = docConfigPath.CreateNode("element", sNode[iNode], "");
            xN[iNode].InnerText = "";
            docConfigPath.SelectSingleNode(sNodeNameLast).AppendChild(xN[iNode]);
        }
        sNodeNameLast += sNodeName;
    }

    if (sNode[cnt - 1] != "")
        xN[iNode - 1].InnerText = sNode[cnt - 1];

    return xN[cnt - 2];
}

Und das Laden ist auf Ihrem:

private void Form1_Load(object sender, EventArgs e)
{
    XmlDocument docConfigPath = new XmlDocument();
    docConfigPath.Load(XML_Config_Path);
    XmlNodeList nodeList = docConfigPath.SelectNodes("config/Size");

    Height = ReadNodeInnerTextAsNumber("config/Size/Height", docConfigPath);
    Width = ReadNodeInnerTextAsNumber("config/Size/Width", docConfigPath);
    Top = ReadNodeInnerTextAsNumber("config/Size/Top", docConfigPath);
    Left = ReadNodeInnerTextAsNumber("config/Size/Left", docConfigPath);
}

Die config.xml sollte Folgendes enthalten:

<?xml version="1.0" encoding="utf-8"?>
<config>
  <Size>
    <Height>800</Height>
    <Width>1400</Width>
    <Top>100</Top>
    <Left>280</Left>
  </Size>
</config>
0
Deniz

Ich habe diese Methode bisher angewendet und sie funktioniert hervorragend. Sie müssen nicht mit den Anwendungseinstellungen herumspielen. Stattdessen wird die Serialisierung verwendet, um eine Einstellungsdatei in Ihr Arbeitsverzeichnis zu schreiben. Ich verwende JSON, aber Sie können die native XML-Serialisierung von .NET oder eine beliebige Serialisierung für diese Angelegenheit verwenden.

Fügen Sie diese statischen Methoden in eine gemeinsame Erweiterungsklasse ein. Bonuspunkte, wenn Sie ein gemeinsames Erweiterungsprojekt haben, auf das Sie durch mehrere Projekte verweisen:

const string WINDOW_STATE_FILE = "windowstate.json";

public static void SaveWindowState(Form form)
{
    var state = new WindowStateInfo
    {
        WindowLocation = form.Location,
        WindowState = form.WindowState
    };

    File.WriteAllText(WINDOW_STATE_FILE, JsonConvert.SerializeObject(state));
}

public static void LoadWindowState(Form form)
{
    if (!File.Exists(WINDOW_STATE_FILE)) return;

    var state = JsonConvert.DeserializeObject<WindowStateInfo>(File.ReadAllText(WINDOW_STATE_FILE));

    if (state.WindowState.HasValue) form.WindowState = state.WindowState.Value;
    if (state.WindowLocation.HasValue) form.Location = state.WindowLocation.Value;
}

public class WindowStateInfo
{
    public FormWindowState? WindowState { get; set; }

    public Point? WindowLocation { get; set; }
}

Sie müssen diesen Code nur einmal schreiben und müssen sich nie wieder damit herumschlagen. Nun zum spaßigen Teil: Tragen Sie den folgenden Code in die Ereignisse Load und FormClosing Ihres Formulars ein:

private void Form1_Load(object sender, EventArgs e)
{
    WinFormsGeneralExtensions.LoadWindowState(this);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    WinFormsGeneralExtensions.SaveWindowState(this);
}

Das ist alles was Sie tun müssen. Das einzige Setup besteht darin, diese Erweiterungen einer gemeinsamen Klasse zuzuordnen. Danach fügen Sie einfach zwei Codezeilen zum Code Ihres Formulars hinzu und schon sind Sie fertig.

Dieser Code funktioniert nur dann wirklich, wenn Ihre WinForm-App nur ein einziges Formular enthält. Wenn es mehrere Formulare gibt, deren Positionen Sie sich merken möchten, müssen Sie kreativ werden und Folgendes tun:

public static void SaveWindowState(Form form)
{
    var state = new WindowStateInfo
    {
        WindowLocation = form.Location,
        WindowState = form.WindowState
    };

    File.WriteAllText($"{form.Name} {WINDOW_STATE_FILE}", JsonConvert.SerializeObject(state));
}

Ich speichere nur Ort und Zustand, aber Sie können dies ändern, um sich an die Höhe und Breite der Form oder irgendetwas anderes zu erinnern. Nehmen Sie die Änderung nur einmal vor und sie funktioniert für jede Anwendung, die sie aufruft.

0

Meine Antwort ist aus ChrisF ♦s Antwort , aber ich habe eines behoben, was ich nicht mochte - wenn das Fenster zum Zeitpunkt des Schließens minimiert wird, erscheint es beim nächsten Start minimiert.

Mein Code verarbeitet diesen Fall korrekt, indem er sich daran erinnert, ob das Fenster zum Zeitpunkt der Minimierung maximiert oder normal war, und dass der permanente Status entsprechend festgelegt wurde.

Leider stellt Winforms diese Informationen nicht direkt zur Verfügung. Daher musste ich WndProc überschreiben und selbst speichern. Siehe Überprüfen Sie, ob das aktuell minimierte Fenster zum Zeitpunkt der Minimierung im maximierten oder normalen Zustand war.

partial class Form1 : Form
{
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SYSCOMMAND)
        {
            int wparam = m.WParam.ToInt32() & 0xfff0;

            if (wparam == SC_MAXIMIZE)
                LastWindowState = FormWindowState.Maximized;
            else if (wparam == SC_RESTORE)
                LastWindowState = FormWindowState.Normal;
        }

        base.WndProc(ref m);
    }

    private const int WM_SYSCOMMAND = 0x0112;
    private const int SC_MAXIMIZE = 0xf030;
    private const int SC_RESTORE = 0xf120;
    private FormWindowState LastWindowState;

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (WindowState == FormWindowState.Normal)
        {
            Properties.Settings.Default.WindowLocation = Location;
            Properties.Settings.Default.WindowSize = Size;
        }
        else
        {
            Properties.Settings.Default.WindowLocation = RestoreBounds.Location;
            Properties.Settings.Default.WindowSize = RestoreBounds.Size;
        }

        if (WindowState == FormWindowState.Minimized)
        {
            Properties.Settings.Default.WindowState = LastWindowState;
        }
        else
        {
            Properties.Settings.Default.WindowState = WindowState;
        }

        Properties.Settings.Default.Save();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        if (Properties.Settings.Default.WindowSize != new Size(0, 0))
        {
            Location = Properties.Settings.Default.WindowLocation;
            Size = Properties.Settings.Default.WindowSize;
            WindowState = Properties.Settings.Default.WindowState;
        }
    }
0
sashoalm