Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Bitmap soll gelegentlich unsichtbar sein (https://www.delphipraxis.net/178696-bitmap-soll-gelegentlich-unsichtbar-sein.html)

Sir Rufo 1. Feb 2014 12:06

AW: Bitmap soll gelegentlich unsichtbar sein
 
Liste der Anhänge anzeigen (Anzahl: 1)
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
Anhang 40647

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
Delphi-Quellcode:
TComponent
).

Am einfachsten erreiche ich das durch das Kopieren der zugewiesenen Instanz (und
Delphi-Quellcode:
TBitmap
ist num mal auch ein
Delphi-Quellcode:
TPersistent
und bringt glücklicherweise ein funktionierendes
Delphi-Quellcode:
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.

Popov 2. Feb 2014 16:55

AW: Bitmap soll gelegentlich unsichtbar sein
 
Ich reite nicht auf Assign rum, auch habe ich nichts dagegen, nur gingen die Antworten von Anfang an in eine andere Richtung als die Frage ursprünglich gemeint war. Ich sehe den Fehler bei mir, ich denke ich habe die Frage missverständlich gestellt. Ich gehe jetzt aber auch nicht erneut drauf ein.

Bei dem Programm geht es um visuelle Darstellung von Informationen. Sowas gibt es schon, deshalb gibt es Erfahrungswerte. Hauptsächlich werden Polygone, Linien usw. gezeichnet, aber auch Bitmaps. Eigentlich sind die Bitmaps nur ein Extra, nicht das Eigentliche, aber falls sie eingefügt werden, wird es bei paar hundert Bitmaps eng und das Refresh kann dann Sekunden dauern. Somit ist alles was unnötig Zeit kostet nicht optimal, z. B. Assign.

Wenn ich also nun (im Fall der Fälle) mit paar hundert Bitmaps zu tun habe, dann stellt sich mir die Frage ob ich für jedes Refresh auch paar hundert Mal Bitmaps mit Assign hin und her kopieren möchte. Oder gibt es da eine bessere Möglichkeit?

Nun habe ich gerade 1 Million Assigns über eine 800*640 Pixel große Bitmap in einer Schleife ausgeführt. Entweder hat der Compiler erkannt, dass das Unsinn war und hat alles optimiert, oder Assign kostet kaum Zeit. Zumindest hat mein Test unter 100 Millisekunden gedauert. Erscheint mir wenig.

Vielleicht hatte ich einfach nur eine falsche Vorstellung von Assign und das Kopieren kostet wirklich kaum Zeit. In dem Fall ist es eine Option.

Was mein letztes Beispiel angeht, das sehe ich nicht als Fehler. Ich hab da bewusst auf Getter und Setter verzichtet, weil es in dem Beispiel nur um den Switch ging. Es war nur ein Test. Ein Getter und Setter war somit nicht nötig.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 Uhr.
Seite 4 von 4   « Erste     234   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz