显示禁用的模态表单

Displaying a disabled modal form

我正在尝试禁用 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;

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

Cannot make a visible window modal.

当出于 read-only 目的应该显示表单时,OP 希望以模态方式显示禁用的表单。

禁用表单是错误的做法。

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

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

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


只是为了强调我关于禁用窗体及其控件的观点,考虑这个对话框:

如果我这样做

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

那么显示的时候是这样的:

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

事实上,您甚至无法使用 title-bar 关闭按钮或 Alt+F4 关闭对话框。您也无法使用其系统菜单关闭它。事实上,您根本无法关闭它,因为要关闭 window,它必须响应用户输入,而禁用的 window 不会那样做。 (你也不能移动 window。)

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

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;

你真棒 UI:

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