在我的应用程序中,我有多种形式可以同时显示,它们都以相同的大小单位显示磁盘空间(文件,硬盘大小等)。因此它们全部以字节,KB,MB,GB或TB显示磁盘空间。我还有一个单独的设置表单,用户可以在其中以其他形式更改显示尺寸。用户在设置表单中单击“确定”后,我希望所有其他(打开的)表单立即更改其大小设置。

每个表单都有一个受保护的过程SetViewSettings,该过程负责这项工作。它们都是祖先形式的后代,该祖先形式将SetViewSettings定义为虚拟的和抽象的。实际显示的表单将覆盖祖先的SetViewSettings方法。到目前为止没有问题。

因为我不想调用每个单独的表单(FormX.SetViewSettings,FormY.SetViewSettings等),所以我使用以下解决方案:

procedure TApplicationForms.SetUnits;
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
    if Screen.Forms[I] is TfrAncestorInfo then
      with Screen.Forms[I] as TfrAncestorInfo do
        acSetUnits.Execute;
end;


用户单击“确定”时,将从SettingsForm中调用此过程。
TFrAncestorInfo是TForm的后代,将SetViewSettings方法声明为虚拟的和抽象的。 acSetUnits是一个在TfrAncestorInfo中声明的Action,它仅调用SetViewSettings。一切正常,但风险在于创建新的TFrAncestorInfo子孙形式,而忘记覆盖SetViewSettings方法,在这种情况下,您将遇到“抽象错误”异常。

在不单独列出(调用)所有后代表单的情况下,是否有其他方法可以调用表单中的SetViewSettings方法?我知道消息和事件,但是我不知道如何在多种形式的情况下使用它们。通常:如何直接向所有TFrAncestorInfo后代表单发送消息或为其生成事件,而无需单独列出它们?

最佳答案

一种选择(有许多其他可能的选择)是向每个表单发送自定义消息。无需担心虚拟/抽象重写,类型检查等问题。只有实现消息处理程序的窗体会对消息做出反应,其余的将简单地忽略它。

const
  WM_SETTINGS_UPDATED = WM_APP + 1;

procedure TApplicationForms.SetUnits;
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
    Screen.Forms[I].Perform(WM_SETTINGS_UPDATED, 0, 0);
end;




type
  TSomeForm = class(TBaseForm)
  private
    procedure WMSettingsUpdated(var Message: TMessage); message WM_SETTINGS_UPDATED;
  protected
    procedure SetViewSettings;
  end;

procedure TSomeForm.WMSettingsUpdated(var Message: TMessage);
begin
  SetViewSettings;
end;

procedure TSomeForm.SetViewSettings;
begin
  //...
end;

09-18 03:21