16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"指定クラスのpublishedなメソッド名を列挙"
この発言に対し以下のコメントが寄せられています
#00948 Satobe さん RE:指定クラスのpublishedなメソッド名を列
◆解説
指定のクラスの published なメソッド名を列挙します。
◆動作確認
Delphi3.1, Delphi4 (Delphi5 は未確認です)
◆実際のコード
Form1に Button1, Memo1 を置いて、以下のコードをお試し下さい
----- ここから -----
implementation
{$R *.DFM}
//テスト用のクラス定義-- ここから --------------------------
type
TTest1 = class(TObject)
public
No: Integer;
published
procedure TTest1Method(s: String);
end;
TTest2 = class(TTest1)
published
procedure TTest2Method(s: String);
end;
TTest3 = class(TTest2)
published
procedure TTest3Method(s: String);
end;
procedure TTest1.TTest1Method(s: String);
begin
ShowMessage(Format('[No=%d]%s', [No, s]));
end;
procedure TTest2.TTest2Method(s: String);
begin
ShowMessage(Format('[No=%d]%s', [No, s]));
end;
procedure TTest3.TTest3Method(s: String);
begin
ShowMessage(Format('[No=%d]%s', [No, s]));
end;
//テスト用のクラス定義-- ここまで --------------------------
//==========================================================
//クラス内の publishedなメソッド名を列挙する
//
//「クラス名.メソッド名」という形式にしているが、
//「メソッド名」のみで良いなら *行の ClassNameの処理は不要
//==========================================================
procedure EnumMethodNames(const AClass: TClass; S: TStrings);
type
PPointer = ^Pointer;
var
vmt: Pointer;
pMethodTable: PChar;
MethodCount, MethodNameLen: Integer;
ClassName, MethodName: String[255]; //*
begin
S.Clear;
vmt := AClass;
while True do begin
ClassName := TClass(vmt).ClassName; //*
pMethodTable := PPointer(PChar(vmt) + vmtMethodTable)^;
if pMethodTable <> nil then begin
MethodCount := PWORD(pMethodTable)^;
inc(pMethodTable, 2);
while MethodCount > 0 do begin
MethodNameLen := PBYTE(pMethodTable + 6)^;
Move((pMethodTable + 6)^, MethodName, MethodNameLen+1);
S.Add(ClassName + '.' + MethodName); //*
//Next Method
inc(pMethodTable, PWORD(pMethodTable)^);
Dec(MethodCount);
end;
end;
//Parentへ
vmt := PPointer(PChar(vmt) + vmtParent)^;
if vmt = nil then Break;
vmt := PPointer(vmt)^;
end;
end;
//動作テスト
procedure TForm1.Button1Click(Sender: TObject);
var
j, p: Integer;
s: String[255];
Method: procedure(s: String) of object;
T3: TTest3;
begin
//TTest3クラスのpublishedなメソッド名をMemo1に列挙
EnumMethodNames(TTest3, Memo1.Lines);
//試しに呼び出してみる
T3 := TTest3.Create;
try
TMethod(Method).Data := T3;
for j:=0 to Memo1.Lines.Count-1 do begin
s := Memo1.Lines[j];
p := Pos('.', s);
if p > 0 then Delete(s, 1, p);
TMethod(Method).Code := TTest3.MethodAddress(s);
if Assigned(TMethod(Method).Code) then begin
T3.No := j;
Method(Memo1.Lines[j]);
end;
end;
finally
T3.Free;
end;
end;
----- ここまで -----
処理の内容、および VMT(仮想メソッドテーブル)等については、
Delphiヘルプや TObject.MethodAddress等のソース(アセンブラ
ですが(^^;)コードを参照してください。
けっこう怪しいルーチンです。(^_^;;
私自身も、これが正しいコードなのかどうか、よくわかってませ
ん。#やってみたら、とりあえず動いたってだけ...
99/09/28(火) 23:12 Satobe(JCG00336)
Original document by Satobe 氏 ID:(JCG00336)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|