65.9K
CodeProject 正在变化。 阅读更多。
Home

窗体放置组件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.91/5 (11投票s)

2003年11月12日

6分钟阅读

viewsIcon

65973

downloadIcon

1414

一个组件类,可以恢复窗体上次关闭时的位置、大小和状态。

Sample Image

目录

引言

在我发布了 Profile 文章 后不久,我回到了我正在开发的小型 Windows 应用程序,添加代码以在窗体关闭时保存其位置和大小,并在下次显示时恢复它们。我添加了 `Load` 和 `Closed` 事件的处理器,并添加了适当的代码来使用我的 `Registry` profile 类保存和恢复位置和大小值。代码只使用了窗体的 `Position`、`Size` 和 `WindowState` 属性,运行得很好……除了一个小问题。如果窗口被最小化或最大化然后关闭,它会以最小化或最大化的状态重新出现,但不会记住其“正常”的大小。因此,其正常大小会与其最大化或最小化的大小相同。这不好!

我开始寻找 .NET 解决方案来解决这个问题,令我沮丧的是,我找不到。然后我想起了我之前开发并在此处 发布 的一个 C++ 类,名为 `PlacementHook`。它使用简单的钩子机制(通过 `SetWindowLong`)透明地处理 `WM_SHOWWINDOW` 和 `WM_DESTROY` 消息,并负责保存和恢复窗口的放置。当然是窗口的放置!——我就是这样能够保存窗口的“正常”大小的。Win32 `WINDOWPLACEMENT` 结构包含一个 `rcNormalPosition` 成员,它跟踪这一点。那么,为什么 .NET 类没有提供这个呢?嗯……

总之,我的新任务明确了:编写一个类来封装窗体放置的保存和恢复。它将使用我的新的 Profile 类来存储和检索放置数据。它将调用 Win32 API `GetWindowPlacement` 来获取窗体的“正常”位置和大小。并且像 `PlacementHook` 一样,它将包含 `Load` 和 `Closed` 事件的处理器,这些处理器将透明地完成所有工作。

因此,我又一次不得不把我的小型 Windows 应用程序放在一边,开始着手我的新类。我称它为 `Placement`,并决定在此处发布它。我希望您能在您的 Windows 应用程序中找到它。

设计说明

最初,我将该类创建为独立的——不继承自任何东西。它只有几个构造函数,在其中会传入 `Form` 对象。该类会在字段中保存 `Form` 对象,并在 `Load` 和 `Closed` 事件处理器中保存/恢复其放置。

然后我回去尝试将其转换为 `Component` 类,以便可以将其添加到工具箱并在设计器中的窗体上拖放。这很麻烦,因为设计器不够智能,无法知道需要将窗体对象(`this`)传递给类的构造函数。所以我不得不给类添加一个默认构造函数。但我仍然不知道如何让设计器生成代码来将 `Form` 属性设置为 `this`,即容器。好吧,经过一些研究,我找到了 `ComponentDesigner` 类。在其 `OnSetComponentDefaults` 方法中,我设置了 `Form` 属性,设计器会巧妙地将其转换为 `this`。

一切都很顺利!`Placement` 类可以像任何组件一样使用,并添加到设计器的工具箱中。一旦在那里,您就可以将组件拖放到窗体上,几乎可以忘记它。编译并运行您的程序后,您会注意到,每次窗体出现时,它都会处于上次关闭时的相同位置和具有相同的尺寸。所有这些都不需要编写一行代码!

当然,我在类中添加了几个属性,以便您可以根据需要调整组件。有一个用于获取/设置负责保存/恢复配置文件数据的 `Profile` 对象。您可以(手动)将其设置为任何 `IProfile` 实现,例如 XML 或 Config——默认是 Registry。还有一个 `Section` 属性,用于保存放置数据将在配置文件中存储的节的名称。最后,我添加了三个不同的布尔属性,允许您单独设置要恢复的放置的哪个方面(位置、大小和状态)。默认情况下,这些都设置为 `true`,并且可以在“属性”窗口中轻松调整。

用法

我将该类放在 `AMS.Form` 命名空间中,并将其构建成一个新的 DLL,名为 _AMS.Form.dll_。我计划随着需求的出现,将其他与 `Form` 相关的类添加到此 DLL 中,但目前它只包含 `Placement` 类。要将其添加到 Visual Studio .NET 工具箱,请按照以下步骤操作:

  1. 在 Visual Studio .NET 中打开您自己的项目。
  2. 打开包含您希望添加控件的窗体的文件。
  3. 右键单击工具箱,然后选择“自定义工具箱”。
  4. 点击“_ .NET Components_”选项卡。
  5. 点击“_Browse_”按钮,然后选择 _AMS.Form.dll_ 文件。
  6. `Placement` 组件将被添加到“ _Customize_”工具箱中,并被勾选。
  7. 点击 _OK_。然后该控件将出现在工具箱中。
  8. 将其拖放到您的窗体上,并根据需要修改其属性。

您也可以手动将 `Placement` 类添加到您的代码中,这也非常简单。首先,您需要将 DLL 添加到您项目的 _References_ 中,在 Visual Studio .NET 中操作如下:

  1. 在 Visual Studio .NET 中打开您自己的项目。
  2. 在 _Solution Explorer_ 工具箱中,右键单击 _References_ 文件夹,然后选择“添加引用”。
  3. 点击“_Browse_”按钮,然后选择 _AMS.Form.dll_ 文件。
  4. 点击 _OK_。现在您可以在您的项目中内部使用 _AMS.Form_ 命名空间。

然后,您可以将此行添加到您的窗体构造函数中,紧跟在调用 `InitializeComponent();` 之后:

AMS.Form.Placement placement = new AMS.Form.Placement(this);

大致就是这样!如果您想更改默认设置,也很简单。这是一个例子:

placement.Profile = new Xml("Settings.xml");
placement.Section = "Some Section";
placement.RestoreSize = false;

_我对该类进行了彻底的文档记录,并为其创建了一个帮助文件,名为_ AMS.Form.chm_。我想您不需要它,但以防万一。

请注意,_AMS.Form.dll_ 依赖于 _AMS.Profile.dll_(我已将其包含在可下载文件中——源代码 在此)。请记住将这两个 DLL 文件放在一起。祝您使用愉快!

历史

版本 1.0

  • 2003 年 11 月 7 日
    • 初始发布。
  • 2003 年 11 月 12 日
    • 由于本文档发布在错误的用户名下,因此重新发布。
    • 更改了 `Restore` 方法,使其在这样做会导致窗体超出可用屏幕边界时不会恢复位置。此外,如果窗体最初是最小化或最大化的,其状态将不会被恢复。感谢 Maximilian Hänel 和 Igor Gribanov 的建议。
© . All rights reserved.