显示禁用的模态表单

时间:2021-06-18 07:07:44

标签: delphi delphi-xe7

我正在尝试禁用 TForm 的后代并将其显示为模态表单。

procedure TForm1.Button1Click(Sender: TObject);
var
  Frm : TMyForm;
begin
  Frm := TMyForm.Create(nil);
  try
    Frm.Enabled := False;
    Frm.ShowModal();
  finally
    Frm.Free;
  end;
end;

在运行时,它会引发以下错误消息:

Picture of the error saying "Cannot make a visible window modal"

<块引用>

无法使可见窗口模态化。

1 个答案:

答案 0 :(得分:4)

当表单应显示为只读目的时,OP 希望以模态方式显示禁用的表单。

禁用表单是错误的做法。

如何显示信息?如果您使用 TEditTMemoTRichEdit 控件,您应该将它们设置为只读。否则,如果您有各种控件(如单选按钮)的某些组合,则应禁用每个此类控件,而不是表单本身。我的意思是,您确定仍希望启用 取消 按钮吗?

此外,禁用表单而不是实际控件会使控件看起来启用,这很令人困惑!这是很重要的一点。

所以您需要做的是正常显示表单(而不是禁用!),然后在显示对话框时将其控件设置为适当的状态。


为了强调我关于禁用表单与其控件的观点,请考虑以下对话框:

Screenshot of a standard dialog box.

如果我这样做

procedure TCustomViewFrm.FormShow(Sender: TObject);
begin
  Enabled := False;
end;

然后它看起来像这样:

Screenshot of the form displayed when disabled. It looks exactly like it did in the last screenshot! Nothing looks disabled!

如您所见,每个控件看起来确实非常有效,但没有控件响应鼠标或键盘输入。这非常令人困惑,而且用户体验非常糟糕。

事实上,您甚至无法使用其标题栏关闭按钮或 Alt+F4 关闭对话框。您也无法使用其系统菜单关闭它。事实上,您根本无法关闭它,因为要关闭一个窗口,它必须响应用户输入,而禁用的窗口则不会这样做。 (你也不能移动窗口。)

相反,如果我们禁用所有控件(取消按钮除外),

procedure DisableControl(AControl: TWinControl);
begin
  for var i := 0 to AControl.ControlCount - 1 do
  begin
    if
      (AControl.Controls[i] is TCustomButton)
        and
      (TCustomButton(AControl.Controls[i]).ModalResult = mrCancel)
    then
      Continue;
    if AControl.Controls[i] is TWinControl then
      DisableControl(TWinControl(AControl.Controls[i]));
    AControl.Controls[i].Enabled := False;
  end;
end;

procedure TCustomViewFrm.FormShow(Sender: TObject);
begin
  DisableControl(Self);
end;

你得到了这个漂亮的用户界面:

Screenshot of the form with all its controls except for the Cancel button disabled, including the labels.

不仅非常清楚所有控件都被禁用,用户还可以使用任务管理器关闭对话框而不杀死您的应用程序。