【发布时间】:2015-10-20 18:06:05
【问题描述】:
我有两种“无模式”形式:
- 一个是特殊的MainForm
- 另一个是无模式形式
你可以看到:
- 两者都存在于任务栏上
- 都有一个任务栏按钮
- 两者都可以独立最小化
- 两者都可以独立恢复
- 两者都不总是在另一个之上(拥有)
现在显示一个模态表单
从这个无模式的表格中,我想展示一个有模式的:
模态形式被构造为:
var
frmExchangeConfirm: TfrmExchangeConfirm;
begin
frmExchangeConfirm := TfrmExchangeConfirm.Create(Application);
try
//Setting popupMode and popupParent still makes the MainForm disabled
// frmExchangeConfirm.PopupMode := pmExplicit;
// frmExchangeConfirm.PopupParent := Self; //owned by us
frmExchangeConfirm.OwnerForm := Self; //tell the form which owner to use
frmExchangeConfirm.ShowModal;
finally
frmExchangeConfirm.Free;
end;
通过新的OwnerForm 属性告诉模态表单使用哪个所有者:
protected
procedure SetOwnerForm(const Value: TForm);
public
property OwnerForm: TForm read GetOwnerForm write SetOwnerForm;
end;
强制重新创建句柄:
procedure TfrmExchangeConfirm.SetOwnerForm(const Value: TForm);
begin
FOwnerForm := Value;
if Self.HandleAllocated then
Self.RecreateWnd;
end;
然后是第二次通过CreateParams:
procedure TfrmExchangeConfirm.CreateParams(var Params: TCreateParams);
begin
inherited;
if FOwnerForm <> nil then
Params.WndParent := FOwnerForm.Handle;
end;
问题是:
- 一旦显示此拥有的模式表单,我就无法与 MainForm 交互
- 我无法使用任务栏按钮最小化 MainForm
- 我无法使用任务栏按钮最小化 Modal 或其所属的父级
- 如果我使用 Minimize 按钮最小化模态窗体,MainForm 就会消失
- 我可以使用它的任务栏按钮激活MainForm;但我无法与之互动
在过去十年中,我已经问过这个问题大约 7 次。上次我被承诺将主窗体设为 MainForm 将解决所有问题。
奖励:自 .NET 1.0 以来,WinForms 已正确处理此问题。
关于什么是模态对话框存在很多混淆。当您必须与它交互才能继续使用它的所有者时,对话框是模态的。来自Windows Interface Design Guidelines:
对话框有两种基本类型:
- 模式对话框要求用户在继续使用所有者窗口之前完成并关闭。这些对话框最适合用于需要在继续之前完成的关键或不频繁的一次性任务。
- 无模式对话框允许用户根据需要在对话框和所有者窗口之间切换。这些对话框最适合用于频繁、重复、持续的任务。
Windows 有一个“所有者”的概念。当一个窗口被“拥有”时,它总是会出现在它的所有者之上。当一个窗口是"modal"时,它意味着所有者被禁用,直到模态任务完成。
您可以在ProgressDialog API 中看到这种效果:
HRESULT StartProgressDialog( [in] HWND hwndParent, IUnknown *punkEnableModless, DWORD dwFlags, LPCVOID pvReserved );hwndParent [in]
类型:HWND
对话框的父窗口的句柄。dwFlags
类型:DWORD
PROGDLG_MODAL
进度对话框将模态到由 hwndParent 指定的窗口。默认情况下,进度对话框是无模式的。
当然,你可能很刻薄,并禁用所有其他窗口
- 在线程中
- 过程
- 或系统
但我希望有 正确的 行为。我想做:
- Windows 的作用
- Office 应用程序的作用
- Beyond Compare 的作用
- WinForms 的作用
- WPF 的作用
- 我用过的每个应用程序都做了什么
- 以及任何用户的期望
自 1998 年以来,我一直希望在我的 Delphi 应用程序中使用它;当意识到 Delphi 3 不能正确支持 Windows 95 和任务栏时。
【问题讨论】:
-
显示模态窗口时,框架是否禁用主窗体?这就是你需要停止发生的事情。
-
我想你先看看 DisableTaskWindows 是如何运作的
-
这就是模态的意思,它禁止与同一个线程的所有形式的交互,除了模态的。我猜你和承诺这个设置将通过模态工作的人之间存在误解。无论如何,不要使用showmodal,只需禁用您要禁用的窗口即可。
-
@SertacAkyuz 模态窗口的重点不是禁用进程中的所有其他窗口,it's to disable the window's owner
-
...该文档引用了previous document,其中包括作者自己的定义:“从最终用户的角度来看,当用户被锁定完成任务时,就会出现模态一旦开始,唯一的逃避就是取消整个操作。”
标签: delphi delphi-xe6