Delphi,框架与表单。多文档界面怎么样?
昨天我开始讨论“MDI 与选项卡式界面”。我问过是否应该继续开发基于 MDI 的应用程序,或者是否应该将子表单嵌入到选项卡中。 有人指出我应该使用 TFrames...我的问题是:为什么?
在 TFrame 上嵌入表单时使用 TFrame 有何优点?到目前为止我什么都不知道,切换只需要我重写代码的某些部分......
(无论如何我不会在设计时使用嵌入!)
提前致谢
yesterday I've started discussion on "MDI vs tabbed interface". I've asked whether should I continue developing my app as MDI-based, or should I embed the child forms into tab sheets.
Someone pointed that I should use TFrames instead... My question is: why?
What are pros of using TFrames when embedding the form over TFrame? So far I don't know any, switching would only require me to rewrite some parts of code...
(I'm not going to use embedding at design time anyway!)
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
回答评论以提供使用框架的原因:
我认为框架是 GUI 的构建块,在设计时将现有组件组合到更高级的组件。在 Delphi 5 之前,人们会使用带有子控件的
TCustomPanel
后代,并将其注册为新组件,准备将其拖放到表单上。框架可以以更少的麻烦实现同样的事情。它们使您能够专注于开发您所需要的功能,仅此而已。如果做得好,您可以将它们嵌入到选项卡控制表、模态或非模态对话框、MDI 子框架和标准框架中。您甚至可以将其中的几个添加到一个表单中 - 这对于嵌入式表单来说可能不会这样做。要点是,为了获得最大的可重用性,分层方法通常是必要的,而框架可以帮助实现这一点。
框架适合随时随地嵌入。表单必须调整为不显示标题栏和边框,通常会覆盖
CreateParams()
并相应地调整窗口样式。检查器中还有更多表单属性,这些属性对于嵌入表单来说没有意义。恕我直言,应该使用最基本、最通用的实体就足够了。表单不仅仅是一个用于嵌入的控件容器。OTOH 我不知道嵌入框架有什么嵌入表单所没有的缺点。
编辑:
有一条关于框架没有的事件的注释,例如
OnCreate
或OnShow
。实际上,我认为框架的另一个优点是,因为事件处理程序没有参数,所以很多东西必然会在表单中进行硬编码。考虑每用户设置的情况:在 OnCreate 中没有太多可用信息,因此最终总是使用常量或 INI 文件部分的表单名称,这使得它非常困难甚至不可能重用该表单或创建它的多个实例。另一方面,对于框架,方法
LoadSettings
是执行此操作的明显方法,并且它可以携带必要的参数。这样,控制权就会返回到它所属的位置,即嵌入框架/表单的容器。只有可以从外部调整行为,才可能实现可重用。对于不是组件且需要生命周期管理的包含对象,例如有
AfterConstruction
和BeforeDestruction
。Answering the comment to provide a reason why to use frames:
I would consider frames to be building blocks of the GUI, with design time combination of existing components to more advanced components. Before Delphi 5 one would have used a
TCustomPanel
descendant with child controls and registered this as the new component, ready to be dropped onto a form. Frames allow for the same thing with less hassle.They allow you to concentrate on developing exactly the functionality you need, and nothing more. Done right you can then embed them into tab control sheets, into modal or modeless dialogs, into MDI child frames and into standard frames. You can even add several of them into one form - something one would probably not do with embedded forms. The point is that for maximum reusability a layered approach is often necessary, and frames help with that.
A frame is fit for embedding from the go. A form has to be adapted to not show a caption bar and border, normally one would override the
CreateParams()
and adjust the window style accordingly. There are a lot more form properties in the inspector that just don't make sense for an embedded form. IMHO one should use the most basic and generic entity that suffices. A form just is much more than a control container for embedding.OTOH I don't know of any disadvantage of embedding a frame that embedding a form wouldn't have.
Edit:
There's a comment regarding events like
OnCreate
orOnShow
that frames don't have. Actually, I'd consider that another advantage of frames, as event handlers don't have parameters, so a lot of stuff gets hard-coded in forms, necessarily.Consider the case of per-user settings: in
OnCreate
there's not much information available, so one invariably ends up using a constant or the name of the form for the INI file section, making it very hard or even impossible to reuse the form or to create several instances of it. With frames on the other hand a methodLoadSettings
is the obvious way to do it, and it can carry the necessary parameters. That way control is returned to where it belongs, to the container of the embedded frame / form. Reusability is only possible if the behaviour can be adjusted from the outside.For contained objects that are not components and need to be lifetime-managed, there are for example
AfterConstruction
andBeforeDestruction
.也许您会在此线程中找到一些答案: gui-设计多种表单与模拟-mdi-tabs-vs-pagecontrol
Maybe you will find some answers in this thread: gui-design-multiple-forms-vs-simulated-mdi-tabs-vs-pagecontrol
框架在创建框架时使用最快的加载且无延迟。
但框架应该有一个父框架来嵌入它。缺点是没有触发onCreate或onShow事件。但是您可以使用消息来调用触发 onShow 事件,如下所示:
放在框架的私有部分:
然后创建如下代码:
希望可以帮助您考虑 GUI 的嵌入式框架。
您可以考虑结合PageControl来控制您的框架打开。
曼兹
Frame use the fastest load and without delay when creating the frame.
But the frame should be has a parent to embedded it. Disadvantage with no onCreate or onShow event has been triggered. but you can call with message for trigger onShow event like this one :
put on private section of frame:
and then create the code like this :
Hope can helping you to consider embedded frame for GUI.
You may consider combined with PageControl to control your frame opening.
Manz
几年前,我对我们的一个应用程序做出了同样的决定,我们想让它看起来像嵌入式表单,首先我使用了框架,并编写了一个类来管理它。
后来我从 LMDTools 找到了 TLMDDisplayForm 组件,这使得在其中嵌入表单变得非常容易,它减少了使用的代码我们还有更多功能。
我们从框架更改为表单的主要目标之一是缺少 TForm 的一些事件,例如:OnCreate、OnShow、OnActive,我们在应用程序中使用它们来执行某些任务,此外还缺少一些属性,例如:ActiveControl 和其他我不记得的东西。
如果您想使用 Forms,我建议您使用 LMDTools 它可以让您更轻松地完成任务,除了基本版本是免费的:-)
I had same decision few years ago for one of our applications, we wanted to make it looks embedded forms, first I used the Frames and I wrote a class to manage it.
Later I found TLMDDisplayForm component from LMDTools, which making embedding forms inside it very easy task, it reduced the code used and we have more features.
one of main goals that we changed from frames to Forms was missing some events of TForm like: OnCreate, OnShow, OnActive which we use for some tasks in our applications, beside missing some properties such as: ActiveControl and other things I don't remember.
If you would like to go with Forms, I suggest you to use LMDTools which make the task easier for you, beside the basic version is free :-)
对于动态插入的表单/框架,我个人更喜欢使用嵌入式表单而不是框架。在几个版本中,当人们编辑设置为 alClient 的框架时,框架会在编辑之间调整大小,并且特定于框架右侧对齐的任何控件都会改变位置。当使用嵌入式表单时,这种情况没有发生,所以我进行了切换。我相信这个问题现在已经在 Delphi 的更高版本中得到解决。
我非常同意 Mghie 之前提出的关于无法通过通知事件将信息传递到嵌入表单的观点。为了解决这个问题,我通常在每个嵌入式表单中实现一系列接口以进行通信。这确实简化了代码,并允许更通用的实现,其中您有一个“容器”来处理许多不同类型的嵌入表单/框架。我的博客上提供了一些这样的示例,作为我设计的向导框架的一部分。
For dynamically inserted forms/frames I personally prefer to use embedded forms over frames. Several versions back when one would edit a frame which was set to alClient, the frame would resize between edits and any controls which were aligned specific to the right of the frame would change position. When using embedded forms this didn't happen so I made the switch. I believe this issue is now fixed with later versions of Delphi.
I strongly agree with the points Mghie made earlier regarding the inability to pass information to the embedded form through notification events. To solve this I generally implement a series of interfaces in each embedded form for communication. This really simplifies the code, and allows for more generic implementations where you have a single "container" that will be dealing with many different types of embedded forms/frames. A few examples of this are available on my blog as part of the wizard framework I designed.
我认为两者都应该使用。例如,我有一个“标准”框架,其中包含 dbnavigator、dbgrid 和数据源组件,这对于典型的数据浏览非常方便。我不是每次都插入这样的组件,而是插入一个框架,该框架还能够将其数据(使用 JVCL :D)导出为多种格式......但我知道我想在设计时显示什么,所以我建议一个非常简单规则:如果在设计时已知,则使用框架,否则使用嵌入式表单。
但是,请记住,表单并不是为嵌入而设计的。像这样使用它们是不自然的(就像一个吸血鬼在埋葬她 80 岁的女儿时所说的那样,而她看起来像 30 岁:D)。嵌入的表单对拥有它的表单知之甚少,并且也可以(逻辑上)假设它不是嵌入的。
补充一下,框架是一个组件,因此,当嵌入到表单中(由其拥有)时,表单知道它,框架也知道表单(可以使用它的方法和属性。嵌入的框架也可以这样做,但是需要额外的编码)
也许 Embarcadero 可以通过创建 TEmbeddableForm 或用于此类目的的接口来帮助我们
问候,
阿尔瓦罗·卡斯蒂洛
I think both should be used. For example, I have a "standard" frame that has a dbnavigator, dbgrid and datasource components which is very handy for the typical data browsing. Instead of inserting such components every time, I insert a frame that also has the ability to export its data (with JVCL :D) to several formats...but I know what I want to display at design time, so I suggest a very easy rule: if it is known at design time, use frames, otherwise use embedded forms.
However, keep in mind that forms were not designed to be embedded. Using them like so, its unnatural (as a vampire states when she buries her 80 old year daughter and she looked like 30 :D). The embedded form knows little about the one that owns it and can also (logically) assume that is not embedded.
Complementing that, a frame is a component, and so, when embedded (owned by) in a form, the form knows about it and the frame knows about the form (can use its methods and properties. An embedded one can also do that but requires extra coding)
Perhaps Embarcadero could give us a hand by creating a TEmbeddableForm or an interface for such purposes
Regards,
Alvaro Castiello
当您想在表单中多次重复“子表单”时,框架是很好的选择。我不会将它们用于选项卡式接口,因为嵌入式表单是 MDI/选项卡式界面使用的更好解决方案。
Frames are good when you want to repeat a "sub-form" multiple times in a form. I'd not use them for tabbed interfacing, as the embedded form is a better solution for MDI/Tabbed interface use.