- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有两个“无模式”表单:
您可以看到:
从这个无模式表单中,我想显示一个模态表单:
Modal 表单的构造如下:
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 次了。上次我被 promise 将主窗体设为 MainForm 可以解决所有问题。
奖励:自 .NET 1.0 以来,WinForms 已正确处理此问题。
对于什么是模态对话框存在很多困惑。当您必须先与其交互才能继续使用其所有者之前,对话框就是模态对话框。来自 Windows Interface Design Guidelines :
Dialog boxes have two fundamental types:
- Modal dialog boxes require users to complete and close before continuing with the owner window. These dialog boxes are best used for critical or infrequent, one-off tasks that require completion before continuing.
- Modeless dialog boxes allow users to switch between the dialog box and the owner window as desired. These dialog boxes are best used for frequent, repetitive, on-going tasks.
Windows 有一个“所有者”的概念。当一个窗口被“拥有”时,它将始终显示在其所有者的顶部。当窗口是“模态”时,这意味着所有者被禁用,直到模态任务完成。
您可以在 ProgressDialog
中看到此效果API:
HRESULT StartProgressDialog(
[in] HWND hwndParent,
IUnknown *punkEnableModless,
DWORD dwFlags,
LPCVOID pvReserved
);hwndParent [in]
Type: HWND
A handle to the dialog box's parent window.dwFlags
Type: DWORD
PROGDLG_MODAL
The progress dialog box will be modal to the window specified by hwndParent. By default, a progress dialog box is modeless.
当然,你可能会很刻薄,并禁用所有其他窗口
但我想要有正确的行为。我想做的是:
自 1998 年以来,我就希望在我的 Delphi 应用程序中使用此功能;当意识到 Delphi 3 不能正确支持 Windows 95 和任务栏时。
最佳答案
ShowModal
禁用同一线程中的所有其他顶级窗口。这包括您的主要表单。
您必须巧妙地显示此表单,使其按照您想要的方式运行。执行以下操作:
Show
显示“模态”表单。您可以在步骤 2 和 3 之间运行您自己的模态消息循环,如 ShowModal
所做的那样,但这可能有点过头了。我只是显示表单为无模式,但禁用其所有者,使其相对于该所有者为“模态”。
这个过程有点微妙。查看 ShowModal
的源代码以获取灵感。此外,雷蒙德有关情态的史诗系列文章也是必读之物。我在这里链接到所有内容:Why does a MessageBox not block the Application on a synchronized thread?
雷蒙德提供的更多信息:The correct order for disabling and enabling windows :
When you destroy the modal dialog, you are destroying the window with foreground activation. The window manager now needs to find somebody else to give activation to. It tries to give it to the dialog's owner, but the owner is still disabled, so the window manager skips it and looks for some other window, somebody who is not disabled.
That's why you get the weird interloper window.
The correct order for destroying a modal dialog is
- Re-enable the owner.
- Destroy the modal dialog.
This time, when the modal dialog is destroyed, the window manager looks to the owner and hey this time it's enabled, so it inherits activation.
No flicker. No interloper.
关于delphi - 如何从非模式窗体显示模式对话框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31705874/
我是一名优秀的程序员,十分优秀!