首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TProc<TObject>到TNotifyEvent

TProc<TObject>到TNotifyEvent
EN

Stack Overflow用户
提问于 2012-07-15 19:45:00
回答 2查看 8K关注 0票数 18

关于这个post,它被接受的答案仍然非常神秘:

代码语言:javascript
复制
@Button1.OnClick := pPointer(Cardinal(pPointer( procedure (sender: tObject) begin ((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' end )^ ) + $0C)^;

我想知道是否有可能设计出一种最简单和优雅的方法,类似于:

代码语言:javascript
复制
Button.OnClick :=
                    AnonProc2NotifyEvent (
                    procedure (Sender: TObject)
                    begin
                      ((Sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!'
                    end
                      );

以便达到相同的目的,并且其中AnonProc2NotifyEvent是具有以下签名的按钮的所有者的方法:

代码语言:javascript
复制
TOwnerOfButton = class(TForm)
  Button: TButton;
  ...
private
  ...
protected
  function AnonProc2NotifyEvent(aProc: TProc<TObject>): TNotifyEvent;
public
  ...
end;

这是可行的吗?如果可行,如何实现?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-15 20:11:19

这将很容易地完成这项工作:

代码语言:javascript
复制
type
  TNotifyEventWrapper = class(TComponent)
  private
    FProc: TProc<TObject>;
  public
    constructor Create(Owner: TComponent; Proc: TProc<TObject>);
  published
    procedure Event(Sender: TObject);
  end;

constructor TNotifyEventWrapper.Create(Owner: TComponent; Proc: TProc<TObject>);
begin
  inherited Create(Owner);
  FProc := Proc;
end;

procedure TNotifyEventWrapper.Event(Sender: TObject);
begin
  FProc(Sender);
end;

function AnonProc2NotifyEvent(Owner: TComponent; Proc: TProc<TObject>): TNotifyEvent;
begin
  Result := TNotifyEventWrapper.Create(Owner, Proc).Event;
end;

AnonProc2NotifyEvent中的Owner参数是为了管理包装器对象的生命周期。如果没有这样的东西,就会泄漏TNotifyEventWrapper的实例。

将事件连接到的组件作为Owner传递。例如:

代码语言:javascript
复制
Button1.OnClick := AnonProc2NotifyEvent(
  Button1,
  procedure(Sender: TObject)
  begin
    (Sender as TButton).Caption := 'Clicked';
  end
);

因此,当按钮被销毁时,TNotifyEventWrapper也将被销毁。包装器对象的生存时间必须至少与它与其关联的事件的对象一样长。因此,选择Button1作为所有者是很自然和显而易见的。

票数 38
EN

Stack Overflow用户

发布于 2012-07-15 22:00:11

为了参考这一点,我研究了上面提到的前一篇SO文章中提到的Barry Kelly的博客post,并提出了这个解决方案:

代码语言:javascript
复制
function TMainForm.Proc2NotifyEvent(const aProc: TNotifyReference): TNotifyEvent;
type
  TVtable = array[0..3] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  TMethod(Result).Code := PPVtable((@aProc)^)^^[3];
  TMethod(Result).Data := Pointer((@aProc)^);
end;

仍然是神秘的,但被封装了,所以与最初的方法相比,简化了编码器的任务。

我试图整理MethRefToMethPtrMakeNotify,并将其放在一个方法中。

请注意,该方法的签名有(轻微)更改,参数aProc变为const。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11491593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档