如何将程序地址保存在数组中,然后在Delphi中使用

如何将程序地址保存在数组中,然后在Delphi中使用,delphi,save,procedure,restore,memory-address,Delphi,Save,Procedure,Restore,Memory Address,我有一个Tsqlquery,大多数字段都使用EventOnChange。我需要在运行时不使用硬编码(例如Table.fieldbyname('ABC')。Onchange:=Nil;)直接关闭它们,然后我还需要打开它们(例如Table.fieldbyname('ABC')。Onchange:=TableABCChange;) 我确实尝试过使用指针数组,并像下面那样使用它: var P:array [1..100] of Pointer; begin for i:=0 to Table.field

我有一个Tsqlquery,大多数字段都使用EventOnChange。我需要在运行时不使用硬编码(例如Table.fieldbyname('ABC')。Onchange:=Nil;)直接关闭它们,然后我还需要打开它们(例如Table.fieldbyname('ABC')。Onchange:=TableABCChange;) 我确实尝试过使用指针数组,并像下面那样使用它:

var P:array [1..100] of Pointer;
begin
for i:=0 to Table.fields.count-1 do
 begin
    {save and switch them off} 
    P[i]:=@Table.fields[i].Onchange; 
    @Table.fields[i].Onchange:=Nil;
 end;
但我不知道如何打开它们

for i:=0 to Table.fields.count-1 do
 begin
    {restore and switch them on} 
    Table.fields[i].Onchange:=P[i]; <---- ERROR
 end;
i:=0到Table.fields.count-1 do的

开始
{还原并打开它们}

Table.fields[i].Onchange:=P[i] 这些事件处理程序是方法指针,因此不能由单个指针表示。它们实际上由两个指针表示:一个指向数据(即对象实例),另一个指向代码

您也在访问数组边界之外的对象。您定义了一个低索引
1
的数组,并立即访问了索引
0
。您还硬编码了
100
的上限,这有点冒险。这里需要的是动态数组

此外,通过将
@
与禁用类型化检查指针的默认编译器选项一起使用,可以抑制编译器对代码进行类型检查的某些功能

OnChange
事件实际上是一个
TFieldNotifyEvent
方法指针。有了这些知识,您的代码应该这样编写:

var 
  SavedChangeEvents: array of TFieldNotifyEvent;
....
// save and set event handler to nil
SetLength(SavedChangeEvents, Table.Fields.Count);
for i := 0 to Table.Fields.Count-1 do
begin
  SavedChangeEvents[i] := Table.Fields[i].OnChange; 
  Table.Fields[i].OnChange := nil;
end;
....
// restore
for i := 0 to Table.Fields.Count-1 do
begin
  Table.Fields[i].OnChange := SavedChangeEvents[i];
end;

请注意,我在任何时候都不能使用
@
运算符。你的目标是永远不要在过程类型中使用该操作符。避免这种使用可以让编译器检查类型安全性。同时,启用。

是,您是对的。使用@depend of compiler选项,我使用的是lazarus和Fp(Free-pascal选项)。这是一个使用错误的低索引数组的mastake。这只是一个例子,不是真实程序的一部分。显示问题的简单方法。有什么原因吗非常感谢。:)