SOU*_*ser 2 delphi arguments var object aggpas
综述:
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);
Run Code Online (Sandbox Code Playgroud)
MyObject并且MyRecord是值类型,而是MyClass引用类型.ProcA和ProcC是原有的副本. ProcB和ProcD是原始的. ProcE是原始参考的副本. ProcF是原始参考. ===========================================
我正在学习使用AggPas这是一个纯粹的pascal矢量图形绘制API.具体来说,使用包含Agg2D对象的单元agg_2D.pas而不是包含TAgg2D类的单元Agg2D.pas.在Agg2D.pas单元上选择单元agg_2D.pas的原因是为了跨平台能力.
但是,我无法使用var前缀正确传递Agg2D对象类型的参数.如下面的代码所示,我想将TForm1创建的Agg2D对象传递给另一个实际负责绘制形状的类.但是,它不起作用.你能帮忙评论可能的原因吗?看来我一定错过了有关对象类型的重要概念.任何建议表示赞赏!您可以新建一个VCL应用程序,附加FormCreate处理程序,并逐行注释掉绘图代码以查看效果.
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.
Run Code Online (Sandbox Code Playgroud)
如果我删除所有出现的过程参数的var前缀,第二个圆绘图代码也会停止工作,我不太明白.为方便起见,本机如下所示:
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.
Run Code Online (Sandbox Code Playgroud)
我很难理解你在这里做了什么.我觉得你的基本问题是,Agg2D是object,所以是值类型.你需要复制它,以便有两个副本而不是一个副本.作者选择使用object而不是类,但这样做需要您对值语义非常警惕,而不是引用TObject后代的语义.
快速黑客得到这个工作是改变fVG: Agg2D;以fVG: ^Agg2D;和TRenderEngine_Agg.Create变化Self.fVG := aVG来Self.fVG := @aVG.通过该更改,绘制椭圆.
现在,我认为你需要重新考虑你的设计.如果你想在一个渲染类中包装一个Agg2D对象,那就没问题,但是你不能获取Agg2D对象的副本.
以下是我编写代码来处理问题的方法:
TRenderEngine_Agg = class
private
fVG: Agg2D;
public
constructor Create;
procedure AttachBMP(aBMP: TBitmap);
procedure DrawEllipse;
end;
constructor TRenderEngine_Agg.Create;
begin
fVG.Construct;
end;
procedure TRenderEngine_Agg.AttachBMP(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];
fVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
end;
procedure TRenderEngine_Agg.DrawEllipse;
begin
Self.fVG.fillColor(30, 50, 20);
Self.fVG.blendMode(BlendContrast );
Self.fVG.ellipse(50, 50, 30, 30);
end;
procedure TForm20.OnSceneResize(Sender: TObject);
begin
fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);
fEngine_Agg.AttachBMP(fBMP);
end;
Run Code Online (Sandbox Code Playgroud)
我们的想法是将所有内容与Agg2D对象放在一起TRenderEngine_Agg.如果你这样做,那么我认为你会变得金色!
| 归档时间: |
|
| 查看次数: |
1073 次 |
| 最近记录: |