代码之家  ›  专栏  ›  技术社区  ›  mj2008

比较Delphi中的函数值指针

  •  5
  • mj2008  · 技术社区  · 15 年前

    我怎么比较 价值 包含指向函数地址的函数的指针的变量?

    我正在维护一些代码,它在Delphi2007中失败了。声明是:

    var
      EditorFrameWindow: Function: HWnd Of Object = Nil;
    

    在表单激活中,我有:

    procedure TEditForm.FormActivate(Sender: TObject);
    begin
      EditorFrameWindow := GetFrameWindow;
    end;
    

    在表格中我有:

    procedure TEditForm.FormDeactivate(Sender: TObject);
    begin
      if EditorFrameWindow = GetFrameWindow then
        EditorFrameWindow := nil;
    end;
    

    所以现在所发生的是表单被停用了两次,并且由于没有其他东西被激活而失败。调用formDeactivate,它匹配,并且将editorframewindow全局设置为(nil,nil)(根据调试器)。然后再次调用它,并调用存储在变量中的函数,但当然没有存储函数,因此它跳过nil并创建一个异常。

    我该怎么做才能阻止这种情况的发生?(框架已更改为选项卡式系统,因此操作可能已更改。)

    2 回复  |  直到 15 年前
        1
  •  14
  •   mghie    15 年前

    procedure TEditForm.FormDeactivate(Sender: TObject);
    begin
      if Assigned(EditorFrameWindow) and (EditorFrameWindow = GetFrameWindow) then
        EditorFrameWindow := nil;
    end;
    

    每次工作机会?

    编辑:

    不比较函数地址,而是比较这些函数的结果。因此,尽管上面的固定代码不能再导致异常,但它可能仍然不能满足您的需要。另一个返回相同结果的函数也将重置事件处理程序。

    要真正检查变量是否设置为特定的事件处理程序,需要比较 TMethod 记录。类似:

    procedure TEditForm.FormDeactivate(Sender: TObject);
    begin
      if (TMethod(EditorFrameWindow).Code = @TForm1.GetFrameWindow)
        and (TMethod(EditorFrameWindow).Data = Self)
      then
        EditorFrameWindow := nil;
    end;
    
        2
  •  9
  •   Community CDub    8 年前

    有两种方法可以比较方法指针。方法指针由两个指针组成,一个代码指针和一个对象指针。Delphi的比较方法指针的本地方法只比较代码指针,如下所示:

    if @EditorWindowMethod = @TEditForm.GetFrameWindow then
      EditorWindowMethod := nil;
    

    它检查代码指针是否在 EditorWindowMethod 变量与 GetFrameWindow 方法在 TEditForm . 它不检查 对象引用 在里面 编辑器窗口方法 是一样的 Self . 如果要使对象引用也相同,则需要使用 TMethod 记录,哪个 Mghie's answer 演示。(你可能 希望比较对象引用,因为听起来您有多个编辑表单。他们都有相同的 获取框架窗口 代码指针,但它们具有不同的对象引用。)

    原因是 @ 在代码中是告诉编译器您想要引用方法指针。如果没有它,编译器将尝试 呼叫 方法指针,这就是让你陷入麻烦的原因。第一次停用窗口时,您 打电话 编辑器窗口方法 并将生成的窗口句柄与 打电话 获取框架窗口 . 当然,它们是匹配的,所以你没有指定 编辑器窗口方法 . 下一次停用表单时,您试图呼叫 编辑器窗口方法 但它是一个空指针。

    您应该考虑摆脱对激活和停用通知的依赖。相反,只需检查表单内部是否处于活动状态 获取框架窗口 .