Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Transparente Komponente - Flackern (https://www.delphipraxis.net/80491-transparente-komponente-flackern.html)

crypti 9. Nov 2006 17:20


Transparente Komponente - Flackern
 
hi!

Ich hab mal wieder eine Frage und ich hoffe das mir jemand weiterhelfen kann.

Ich habe eine Komponente welche von CustomControl abgeleitet ist, da ich ein Handle brauche. Da ich diese auch auf Bilder o.ä. legen möchte, muss diese so wie standardmäßig ein GraphicControl transparent sein.
Das lässt sich ja über WS_EX_TRANSPARENT realisieren, kein Problem.

Nur wenn ich jetzt in der Paint Funktion Bilder o.ä. zeichnen möchte, dann kommt es natürlich zum Flackern. Eigentlich macht man da das DoubleBuffered an und gut ist. Jedoch funktioniert das bei einem Transparenten Fenster ja nicht.
Wenn ich DoubleBuffered:=true mache, dann ist der Bereich meiner Komponente Schwarz und nicht mehr transparent.

Nun dachte ich, man könnte die Zeichnungsaktivitäten erst in einem Bild (Bitmap) machen und dann am Ende der Paint Funktion einfach mit dem Original Canvas zusammenmergen, jedoch funktioniert das nicht.

Hat vielleicht einer ne Idee was man da noch machen kann?

Ich danke euch schon mal!!!!

chaosben 10. Nov 2006 05:16

Re: Transparente Komponente - Flackern
 
Hi!
Zitat:

Zitat von crypti
jedoch funktioniert das nicht.

Das ist zu ungenau. Was funktioniert nicht? Welche Fehlermeldungen?

Zitat:

Zitat von crypti
Nun dachte ich, man könnte die Zeichnungsaktivitäten erst in einem Bild (Bitmap) machen und dann am Ende der Paint Funktion einfach mit dem Original Canvas zusammenmergen,

Das ist genau das, was du tun musst, um das Flackern zu beseitigen. Hier ein Beispiel:
Delphi-Quellcode:
var
  Buffer : TBitmap;
begin
  Buffer:=TBitmap.Create;
  Buffer.Width:=Self.Width //...usw
 
  //Transparenz entsteht, wenn man das anzeigt, was hinter dem Control ist
  //also fordern wir unseren Parent auf, genau das zu zeichnen
  DrawParentBackground(Buffer.Canvas.Handle);

  //Jetzt das malen, was wir wollen
 
  //Danach den Buffer ins Control malen
  BitBlt(Self.Canvas.Handle,
         0,0,
         Self.Width, Self.Height,
         Buffer.Canvas.Handle,
         0,0,
         SRCCOPY);
 
  Buffer.Free;
end;

//leider weiß ich nicht mehr, von wem die Prozedur war :(
procedure TMyControl.DrawParentBackground(AToDC : HDC);
var
  SaveIndex: Integer;
  Position: TPoint;
begin
  SaveIndex := SaveDC(AToDC);
  GetViewportOrgEx(AToDC, Position);
  SetViewportOrgEx(AToDC, Position.X - Left, Position.Y - Top, nil);
  IntersectClipRect(AToDC, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
  Parent.Perform(WM_ERASEBKGND, AToDC, 0);
  Parent.Perform(WM_PAINT, AToDC, 0);
  RestoreDC(AToDC, SaveIndex);
end;

martin-sun 10. Nov 2006 08:13

Re: Transparente Komponente - Flackern
 
Hallo,

das Flackern liegt IMHO daran, dass Windows trotz transparentem Style die WM_ERASEBKGND message sendet und das Control demnach den Hintergund löscht, bevor es sich selbst neu (transparent) zeichnet.
Bin gerade nicht zu Hause zum probieren, aber entweder kann man das Zeichnen des Hintergrunds mit einem zusätzlichen Style Flag verhindern, oder aber durch das überschreiben der Message.

Gruß
Martin

crypti 10. Nov 2006 09:07

Re: Transparente Komponente - Flackern
 
Hi!

Zitat:

Zitat von chaosben
Zitat:

Zitat von crypti
Nun dachte ich, man könnte die Zeichnungsaktivitäten erst in einem Bild (Bitmap) machen und dann am Ende der Paint Funktion einfach mit dem Original Canvas zusammenmergen,

Das ist genau das, was du tun musst, um das Flackern zu beseitigen. Hier ein Beispiel:
Delphi-Quellcode:
var
  Buffer : TBitmap;
begin
  Buffer:=TBitmap.Create;
  Buffer.Width:=Self.Width //...usw
 
  //Transparenz entsteht, wenn man das anzeigt, was hinter dem Control ist
  //also fordern wir unseren Parent auf, genau das zu zeichnen
  DrawParentBackground(Buffer.Canvas.Handle);

  //Jetzt das malen, was wir wollen
 
  //Danach den Buffer ins Control malen
  BitBlt(Self.Canvas.Handle,
         0,0,
         Self.Width, Self.Height,
         Buffer.Canvas.Handle,
         0,0,
         SRCCOPY);
 
  Buffer.Free;
end;

//leider weiß ich nicht mehr, von wem die Prozedur war :(
procedure TMyControl.DrawParentBackground(AToDC : HDC);
var
  SaveIndex: Integer;
  Position: TPoint;
begin
  SaveIndex := SaveDC(AToDC);
  GetViewportOrgEx(AToDC, Position);
  SetViewportOrgEx(AToDC, Position.X - Left, Position.Y - Top, nil);
  IntersectClipRect(AToDC, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
  Parent.Perform(WM_ERASEBKGND, AToDC, 0);
  Parent.Perform(WM_PAINT, AToDC, 0);
  RestoreDC(AToDC, SaveIndex);
end;

Die Lösung kenne ich schon, jedoch bringt einen diese nicht ans Ziel. Wenn ich in der Paint Funktion über die DrawParentBackground arbeite, dann wird bei mir nicht der Hintergrund des Controls in das temporäre Bitmap gezeichnet, sondern es ist schlichtweg einfach nur weiß. Man kann das Bitmap ja nach der Erzeugung mit DrawParentBackground einfach mal abspeichern, aber es ist wirklich weiß.
Ich habe auch gesehen das diese Funktionen beim FlatPanel mit zum Einsatz kommen. Jedoch habe ich dort genau den gleichen Effekt. Es wird nicht transparent, sondern ist einfach nur weiß.

Aus diesem Grund habe ich oben auch geschrieben das es nicht funktioniert.


Was mit mitlerweile aufgefallen ist.

Wenn ich das Control mit WS_EX_TRANSPARENT zeichne, dann wird bei einem Zeichnen die Zeichenfläche nicht aktualisiert. Dies bedeutet, wenn ich in das Control ein Label o.ä. reinpacke, dann überdecken sich die Texte. Man muss hier im Paint ein zusätzliches Repaint auf das Parent des Controls ausführen. Wenn ich dieses Paint weglasse, dann flackert auch nichts mehr. Aber wenn ich ein Transparentes PNG o.ä. dort mit reinpacken will, dann brauche ich ja exakt den Hintergrund um immer die gleiche Darstellung zu erhalten. Sonst wird ein Grau nach der dritten Aktualisierung zu einem Grau.

Wenn man die Transparenz nur "simulieren" will und zwar über ein Bitmap das aus dem Hintergrund immer wieder neu entsteht, dann brauchen wir das WS_EX_TRANSPARENT ja überhaupt nicht. Wahrscheinlich ist diese Funktionsweise sogar die schnellste.

Ich danke euch das ihr euch meiner Fragen annehmt.

tschöööö

chaosben 10. Nov 2006 09:14

Re: Transparente Komponente - Flackern
 
Ich nehme genau diese von mir oben beschriebe Methode um die CarbonCopy-Controls zu malen und diese sind transparent. Wenn das bei dir nicht funktioniert, dann deshalb weil du etwas anderes falsch machst. Lass zum Beispiel mal das WS_EX_TRANSPARENT weg.

crypti 10. Nov 2006 09:58

Re: Transparente Komponente - Flackern
 
Kann es sein das es hier Unterschiede zwischen Delphi7 und Delphi 2005/2006 gibt? Weil wenn ich testweise exakt deinen Source verwende, dann isses trotzdem weiß.

chaosben 10. Nov 2006 10:38

Re: Transparente Komponente - Flackern
 
Guck dir mal die Sourcen hier an. Vielleicht hilfts

crypti 10. Nov 2006 12:46

Re: Transparente Komponente - Flackern
 
OK, mein Fehler.

Ich hatte im Formular noch ein DoubleBuffered:=true drin. Wenn man das hat und die Zeichnungsaktionen mit dem Bitmap dann versucht, dann kommt man zum weißen Bereich.

Das muss dann natürlich nur in der jeweiligen Komponente machen.

crypti 13. Nov 2006 14:28

Re: Transparente Komponente - Flackern
 
Gibt es hier noch eine effektivere Methode? Zum Beispiel mit dem WS_EX_TRANSPARENT?

Das was ich allerdings benötige, ist beim Paint immer ein sauberes abbild vom Hintergrund.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:40 Uhr.

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