Ich weiß ja nicht ob das hier jetzt eine Posse wird ...
... mit dieser (schon mal von mir veröffentlichen Klasse)
Delphi-Quellcode:
unit DrawLayer;
interface
uses
Windows,
Graphics;
type
TEnableBitmap =
class( TBitmap )
private
FEnabled : Boolean;
protected
procedure Draw( ACanvas : TCanvas;
const Rect : TRect );
override;
procedure DrawTransparent( ACanvas : TCanvas;
const Rect : TRect; Opacity : Byte );
override;
public
procedure AfterConstruction;
override;
property Enabled : Boolean
read FEnabled
write FEnabled;
end;
TDrawLayer =
class
private
FBitmap : TBitmap;
procedure SetBitmap(
const Value : TBitmap );
function GetBitmapEnabled : Boolean;
procedure SetBitmapEnabled(
const Value : Boolean );
public
procedure AfterConstruction;
override;
property Bitmap : TBitmap
read FBitmap
write SetBitmap;
property BitmapEnabled : Boolean
read GetBitmapEnabled
write SetBitmapEnabled;
end;
implementation
{ TEnableBitmap }
procedure TEnableBitmap.AfterConstruction;
begin
inherited;
FEnabled := True;
end;
procedure TEnableBitmap.Draw( ACanvas : TCanvas;
const Rect : TRect );
begin
if FEnabled
then
inherited;
end;
procedure TEnableBitmap.DrawTransparent( ACanvas : TCanvas;
const Rect : TRect; Opacity : Byte );
begin
if FEnabled
then
inherited;
end;
{ TDrawLayer }
procedure TDrawLayer.AfterConstruction;
begin
inherited;
FBitmap := TEnableBitmap.Create;
end;
function TDrawLayer.GetBitmapEnabled : Boolean;
begin
Result := ( FBitmap
as TEnableBitmap ).Enabled;
end;
procedure TDrawLayer.SetBitmap(
const Value : TBitmap );
begin
FBitmap.Assign( Value );
end;
procedure TDrawLayer.SetBitmapEnabled(
const Value : Boolean );
begin
( FBitmap
as TEnableBitmap ).Enabled := Value;
end;
end.
und der von
dir angegebenen Testroutine
Delphi-Quellcode:
unit FormMain;
interface
uses
DrawLayer,
Windows, Messages,
SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type
TMainForm =
class( TForm )
Panel1 : TPanel;
Button1 : TButton;
procedure Button1Click( Sender : TObject );
end;
var
MainForm : TMainForm;
implementation
{$R *.dfm}
{ TMainForm }
procedure TMainForm.Button1Click( Sender : TObject );
var
Bmp : TBitmap;
begin
with TDrawLayer.Create
do
try
Bitmap.Canvas.Brush.Color := clRed;
Bitmap.Width := 100;
Bitmap.Height := 50;
Self.Canvas.Draw( 0, 0, Bitmap );
// Bis jetzt alles ok
// Jetzt das Problem
BitmapEnabled := False;
// Man denkt sich nichts böses dabei, ist ja auch erlaubt
Bmp := Bitmap;
Bmp.Canvas.Ellipse( Bmp.Canvas.ClipRect );
Self.Canvas.Draw( 100, 100, Bmp );
// Nun stimmt nichts nicht überein. Wo ist die Ellipse?
BitmapEnabled := True;
Self.Canvas.Draw( 200, 200, Bitmap );
finally
Free
end;
end;
end.
erhalte ich folgendes Ergebnis
Es macht genau das was du gefordert und beschrieben hast.
Warum du auf dem Assign rumreitest, kann ich nicht nachvollziehen. Wenn eine
Eigenschaft mit Schreibzugriff eine Klasse ist, dann muss gewährleistet sein, dass dort kein Speicherleck auftritt.
Und es gilt auch die allgemeine Regel, wer die Instanz erzeugt ist auch für das Aufräumen zuständig. Andernfalls muss diese Aufgabe klar delegiert werden (z.B. Owner bei
TComponent
).
Am einfachsten erreiche ich das durch das Kopieren der zugewiesenen Instanz (und
TBitmap
ist num mal auch ein
TPersistent
und bringt glücklicherweise ein funktionierendes
Assign
mit).
Und wie dir auffällt wird in deiner gesamten Testprozedur das Assign nicht einmal aufgerufen (weil ja
direkt mit der Bitmap-instanz gearbeitet wird).
Also könnte die Eigenschaft Bitmap auch ReadOnly sein. Dann entfällt der Setter und damit das Assign (wenn es denn die/deine Augen stören sollte).
Bitte erläutere uns doch jetzt, was noch fehlt, denn
dein Test wird zu 100% korrekt abgearbeitet.