Delphi 是否提供用于表单创建通知的事件处理程序?

mjn*_*mjn 5 forms delphi aop dynamic

Delphi 是否提供某种用于表单创建的事件或挂钩(或者更一般地说,表单生命周期事件)?

因此,如果在代码中的某处创建并显示表单(模态或非模态,动态或在通常的应用程序启动阶段),Delphi 会调用一个事件处理程序,该处理程序允许在显示之前记录/分析/修改表单?

我知道有一些选项涉及引入基本表单类或自定义表单创建过程,但对于已经拥有许多表单的现有应用程序来说,“最好”有一个非侵入性选项来添加类似于横切关注点的内容在面向方面编程(AOP)中。

例如,如果我有一些用于注入额外事件处理程序的使用情况统计跟踪代码,我可以简单地为每个表单添加此功能,开发人员不必更改应用程序代码,只需添加与此类似的代码

...
   Application.OnNewForm := MyNewFormCreated;
...

procedure TMyApp.MyNewFormCreated(Sender: TCustomForm);
begin
  // iterate over components and do other stuff with the new form
  ...
end;
Run Code Online (Sandbox Code Playgroud)

Arn*_*hez 5

在运行时,您可以重写TCustomForm.DoCreateTCustomFrame.Create方法,如下所示:

type
  THookedForm = class(TCustomForm)
    procedure HookedDoCreate;
  end;

  THookedFrame = class(TCustomFrame)
    constructor Create(AOwner: TComponent); override;
  end;

var
  OriginalForm, OriginalFrame: TPatchCode;

procedure PatchCreate;
begin
  if OriginalForm[0]<>0 then
    exit; // patch once
  RedirectCode(@THookedForm.DoCreate,@THookedForm.HookedDoCreate,@OriginalForm);
  RedirectCode(@THookedFrame.Create,@THookedFrame.Create,@OriginalFrame);
end;


// hook logic was inspired from GetText()

{ THookedForm }

procedure THookedForm.HookedDoCreate;
// translate form contents just before an OnCreate handler would be called
begin
  try
  try
    if Language<>nil then begin
      DisableAlign;
      DisableAutoRange;
      try
        Language.FormTranslateOne(self); // translate form
      finally
        EnableAlign;
        EnableAutoRange;
      end;
    end;
  finally
    RedirectCodeRestore(@THookedForm.DoCreate,OriginalForm); // disable Hook
    try
      DoCreate;  // call normal DoCreate event
    finally
      RedirectCode(@THookedForm.DoCreate,@THookedForm.HookedDoCreate);
    end;
  end;
  except
    on Exception do; // ignore all raised exception
  end;
end;

{ THookedFrame }

constructor THookedFrame.Create(AOwner: TComponent);
// translate frame contents just after constructor has been called
begin
  RedirectCodeRestore(@THookedFrame.Create,OriginalFrame); // disable Hook
  try
    inherited Create(AOwner); // call normal constructor
  finally
    RedirectCode(@THookedFrame.Create,@THookedFrame.Create);
  end;
  if Language=nil then exit;
  DisableAlign;
  DisableAutoRange;
  try
    Language.FormTranslateOne(self); // translate frame
  finally
    EnableAlign;
    EnableAutoRange;
  end;
end;


....

initialization
  PatchCreate;
Run Code Online (Sandbox Code Playgroud)

因此,DoCreate每次创建 TForm 实例时都会调用您自己的事件。

此代码是从mORMoti18n.pas中提取的,您可以在SynCommons.pas中找到补丁例程(适用于 Windows 和 Linux/BSD)。


Ken*_*ssa 2

我目前能想到的最适合您需要的选项是 Screen.OnActiveFormChange每次当前活动表单更改时触发的事件。但这对于您的需求来说可能为时已晚。