関数や手続きのアドレスを渡す

解決


QA  2009-04-16 00:15:02  No: 34009

以下の TPaintScreen で座標の描写は TPaintScreen 内部で処理し、関数は本体で定義したものを適当な引数で TPaintScreen に渡したいのです。目的はこの2つの処理の裏画面書き込み・表画面転送を同時に行うためです。TPaintScreen.Draw にどういうコードを書けばいいでしょう。

  TPaintScreen = class(TPaintBox)
  private
    procedure FDrawCoordinate(Target: TCanvas);//座標
  public
    Func: Pointer;
    OffBmp: TBitmap;
    procedure Draw;
    ・・・・・・
  end;

constructor TPaintScreen.Create(AOwner: TComponent; Func: Pointer);
begin
  OffBmp := TBitmap.Create;  //オフスクリーン
  inherited Create(AOwner);
end;

procedure TPaintScreen.FDrawFunction(Target: TCanvas);
begin
end;

procedure TPaintScreen.Draw;
begin
  FDrawCoordinate(OffBmp.Canvas);//座標
{  ここで以下のようにすると「演算子まだはセミコロンが必要」のコンパイルエラー発生
  Func(OffBmp); 
  この程度の簡潔なコードで TForm1.FDrawSinX を処理する方法はないものか}
  Canvas.Draw(0, 0, OffBmp);
end;

// +-----------------  Form1  ------------------+
procedure TForm1.FormCreate(Sender: TObject);
begin
  PaintScreen1 := TPaintScreen.Create(Form1);
  PaintScreen1.Func := Nil;
      ・・・・・・
end;

procedure TForm1.FDrawSinX(Target: TPaintScreen);
begin
  with Target.OffBmp.Canvas do
      ・・・・・・
  //ここでTarget.Canvas.Draw(0, 0, Target.OffBmp); で表画面に転送してもちらつく
end;

procedure TForm1.FPutScreen;
begin
  PaintScreen1.Func := TForm1.FDrawSinX;
  PaintScreen1.Draw;
end;


QA  2009-04-16 00:21:08  No: 34010

> Func(OffBmp);
これはミス。しかしここをFunc(Self);としてもだめだろうし・・・。


ヘルプで  2009-04-16 00:55:54  No: 34011

「メソッドポインタ」


ofZ  2009-04-16 02:18:38  No: 34012

type
  TPaintScreen=class;

  TFunc = procedure(Target: TPaintScreen) of object;
 
  TPaintScreen = class(TPaintBox)
  public
    Func: TFunc;
  end;

procedure TForm1.FPutScreen;
begin
  PaintScreen1.Func := FDrawSinX;
end;

こんな感じ?


KHE00221  2009-04-16 03:37:20  No: 34013

どうせならイベントにしたほうが・・・・

TDrawSinX = procedure (Sender: TBitmap) of object;

TPaintScreen = class(TPaintBox)
private
  FDrawSinX: TDrawSinX;
  OffBmp: TBitmap;
public
  procedure Draw;
  procedure DrawSinX(ABitmap: TBitmap);
published
  property OnDrawSinX: TDrawSinX read FDrawSinX write FDrawSinX;
end;

procedure TPaintScreen.Draw;
begin
    DrawSinX(OffBmp);
end;

procedure TPaintScreen.DrawSinX(ABitmap: TBitmap);
begin
    if Assigned(OnDrawSinX) = True then OnDrawSinX(ABitmap);
end;


QA  2009-04-16 06:30:52  No: 34014

レスありがとうございます。まずofZ さんの方法でやってみましたが、関数は描かれません。
  TPaintScreen 内部でFuncを処理する必要はないのでしょうか?
  KHE00221 さんの方はイベントの代入でコンパイルエラーが出ます。
procedure TForm1.FormCreate(Sender: TObject);
begin
  PaintScreen1 := TPaintScreen.Create(Form1);
  with PaintScreen1 do
  begin
    OnPaint := PaintScreen1Paint;//イベントを代入
    ・・・・・・・・
    OnDrawSinX := PaintScreen1DrawSinX; //ここでTBitmapとTObjectの互換エラー発生
  end;
end;

procedure TForm1.PaintScreen1DrawSinX(Sender: TObject);
var
  Ex,Ey: Extended;
begin
  with PaintScreen1 do
    OffBmp.Canvas.・・・・;

end;


KHE00221  2009-04-16 06:38:39  No: 34015

ちょい修正

TDrawSinX = procedure (Sender: TObject; ABitmap: TBitmap) of object;

TPaintScreen = class(TPaintBox)
private
  FDrawSinX: TDrawSinX;
  OffBmp: TBitmap;
public
  procedure Draw;
  procedure DrawSinX(ABitmap: TBitmap);
published
  property OnDrawSinX: TDrawSinX read FDrawSinX write FDrawSinX;
end;

procedure TPaintScreen.Draw;
begin
    DrawSinX(OffBmp);
end;

procedure TPaintScreen.DrawSinX(ABitmap: TBitmap);
begin
    if Assigned(OnDrawSinX) = True then OnDrawSinX(Self,ABitmap);
end;

に変更して

procedure TForm1.PaintScreen1DrawSinX(Sender: TObject; ABitmap: TBitmap);
var
  Ex,Ey: Extended;
begin
  with ABitmap do
    Canvas.・・・・;


KHE00221  2009-04-16 06:40:16  No: 34016

イベントにしてるからオブジェクトインスペクターから設定できるけど・・・
動的に作ってるのかな?


QA  2009-04-16 08:16:11  No: 34017

> KHE00221 さん
  ありがとうございました。無事動きましたです。

> 動的に作ってるのかな?
  そのとおりです。昔から自作の使い捨てコンポはほとんど動的に使用していました。人に使ってもらうようなものは作れないので TCustomXXX から継承したこともほとんどありません(笑)。というかコンポ作成の方法をほとんど忘れています。
  実は10年ぶりくらいにDelphiで遊びだしたのですが(今だにDelphi5です)、10年ほど前に自分が作ったコードすら、コメントを書いているにもなかなかわからないような状態です。
  このようなサイトはほんとうにありがたいですね。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加