我有两个"无模式" 表单:
你可以看到:
从这种无模式的形式,我想展示一个模态:
模态表单构造如下:
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;
问题是:
在过去的十年里,我已经问了7次这个问题。我最后一次承诺,将主要形式 MainForm 解决所有问题。
奖金:自.NET 1.0起,WinForms已正确处理此问题。
关于模态对话框的内容存在很多混淆。在您继续使用其所有者之前必须与其进行交互时,对话框是模态的。来自Windows Interface Design Guidelines:
对话框有两种基本类型:
- 模式对话框要求用户在继续所有者窗口之前完成并关闭。这些对话框最适用于需要在继续之前完成的关键或不常见的一次性任务。
- 无模式对话框允许用户根据需要在对话框和所有者窗口之间切换。这些对话框最适合用于频繁,重复和正在进行的任务。
Windows具有&#34;所有者&#34; 的概念。当一个窗口&#34;拥有&#34; 时,它将始终显示在其所有者之上。当窗口为&#34; modal&#34; 时,表示所有者被禁用,直到模态任务完成。
您可以在ProgressDialog
API中看到此效果:
HRESULT StartProgressDialog( [in] HWND hwndParent, IUnknown *punkEnableModless, DWORD dwFlags, LPCVOID pvReserved );
hwndParent [in]
输入: HWND
对话框的父窗口的句柄。dwFlags中
键入: DWORD
的 PROGDLG_MODAL
进度对话框将模态为 hwndParent 指定的窗口。默认情况下,进度对话框是无模式的。
当然,你可能是卑鄙的,并禁用所有其他窗口
但我希望正确的行为。我想这样做:
自1998年以来,我一直想在我的Delphi应用程序中使用它;当实现Delphi 3没有正确支持Windows 95和任务栏时。
答案 0 :(得分:7)
ShowModal
禁用同一线程中的所有其他顶级窗口。这包括你的主要表格。
您必须巧妙地显示此表单,以使其按您希望的方式运行。执行以下操作:
Show
你可以在第2步和第3步之间运行自己的模态消息循环,就像ShowModal
那样,但这可能有点过分。我只是将表单显示为无模式,但禁用其所有者使其与该所有者“模态”。
这个过程有点微妙。查看ShowModal
的来源获取灵感。此外,雷蒙德关于情态的史诗系列文章是必不可少的阅读。我在此处链接到所有内容:Why does a MessageBox not block the Application on a synchronized thread?
Raymond的更多内容:The correct order for disabling and enabling windows:
当你破坏模态对话框时,你正在通过前景激活来破坏窗口。窗口管理器现在需要找到其他人来激活。它试图将它提供给对话框的所有者,但是所有者仍然被禁用,因此窗口管理器会跳过它并查找其他窗口,即未被禁用的窗口。
这就是你得到奇怪的闯入者窗口的原因。
销毁模态对话框的正确顺序是
- 重新启用所有者。
- 销毁模态对话框。
这一次,当模态对话框被销毁时,窗口管理器会向所有者查找,而这次它已启用,因此它继承了激活。
没有闪烁。没有闯入者。