11

我有一个应用程序,其中有一个主背景表单,用户只能从那里维护系统不同部分的非模态表单。非模态表单会覆盖 CreateParams 方法,因此每个表单都会在开始任务栏中显示一个按钮:

procedure TfmMaterialsPlanning.CreateParams(var Params: TCreateParams);
begin
   inherited;
   //create a new window on the task bar when this form is created
   Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

实际上,用户可以打开一个维护“Apples”的非模态表单,另一个维护“Oranges”的非模态表单,并使用开始菜单栏在两者之间轻松切换。

但是,如果他们从“Apples”表单打开一个模态表单,例如设置选项、偏好等,那么他们在关闭该模态表单之前不能使用“Oranges”表单。

是否可以仅将模态表单模态到父表单?那么如果他们打开苹果的选项表,他们就不能使用苹果的维护表,但仍然可以使用橙子的维护表?

4

5 回答 5

6

如果您查看 TCustomForm.ShowModal() 的源代码,您将看到 VCL 不使用 Windows API 调用来显示模态对话框,而是在模态表单显示时禁用应用程序中的所有其他表单显示。您当然可以尝试同样的方法,只需 Show() 表单模式对话框,然后禁用父级,然后在表单模式对话框关闭后重新启用它。需要有一个中心位置来跟踪表单模式对话框、需要重新启用的表单等。但是,即使在应用程序之间来回切换、最小化应用程序等时,您也应该彻底测试代码是否确实按照您的意愿执行。

话虽如此 - 我认为这根本不是一个好主意。它打破了 Windows 用户对应用程序行为所做的所有假设。与 Mac OS X 不同,Windows 中应用程序模式对话框和表单模式对话框之间没有区别,您应该坚持与您正在编程的平台一致的行为。

很可能有更好的方式来构建你的 UI。查看“Windows 用户体验交互指南”中对话框的相关页面。最好尽可能避免模态对话框,链接的指南显示了许多用例的更好选择。如果您限制使用模态对话框,也许您不再需要表单模态对话框。

于 2009-01-21T08:06:07.000 回答
3

这篇文章有一个很好的技巧来满足您的需求:http: //blogs.teamb.com/deepakshenoy/2006/08/21/26864

摘要是在模态窗口禁用它时重新启用您想要的非模态窗口。

于 2010-09-15T15:56:12.287 回答
0

顺便说一句(尽管这将是大量工作),解决这个问题的另一种方法是 Google 的 chrome 的方式,其中每个“选项卡”都是一个单独的进程,但在用户看来是一个单独的集成应用程序。

即使这种方法可以实现您想要的,我也必须同意上面的评论,即这会打破用户对模态行为的假设和期望。

于 2009-01-21T09:09:45.360 回答
0

您不能通过阻止“Apples”表单在其子表单打开时接受焦点来达到相同的效果吗?

于 2009-01-21T03:10:22.463 回答
-1

如果您在自己的线程中创建每个非模态表单,这是可能的。然后每个模态表单将阻塞它所属的线程。

编辑:这应该是可能的,即使 vcl 不是线程安全的。请看一下Alexeys 对 如何做到这一点的解释:

因此,如果您有一组应该存在于单独线程中的表单,则将它们放入一个 dll 中,在没有包的情况下编译并使用!它会工作并且是线程安全的。

于 2009-01-21T08:02:31.937 回答