Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#31

AW: Bitmap soll gelegentlich unsichtbar sein

  Alt 1. Feb 2014, 13:06
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
dp_178696.png

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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat