如何将包含函数指针的变量的值与函数地址进行比较?
我正在维护一些代码,它在Delphi 2007中失败了.声明是:
var
EditorFrameWindow: Function: HWnd Of Object = Nil;
Run Code Online (Sandbox Code Playgroud)
在表单激活中,我有:
procedure TEditForm.FormActivate(Sender: TObject);
begin
EditorFrameWindow := GetFrameWindow;
end;
Run Code Online (Sandbox Code Playgroud)
在表格停用我有:
procedure TEditForm.FormDeactivate(Sender: TObject);
begin
if EditorFrameWindow = GetFrameWindow then
EditorFrameWindow := nil;
end;
Run Code Online (Sandbox Code Playgroud)
所以正在发生的事情是表单被停用了两次,并且因为没有其他任何东西被激活而失败.调用FormDeactivate,它匹配,并且EditorFrameWindow全局设置为(nil,nil)(根据调试器).然后再次调用它,并调用存储在变量中的函数,但当然没有存储的函数,因此它跳过nil并创建一个异常.
我应该怎么做才能阻止这种情况发生?(框架已更改为选项卡式系统,因此操作可能已更改.)
mgh*_*hie 14
将
procedure TEditForm.FormDeactivate(Sender: TObject);
begin
if Assigned(EditorFrameWindow) and (EditorFrameWindow = GetFrameWindow) then
EditorFrameWindow := nil;
end;
Run Code Online (Sandbox Code Playgroud)
每次机会工作?
编辑:
您不比较函数地址,比较这些函数的结果.因此,即使上面的固定代码不再导致异常,它仍然可能无法完成您想要的操作.另一个返回相同结果的函数也会重置事件处理程序.
要真正检查变量是否设置为特定的事件处理程序,您需要比较TMethod记录中的两个元素.就像是:
procedure TEditForm.FormDeactivate(Sender: TObject);
begin
if (TMethod(EditorFrameWindow).Code = @TForm1.GetFrameWindow)
and (TMethod(EditorFrameWindow).Data = Self)
then
EditorFrameWindow := nil;
end;
Run Code Online (Sandbox Code Playgroud)
您可能有两种方法来比较方法指针.方法指针由两个指针组成,一个代码指针和一个对象指针.Delphi比较方法指针的本地方法只比较代码指针,它看起来像这样:
if @EditorWindowMethod = @TEditForm.GetFrameWindow then
EditorWindowMethod := nil;
Run Code Online (Sandbox Code Playgroud)
它检查在该代码指针是否EditorWindowMethod可变的的起始地址匹配GetFrameWindow在方法TEditForm.它不检查是否对象引用的EditorWindowMethod是一样的Self.如果你想使对象引用也是相同的,那么你需要将方法指针拆分为TMethod记录的组成部分,Mghie的答案就是这样.(而且你可能也想比较的对象引用,因为它听起来像您有多个编辑表单.它们都具有相同的GetFrameWindow代码指针,但它们有不同的对象引用.)
@代码中的原因是告诉编译器您要引用方法指针.没有它,编译器将尝试调用方法指针,这就是让你陷入困境的原因.第一次停用窗口时,您调用 EditorWindowMethod并将生成的窗口句柄与调用 的返回值进行比较GetFrameWindow.当然,他们匹配,所以你没有分配EditorWindowMethod.下次停用表单时,您尝试EditorWindowMethod再次调用,但它是一个空指针.
您应该考虑摆脱对激活和停用通知的依赖.相反,只需检查表单内部是否处于活动状态GetFrameWindow.
| 归档时间: |
|
| 查看次数: |
4512 次 |
| 最近记录: |