昨天我开始讨论“MDI 与选项卡式界面”。我问过我是否应该继续将我的应用程序开发为基于 MDI 的应用程序,还是应该将子表单嵌入到选项卡表中。有人指出我应该改用 TFrames ......我的问题是:为什么?
在 TFrame 上嵌入表单时使用 TFrame 有什么优点?到目前为止我什么都不知道,切换只需要我重写部分代码......
(无论如何,我不会在设计时使用嵌入!)
提前致谢
回答评论以提供使用框架的原因:
我认为框架是 GUI 的构建块,在设计时将现有组件组合到更高级的组件。在 Delphi 5 之前,人们会使用TCustomPanel
带有子控件的后代并将其注册为新组件,准备好拖放到表单上。框架允许以更少的麻烦做同样的事情。
它们使您可以专注于开发您需要的功能,仅此而已。如果做得对,您就可以将它们嵌入到选项卡控制表、模式或非模式对话框、MDI 子框架和标准框架中。您甚至可以将其中的几个添加到一个表单中——这是嵌入式表单可能无法做到的。关键是为了最大程度的可重用性,通常需要分层方法,而框架有助于实现这一点。
框架适合随时嵌入。必须调整表单以不显示标题栏和边框,通常会覆盖CreateParams()
并相应地调整窗口样式。检查器中有更多的表单属性对嵌入式表单没有意义。恕我直言,应该使用足够的最基本和通用的实体。表单不仅仅是用于嵌入的控件容器。
OTOH我不知道嵌入框架没有嵌入表单的任何缺点。
编辑:
OnCreate
有关于类似或OnShow
框架没有的事件的评论。实际上,我认为框架的另一个优点是,因为事件处理程序没有参数,所以很多东西必然会以形式硬编码。
考虑每个用户设置的情况:在OnCreate
没有太多可用信息的情况下,因此最终总是使用常量或 INI 文件部分的表单名称,这使得重用表单或创建表单变得非常困难甚至不可能它的几个实例。另一方面,使用框架,方法LoadSettings
是显而易见的方法,它可以携带必要的参数。这样,控制就返回到它所属的地方,即嵌入框架/表单的容器。只有在可以从外部调整行为的情况下,才能实现可重用性。
对于不是组件且需要生命周期管理的包含对象,例如AfterConstruction
和BeforeDestruction
。
也许你会在这个线程中找到一些答案:gui-design-multiple-forms-vs-simulated-mdi-tabs-vs-pagecontrol
框架在创建框架时使用最快的加载并且没有延迟。
但是框架应该有一个嵌入它的父级。没有触发 onCreate 或 onShow 事件的缺点。但是您可以使用消息调用触发 onShow 事件,如下所示:
放在框架的私人部分:
procedure CMShowingChanged(var M: TMessage); message CM_SHOWINGCHANGED;
然后像这样创建代码:
procedure TFrame1.CMShowingChanged(var M: TMessage);
begin
inherited;
if Showing then
begin
// .... put your code for onShowing is triggered
end
else
begin
// .... put your code for onHiding is triggered
end;
end;
希望可以帮助您考虑 GUI 的嵌入式框架。
您可以考虑结合 PageControl 来控制您的框架打开。
曼兹
几年前我对我们的一个应用程序做出了同样的决定,我们想让它看起来像嵌入式表单,首先我使用 Frames 并编写了一个类来管理它。
后来我从LMDTools中找到了 TLMDDisplayForm 组件,这使得在其中嵌入表单变得非常容易,它减少了使用的代码并且我们拥有更多的功能。
我们从框架更改为表单的主要目标之一是缺少一些 TForm 事件,例如:OnCreate、OnShow、OnActive,我们在应用程序中用于某些任务,此外还缺少一些属性,例如:ActiveControl 和其他我不记得的东西.
如果您想使用 Forms,我建议您使用LMDTools,它可以让您更轻松地完成任务,除了基本版本是免费的 :-)
对于动态插入的表单/框架,我个人更喜欢在框架上使用嵌入式表单。回到几个版本,当人们编辑设置为 alClient 的框架时,框架将在编辑之间调整大小,并且特定于框架右侧对齐的任何控件都会改变位置。使用嵌入式表单时没有发生这种情况,所以我进行了切换。我相信这个问题现在已经在更高版本的 Delphi 中得到解决。
我非常同意 Mghie 之前提出的关于无法通过通知事件将信息传递到嵌入式表单的观点。为了解决这个问题,我通常在每个嵌入式表单中实现一系列接口用于通信。这确实简化了代码,并允许更通用的实现,其中您有一个“容器”,它将处理许多不同类型的嵌入式表单/框架。作为我设计的向导框架的一部分,我的博客上提供了一些示例。
我认为两者都应该使用。例如,我有一个“标准”框架,其中包含 dbnavigator、dbgrid 和数据源组件,这对于典型的数据浏览非常方便。我不是每次都插入这样的组件,而是插入一个框架,该框架也能够将其数据(使用 JVCL :D)导出为多种格式......但我知道我想在设计时显示什么,所以我建议非常简单规则:如果在设计时已知,则使用框架,否则使用嵌入式表单。
但是,请记住,表单不是为嵌入而设计的。像这样使用它们是不自然的(正如吸血鬼所说,当她埋葬她 80 岁的女儿时,她看起来像 30 岁:D)。嵌入式表单对拥有它的表单知之甚少,并且还可以(逻辑上)假设它不是嵌入式的。
作为补充,框架是一个组件,因此,当嵌入(拥有)在表单中时,表单知道它并且框架知道表单(可以使用它的方法和属性。嵌入式也可以这样做,但是需要额外的编码)
也许 Embarcadero 可以通过创建 TEmbeddableForm 或用于此类目的的接口来帮助我们
问候, 阿尔瓦罗·卡斯蒂耶罗
当您想在一个表单中多次重复“子表单”时,框架是很好的选择。我不会将它们用于选项卡式界面,因为嵌入式表单是 MDI/选项卡式界面使用的更好解决方案。