要約:
type
MyObject = object
end;
MyRecord = record
end;
MyClass = class
end;
procedure ProcA(aMyObject: MyObject);
procedure ProcB(var aMyObject: MyObject);
procedure ProcC(aMyRecord: MyRecord);
procedure ProcD(var aMyRecord: MyRecord);
procedure ProcE(aMyClass: MyOClass);
procedure ProcF(var aMyClass: MyClass);
MyObject
とMyRecord
は値型ですが、MyClass
は参照型です。- 値型の変数を代入すると、変数がコピーされます。参照型の変数を代入すると、参照がコピーされます。
ProcA
およびの引数はProcC
、元の引数のコピーです。ProcB
との引数ProcD
は元のものです。- の引数
ProcE
は、元の参照のコピーです。 - の引数
ProcF
は元の参照です。 - ユニット agg_2D.pas で宣言されている Agg2D オブジェクトをラップして描画する方法については、以下の David の回答を参照してください。
==========================================
AggPasの使い方を学んでいますこれは純粋なパスカル ベクトル グラフィックス描画 API です。具体的には、TAgg2D クラスを含むユニット Agg2D.pas の代わりに、Agg2D オブジェクトを含むユニット agg_2D.pas が使用されます。ユニット Agg2D.pas よりもユニット agg_2D.pas を選択する理由は、クロスプラットフォーム機能のためです。
しかし、var プレフィックスを持つ Agg2D オブジェクト型の引数を正しく渡すことができません。次のコードに示すように、TForm1 によって作成された Agg2D オブジェクトを、実際に形状の描画を担当する別のクラスに渡したいと考えています。しかし、うまくいきません。考えられる理由についてコメントしていただけますか?オブジェクト型に関する重要な概念を見逃していたようです。どんな提案でも大歓迎です!VCL アプリケーションを新規作成し、FormCreate ハンドラーをアタッチし、描画コードを 1 行ずつコメント アウトして効果を確認できます。
unit Unit1;
interface
uses
agg_2D,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TRenderEngine_BMP = class;
TRenderEngine_Agg = class;
TForm1 = class;
TRenderEngine_BMP = class
private
fBMP: TBitmap;
public
constructor Create(var aBMP: TBitmap);
procedure DrawEllipse;
end;
TRenderEngine_Agg = class
private
fVG: Agg2D;
public
constructor Create(var aVG: Agg2D);
procedure DrawEllipse;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
fBMP: TBitmap;
fVG: Agg2D;
fEngine_BMP: TRenderEngine_BMP;
fEngine_Agg: TRenderEngine_Agg;
procedure AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
procedure OnSceneResize(Sender: TObject);
procedure OnScenePaint(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Math;
{ TRenderEngine_BMP }
constructor TRenderEngine_BMP.Create(var aBMP: TBitmap);
begin
Self.fBMP := aBMP;
end;
procedure TRenderEngine_BMP.DrawEllipse;
begin
Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
end;
{ TRenderEngine_Agg }
constructor TRenderEngine_Agg.Create(var aVG: Agg2D);
begin
Self.fVG := aVG;
end;
procedure TRenderEngine_Agg.DrawEllipse;
begin
Self.fVG.ellipse(50, 50, 30, 30);
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;
fBMP := TBitmap.Create;
fBMP.PixelFormat := pf32bit;
fBMP.Canvas.Brush.Style := bsSolid;
fBMP.Canvas.Brush.Color := clBlue;
fBMP.Width := ClientWidth;
fBMP.Height := ClientHeight;
fVG.Construct;
Self.AttachBMP(fVG, fBMP);
fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
fEngine_Agg := TRenderEngine_Agg.Create(fVG);
end;
procedure TForm1.AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
var
tmpBuffer: pointer;
tmpStride: integer;
begin
tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);
if tmpStride < 0 then
tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
else
tmpBuffer := aBMP.ScanLine[0];
aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
end;
procedure TForm1.OnScenePaint(Sender: TObject);
begin
Self.fBMP.Canvas.FillRect(Self.ClientRect);
// Self.fBMP.Canvas.ellipse(20, 20, 80, 80); // Work
// Self.fVG.ellipse(50, 50, 30, 30); // Work
// Self.fEngine_BMP.DrawEllipse; // Work
Self.fEngine_Agg.DrawEllipse; // Do not work
Self.Canvas.Draw(0, 0, fBMP);
end;
procedure TForm1.OnSceneResize(Sender: TObject);
begin
fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);
Self.AttachBMP(fVG, fBMP);
end;
end.
プロシージャ引数の var プレフィックスをすべて削除すると、2 番目の円描画コードも機能しなくなりますが、これはよくわかりません。便宜上、ユニットは次のように表示されます。
unit Unit1;
interface
uses
agg_2D,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TRenderEngine_BMP = class;
TRenderEngine_Agg = class;
TForm1 = class;
TRenderEngine_BMP = class
private
fBMP: TBitmap;
public
constructor Create(aBMP: TBitmap);
procedure DrawEllipse;
end;
TRenderEngine_Agg = class
private
fVG: Agg2D;
public
constructor Create(aVG: Agg2D);
procedure DrawEllipse;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
fBMP: TBitmap;
fVG: Agg2D;
fEngine_BMP: TRenderEngine_BMP;
fEngine_Agg: TRenderEngine_Agg;
procedure AttachBMP(aVG: Agg2D; aBMP: TBitmap);
procedure OnSceneResize(Sender: TObject);
procedure OnScenePaint(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Math;
{ TRenderEngine_BMP }
constructor TRenderEngine_BMP.Create(aBMP: TBitmap);
begin
Self.fBMP := aBMP;
end;
procedure TRenderEngine_BMP.DrawEllipse;
begin
Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
end;
{ TRenderEngine_Agg }
constructor TRenderEngine_Agg.Create(aVG: Agg2D);
begin
Self.fVG := aVG;
end;
procedure TRenderEngine_Agg.DrawEllipse;
begin
Self.fVG.ellipse(50, 50, 30, 30);
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;
fBMP := TBitmap.Create;
fBMP.PixelFormat := pf32bit;
fBMP.Canvas.Brush.Style := bsSolid;
fBMP.Canvas.Brush.Color := clBlue;
fBMP.Width := ClientWidth;
fBMP.Height := ClientHeight;
fVG.Construct;
Self.AttachBMP(fVG, fBMP);
fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
fEngine_Agg := TRenderEngine_Agg.Create(fVG);
end;
procedure TForm1.AttachBMP(aVG: Agg2D; aBMP: TBitmap);
var
tmpBuffer: pointer;
tmpStride: integer;
begin
tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);
if tmpStride < 0 then
tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
else
tmpBuffer := aBMP.ScanLine[0];
aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
end;
procedure TForm1.OnScenePaint(Sender: TObject);
begin
Self.fBMP.Canvas.FillRect(Self.ClientRect);
// Self.fBMP.Canvas.ellipse(20, 20, 80, 80); // Work
// Self.fVG.ellipse(50, 50, 30, 30); // Do not Work
// Self.fEngine_BMP.DrawEllipse; // Work
Self.fEngine_Agg.DrawEllipse; // Do not work
Self.Canvas.Draw(0, 0, fBMP);
end;
procedure TForm1.OnSceneResize(Sender: TObject);
begin
fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);
Self.AttachBMP(fVG, fBMP);
end;
end.