这似乎是一个标准要求:下次用户启动应用程序时,打开与之前相同位置和状态的窗口。这是我的愿望清单:
我将添加我当前的解决方案作为答案以及限制。
答案 0 :(得分:18)
我的另一个选择是围绕应用程序设置编写更多自定义代码,并在formLoad和formClosed上执行它。这不使用数据绑定。
缺点:
现在,这是我首选的解决方案,但似乎工作太多了。为了减少工作量,我创建了一个WindowSettings类,它将窗口位置,大小,状态和任何拆分器位置序列化为单个应用程序设置。然后我可以为我的应用程序中的每个表单创建该类型的设置,保存在关闭,并在加载时恢复。
我发布了the source code,包括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);
}
答案 1 :(得分:6)
下面的示例显示了我是如何做到的
关闭表单时会调用SavePreferences并保存表单的大小,还会显示一个标志,指示它是否已最大化(在此版本中,如果最小化则不保存 - 它将在下次恢复或最大化时恢复)
从OnLoad调用LoadPreferences。
首先保存设计时WindowState并将其设置为Normal。如果窗口状态为“正常”,则只能成功设置表单大小。
然后从您的持久设置中恢复大小。
现在确保表单适合您的屏幕(致电FitToScreen)。自您上次运行应用程序后,屏幕分辨率可能已更改。
最后将WindowState设置回最大化(如果保持原样),或者设置为之前保存的设计时值。
这显然可以适应于保持起始位置以及在关闭时表单是否最小化 - 我不需要这样做。表单上控件的其他设置(例如拆分器位置和选项卡容器)非常简单。
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
答案 2 :(得分:5)
我发现最简单的解决方案是使用数据绑定和应用程序设置。我将窗口上的location和clientSize属性与拆分器上的splitterDistance绑定在一起。
缺点:
如果你想尝试这种奇怪的行为,我使用这种技术发布了sample solution。
答案 3 :(得分:5)
我为每个要保存的值设置了一个设置,并使用如下代码:
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;
}
请记住,重新编译会擦除存储设置的配置文件,因此请在保存和恢复之间进行代码更改时对其进行测试。
答案 4 :(得分:3)
根据Don 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");
这使用Reflection从/向设置类获取/设置先前的设置。将Save调用放入Form_Closing例程可能不是最佳选择,只要主应用程序退出,就可以将其删除并保存设置文件。
要将它用作常规表单,只需使用无参数构造函数。
答案 5 :(得分:2)
您可以使用“设置”来存储该信息。您所要做的就是将所需的属性(例如form.Size和form.Location)绑定到特定设置,并自动保存和更新。
答案 6 :(得分:2)
您可以使用应用程序设置来设置将保留哪些控件属性,在Form_closed事件中,您必须在应用程序设置上使用save方法将这些属性写入磁盘:
Properties.Settings.Default.Save();
答案 7 :(得分:2)
以下是我自己使用的一些例子。它只考虑主监视器,因此如果在多个监视器上使用它可能会更好地处理它。
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();