我有一个应用程序,其中一个不可见的“主机”应用程序对象创建主窗体,而主窗体临时创建数据监视对话框窗体。
“主机”中有一个异步数据接收器,具有跟踪输出事件。当对话框存在时,此事件应与数据监视对话框窗体的方法临时绑定,而在将其销毁时取消绑定。
我在下面最小化了此应用程序。您能检查一下这样做是否正确吗?请注意“注意”注释。
program BindToTempObject;
uses
Vcl.Forms, System.Classes, Vcl.StdCtrls, Vcl.ExtCtrls, System.SysUtils;
type
TBoolEvent = procedure(b: Boolean) of object;
TDialogForm = class(TForm)
public
constructor Create(AOwner: TComponent); override;
procedure BoolEventHandler(b: Boolean);
end;
TMainForm = class(TForm)
private
_btn: TButton;
_onBoolEventRelay: TBoolEvent; //Attention
procedure _btnClick(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
procedure BoolEventRelay(b: Boolean); //Attention
end;
TAppObject = class
private
_mainForm: TMainForm;
_eventSource: TTimer;
_boolState: Boolean;
procedure _eventSourceTick(Sender: TObject);
public
OnBoolEvent: TBoolEvent;
constructor Create();
destructor Destroy(); override;
end;
var
app: TAppObject;
{ TAppObject }
constructor TAppObject.Create();
begin
Application.CreateForm(TMainForm, _mainForm);
OnBoolEvent := _mainForm.BoolEventRelay; //Attention
_eventSource := TTimer.Create(nil);
_eventSource.OnTimer := _eventSourceTick;
_eventSource.Enabled := True;
end;
destructor TAppObject.Destroy();
begin
_eventSource.OnTimer := nil;
_eventSource.Free();
inherited;
end;
procedure TAppObject._eventSourceTick(Sender: TObject);
begin
_boolState := not _boolState;
if Assigned(OnBoolEvent) then OnBoolEvent(_boolState);
end;
{ TMainForm }
constructor TMainForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Main form';
_btn := TButton.Create(Self);
_btn.Parent := Self;
_btn.Caption := 'Click me';
_btn.OnClick := _btnClick;
end;
procedure TMainForm.BoolEventRelay(b: Boolean);
begin
if Assigned(_onBoolEventRelay) then _onBoolEventRelay(b); //Attention
end;
procedure TMainForm._btnClick(Sender: TObject);
var
dlg: TDialogForm;
begin
dlg := TDialogForm.Create(Self);
try
_onBoolEventRelay := dlg.BoolEventHandler; //Attention
dlg.ShowModal();
finally
_onBoolEventRelay := nil; //Attention
dlg.Free();
end;
end;
{ TDialogForm }
procedure TDialogForm.BoolEventHandler(b: Boolean);
begin
Caption := BoolToStr(b, True);
end;
constructor TDialogForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Dialog form';
end;
begin
Application.Initialize();
app := TAppObject.Create();
try
Application.Run();
finally
app.Free();
end;
end.
答案 0 :(得分:1)
您肯定可以那样做。班级之间的职责分工合理,因此他们不必彼此了解。
但是,在您的特定示例中,由于所有内容都在一个单元中,并且app
对象是全局可访问的,因此可以通过将TDialogForm.BoolEventHandler()
方法直接分配给对象来简化代码TAppObject.OnBoolEvent
事件,并以中间人身份摆脱TMainForm
:
program BindToTempObject;
uses
Vcl.Forms, System.Classes, Vcl.StdCtrls, Vcl.ExtCtrls, System.SysUtils;
type
TBoolEvent = procedure(b: Boolean) of object;
TDialogForm = class(TForm)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy(); override;
procedure BoolEventHandler(b: Boolean);
end;
TMainForm = class(TForm)
private
_btn: TButton;
procedure _btnClick(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
end;
TAppObject = class
private
_mainForm: TMainForm;
_eventSource: TTimer;
_boolState: Boolean;
procedure _eventSourceTick(Sender: TObject);
public
OnBoolEvent: TBoolEvent;
constructor Create();
destructor Destroy(); override;
end;
var
app: TAppObject;
{ TAppObject }
constructor TAppObject.Create();
begin
Application.CreateForm(TMainForm, _mainForm);
_eventSource := TTimer.Create(nil);
_eventSource.OnTimer := _eventSourceTick;
_eventSource.Enabled := True;
end;
destructor TAppObject.Destroy();
begin
_eventSource.OnTimer := nil;
_eventSource.Free();
inherited;
end;
procedure TAppObject._eventSourceTick(Sender: TObject);
begin
_boolState := not _boolState;
if Assigned(OnBoolEvent) then OnBoolEvent(_boolState);
end;
{ TMainForm }
constructor TMainForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Main form';
_btn := TButton.Create(Self);
_btn.Parent := Self;
_btn.Caption := 'Click me';
_btn.OnClick := _btnClick;
end;
procedure TMainForm._btnClick(Sender: TObject);
var
dlg: TDialogForm;
begin
dlg := TDialogForm.Create(Self);
try
dlg.ShowModal();
finally
dlg.Free();
end;
end;
{ TDialogForm }
procedure TDialogForm.BoolEventHandler(b: Boolean);
begin
Caption := BoolToStr(b, True);
end;
constructor TDialogForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Dialog form';
app.OnBoolEvent := BoolEventHandler;
end;
destructor TDialogForm.Destroy();
begin
app.OnBoolEvent := nil;
inherited;
end;
begin
Application.Initialize();
app := TAppObject.Create();
try
Application.Run();
finally
app.Free();
end;
end.