2016-09-05 19 views
2

ほとんどのフィールドでイベントOnchangeを使用するTsqlqueryがあります。私は実行時にハードコーディング(例えば、Table.fieldbyname( 'ABC')。Onchange:= Nil;)を使用して、それらをdinamically切り替えなければなりません。 ONCHANGE:; = TableABCChange) 私はポインタの配列を使用すると、以下のように使用してみました:プロシージャのアドレスを配列に保存してDelphiで使用する方法

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]:[email protected][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; 

にそれらを切り替えることがアイデアを持っていませんそれ?

答えて

9

これらのイベントハンドラはメソッドポインタであるため、単一のポインタでは表現できません。それらは実際には2つのポインタによって表される.1つはデータ(すなわちオブジェクトインスタンス)であり、もう1つはコードである。

また、配列の範囲外にアクセスしています。 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; 

注:その知識で、あなたのコードはそうのように記述する必要があります。手続き型でその演算子を使用しないことを目標にしてください。このような使用を避けると、コンパイラに型の安全性をチェックさせることができます。同時に、typed checked pointersを有効にします。

+1

はい、そうです。私はlazarusとFp(Free Pascal Option)を使用しています。これは配列の間違った低指数を使用して、マスターであった。これは実際のプログラムの一例ではありません。問題を簡単に表示する方法。何故、どうもありがとう。 :)) – Kazmirus