如何检查两个事件是否指向Delphi中的相同过程?

时间:2011-08-01 08:58:16

标签: delphi events

假设我有一个Button1.OnClick事件链接到Button1Click程序。我也将Button2.OnClick链接到其他一些程序。如何检查两个事件是否与运行时的不同或相同过程相关联?

我试图测试是否:

  • Button1.OnClick = Button2.OnClick,但这给了我一个错误(实际参数不够)
  • @(Button1.OnClick)= @(Button2.OnClick),再次出错(实际参数不够)

如何正确测试?

3 个答案:

答案 0 :(得分:29)

方法引用可以分为两部分,指向对象的指针和指向方法本身的指针。在名为System的{​​{1}}单元中定义了一种方便的记录类型,允许我们进行分解。

有了这些知识,我们可以这样写:

TMethod

希望这会有所帮助。 :)

修改:只是以更好的格式布局我想在这里解决的问题(正如评论中所提到的那样)。

如果您有两个表单,则从同一个基类实例化:

function SameMethod(AMethod1, AMethod2: TNotifyEvent): boolean;
begin
  result := (TMethod(AMethod1).Code = TMethod(AMethod2).Code) 
            and (TMethod(AMethod1).Data = TMethod(AMethod2).Data);   
end;

并将这些表单中的相同方法分配给两个按钮:

Form1 := TMyForm.Create(nil);
Form2 := TMyForm.Create(nil);

并比较两个Button1.OnClick := Form1.ButtonClick; Button2.OnClick := Form2.ButtonClick; 属性,您会发现OnClick是相同的,但Code是不同的。那是因为它是相同的方法,但是在类的两个不同实例中......

现在,如果在同一个对象上有两个方法:

Data

然后他们的Form1 := TMyForm.Create(nil); Button1.OnClick := Form1.ButtonClick1; Button2.OnClick := Form1.ButtonClick2; 会相同,但他们的Data会有所不同。

答案 1 :(得分:17)

我用这个功能做到了:

function MethodPointersEqual(const MethodPointer1, MethodPointer2): Boolean;
var
  Method1: System.TMethod absolute MethodPointer1;
  Method2: System.TMethod absolute MethodPointer2;
begin
  Result := (Method1.Code=Method2.Code) and (Method1.Data=Method2.Data)
end;

它有效,但是如果有人知道一种较少 hacky 的方法,那么我很乐意听到它!

答案 2 :(得分:2)

我知道这是一个老问题......但这是我的2个......

这个答案与Nat的类似,但并不仅限于我们只有TNotifyEvents ...并回答David的问题,如何做到这一点,而不是黑客......

function CompareMethods(aMethod1, aMethod2: TMethod): boolean;
begin
  Result := (aMethod1.Code = aMethod2.Code) and
            (aMethod1.Data = aMethod2.Data);
end; 

我这样使用它

procedure TDefaultLoop.RemoveObserver(aObserver: TObject; aEvent: TNotifyEvent);
var
  a_Index: integer;
begin
  for a_Index := 0 to FNotifyList.Count - 1 do
    if Assigned(FNotifyList[a_Index]) and
     (TNotify(FNotifyList[a_Index]).Observer = aObserver) and
      CompareMethods(TMethod(TNotify(FNotifyList[a_Index]).Event), TMethod(aEvent))     then
begin
  FNotifyList.Delete(a_Index);
  FNotifyList[a_Index] := nil;
end;

快速而肮脏的演示

procedure TForm53.Button1Click(Sender: TObject);
var
  a_Event1, a_Event2: TMethod;
begin
  if Sender is TButton then
  begin
     a_Event1 := TMethod(Button1.OnClick);
     a_Event2 := TMethod(Button2.OnClick);
    if CompareMethods(TMethod(TButton(Sender).OnClick), a_Event1) then
       ShowMessage('Button1Click Same Method');
    if CompareMethods(TMethod(TButton(Sender).OnClick), a_Event2) then
       ShowMessage('Button2Click Same Method');
  end;
end;


procedure TForm53.Button2Click(Sender: TObject);
var
  a_Event1, a_Event2: TMethod;
begin
  if Sender is TButton then
  begin
     a_Event1 := TMethod(Button1.OnClick);
     a_Event2 := TMethod(Button2.OnClick);
    if CompareMethods(TMethod(TButton(Sender).OnClick), a_Event1) then
       ShowMessage('Button1Click Same Method');
    if CompareMethods(TMethod(TButton(Sender).OnClick), a_Event2) then
       ShowMessage('Button2Click Same Method');
  end;
end;