我正在尝试更改TNotifyEvent的值,就像我对带有指向其值的指针的整数所做的一样。但是,当我尝试对TNotifyEvent进行操作时,出现异常(访问冲突)。我怎样才能做到这一点 ?

我的目标是更改外部变量的值。这是一个代码来解释这里我得到的错误:

procedure TForm11.Button3Click(Sender: TObject);
var
  LInteger: integer;
  LPinteger: ^Integer;

  LPNotify: ^TNotifyEvent;
  LNotify: TNotifyEvent;
begin
  LInteger := 10;
  LPinteger := @LInteger;
  LPinteger^ := 20; //It's ok, it make both variables with the same value
  Caption := Format('Pointer: %d | Value: %d', [LPinteger^, LInteger]);

  LNotify := Button3Click;
  LPNotify := @LNotify;
  LPNotify^ := nil; //Here I get the error

  Caption := Format('Pointer: %d | Value: %d', [Integer(LPNotify), Integer(@LNotify)]);
end;


ks

最佳答案

@运算符对过程类型变量有不同的处理方式。 documentation说:


在某些情况下,程序变量应如何处理尚不清楚
被解释。考虑以下语句:

if F = MyFunction then ...;


在这种情况下,F的出现导致函数调用;的
编译器调用F指向的函数,然后调用该函数
MyFunction,然后比较结果。规则是,每当
过程变量出现在表达式中,它表示一个调用
引用的过程或功能。在F引用的情况下
一个过程(不返回值),或者F引用一个
需要参数的函数,前一条语句会导致
编译错误。将F的程序值与
MyFunction,使用:

if @F = @MyFunction then ...;


@F将F转换为一个无类型的指针变量,该变量包含一个
地址,然后@MyFunction返回MyFunction的地址。

获取过程变量的内存地址(而不是
地址存储在其中),请使用@@。例如,@@ F返回的地址
F。


这是您的情况。代替

LPNotify := @LNotify;


你需要

LPNotify := @@LNotify;


如果在启用“键入地址”选项的情况下进行编译,则编译器将拒绝LPNotify := @LNotify作为类型不匹配。我找不到Embarcadero继续输入的地址默认为禁用的声音说明。

函数的最后一行应该是

Caption := Format(
  'Pointer: %d | Value: %d',
  [Int64(@LNotify), Int64(TMethod(LPNotify^))]
);


我假设您对Int64强制转换使用32位编译器。

09-25 17:42
查看更多