这似乎是一个标准要求:下次用户启动应用程序时,以与以前相同的位置和状态打开窗口.这是我的愿望清单:
窗口位置与原样相同
除非屏幕已调整大小并且旧位置现在已关闭屏幕.
分裂者应保持其立场
标签容器应保留其选择
一些下拉菜单应该保留他们的选择
窗口状态(最大化,最小化,正常)与其相同.
也许你永远不应该开始最小化,我还没有决定.
我将添加我当前的解决方案作为答案以及限制.
我的另一个选择是围绕应用程序设置编写更多自定义代码,并在formLoad和formClosed上执行它.这不使用数据绑定.
缺点:
要编写更多代码.
非常繁琐.您在formLoad上设置属性的顺序令人困惑.例如,您必须确保在设置分割器距离之前设置窗口大小.
现在,这是我首选的解决方案,但似乎工作太多了.为了减少工作量,我创建了一个WindowSettings类,它将窗口位置,大小,状态和任何拆分器位置序列化为单个应用程序设置.然后我可以为我的应用程序中的每个表单创建该类型的设置,保存关闭,并在加载时恢复.
我发布了源代码,包括WindowSettings类和一些使用它的表单.有关将其添加到项目的说明包含在WindowSettings.cs文件中.最棘手的部分是弄清楚如何使用自定义类型添加应用程序设置.从类型下拉列表中选择"浏览...",然后手动输入命名空间和类名.项目中的类型不会显示在列表中.
更新:我添加了一些静态方法来简化您添加到每个表单的样板代码.按照将WindowSettings类添加到项目并创建应用程序设置的说明后,这里是一个代码示例,必须将其添加到要记录和还原的位置的每个表单中.
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); }
下面的示例显示了我是如何做到的
关闭表单时会调用SavePreferences并保存表单的大小,并显示一个标志,指示它是否已最大化(在此版本中,如果它被最小化,我将不保存 - 它将在下次恢复或最大化时恢复).
从OnLoad调用LoadPreferences.
首先保存设计时WindowState并将其设置为Normal.如果WindowState为Normal,则只能成功设置表单大小.
接下来从您的持久设置中恢复大小.
现在确保表格适合您的屏幕(致电FitToScreen).自上次运行应用程序以来,屏幕分辨率可能已更改.
最后将WindowState设置回Maximized(如果持久化),或者设置为之前保存的设计时值.
这显然可以适应于保持起始位置以及在关闭时表单是否最小化 - 我不需要这样做.表单上控件的其他设置(如拆分器位置和选项卡容器)非常简单.
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 }
X
我发现最简单的解决方案是使用数据绑定和应用程序设置.我将窗口上的location和clientSize属性与拆分器上的splitterDistance绑定在一起.
缺点:
如果在最小化时关闭窗口,则下次打开时会隐藏窗口.把窗户拉回来真的很难.
如果在最大化时关闭窗口,则会打开整个屏幕,但不会最大化(次要问题).
使用右上角或左下角调整窗口大小非常难看.我猜这两个数据绑定属性正在互相争斗.
如果您想尝试这种奇怪的行为,我会使用这种技术发布一个示例解决方案.
我为每个要保存的值设置了一个设置,并使用如下代码:
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; }
请记住,重新编译会擦除存储设置的配置文件,因此请在保存和恢复之间进行代码更改时对其进行测试.