首页 > 解决方案 > 显示禁用的模态表单

问题描述

我正在尝试禁用 aTForm的后代并将其显示为模态形式。

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

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

错误说的图片

无法制作可见的窗口模式。

标签: delphidelphi-xe7

解决方案


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

禁用表单是错误的做法。

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

另外,禁用表单而不是实际的控件会使控件看起来是启用的,这很混乱!这是很重要的一点。

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


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

标准对话框的屏幕截图。

如果我做

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

然后它看起来像这样:

禁用时显示的表单屏幕截图。 它看起来与上一个屏幕截图中的完全一样! 没有任何东西看起来被禁用!

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

事实上,您甚至无法使用其标题栏关闭按钮或 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;

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

表单的屏幕截图,其中除“取消”按钮之外的所有控件都已禁用,包括标签。

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


推荐阅读