AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Transparentes TCustomControl

Ein Thema von Gausi · begonnen am 25. Sep 2023 · letzter Beitrag vom 26. Sep 2023
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
847 Beiträge
 
Delphi 11 Alexandria
 
#1

Transparentes TCustomControl

  Alt 25. Sep 2023, 18:30
Ich möchte eine kleine Komponente erstellen, die (teilweise) transparent sein soll. Und da habe ich beim Zeichnen noch ein paar Problemchen. Zum einen "flackert" es noch ein wenig, und mit myForm.DoubleBuffered := True; geht die Transparenz komplett flöten. Irgendwo fehlt mir noch ein Puzzlestück in der Paint-Behandlung von Windows.

Hat da einer Erfahrung mit, oder versteht jemand den Paint-Zyklus von Windows besser als ich, insbesondere mit Blick auf DoubleBuffered? TCustomTransparentControl als Basis für die Ableitung habe ich auch probiert, aber da wird das flackern extrem störend. Wenn ich mir da die Invalidate-Methode anschaue, dann habe ich auch nicht den Eindruck, als wäre das sonderlich effizient.

Ich habe das mal auf ein Minimalbeispiel runtergebrochen. Hier wird einfach beim MouseMove an der Zeigerposition ein kleiner Kreis gezeichnet. Die eigentliche Komponente macht natürlich ein wenig mehr, und kann z.B. auch den Fokus bekommen.

Delphi-Quellcode:
TDemoDings = class(TCustomControl)
  private
    FX: Integer;
    FY: Integer;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure DoDraw(aCanvas: TCanvas);
    procedure Paint; override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure WMEraseBkgnd(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND;
  public

end;

///

procedure TDemoDings.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TDemoDings.DoDraw(aCanvas: TCanvas);
var
  aRect: TRect;
begin
  // Rahmen um die Komponente zeichnen
  aRect := ClientRect;
  InflateRect(aRect, -2, -2);
  Canvas.Brush.Color := clBlack;
  aCanvas.FrameRect(aRect);
  // an der aktuellen Position einen kleinen Kreis malen.
  aCanvas.Brush.Style := bsSolid;
  aCanvas.Brush.Color := clRed;
  aCanvas.Ellipse(FX-4, FY-4, FX+4, FY+4);
end;

procedure TDemoDings.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  aRect: TRect;
begin
  // Bereich, auf dem ich vorher rumgeschmiert habe, wieder löschen
  aRect := Rect(FX-5, FY-5, FX+5, FY+5);
  OffsetRect(aRect, Left, Top);
  InvalidateRect(Parent.Handle, @aRect, True);
  // Koordinaten neu setzen und per Invalidate das Neuzeichnen anfordern
  FX := X;
  FY := Y;
  Invalidate;
end;

procedure TDemoDings.Paint;
begin
  DoDraw(Canvas);
end;

procedure TDemoDings.WMEraseBkgnd(var Msg: TWMEraseBkgnd);
begin
  SetBkMode (msg.DC, TRANSPARENT);
  msg.result := 1;
end;
Kleine Mini-Projekt im Anhang, bei dem die Komponente teilweise über einem TImage liegt.
Angehängte Dateien
Dateityp: zip Demo.zip (11,5 KB, 10x aufgerufen)
The angels have the phone box.
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
213 Beiträge
 
#2

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 10:10
Does anyone have experience with or understand the Windows Paint cycle better than I do, especially with regard to DoubleBuffered?
I can't reproduce that annoying flicker, because on my Windows i have all theming and visual enhancement disabled even the Windows service is disabled.

But i barely notice an empty box around the mouse cursor as you move it, i think you referring to this barely noticeable behavior, which might be a flickering a lot on other Windows's.

Anyway, i don't have a definite answer or solution, but i can give thoughts about your code.
1) Assuming "invalids" is Invalidate as the demo, then you are invalidating a small rect at the parent then calling to full invalidate on self, here i am not sure if the sysetem will call to draw all the lower controls.
2) self is transparent, if it wasn't then repaint done right it should fully draw self, not only a rect, hence it should cause a redraw of all the lower levels, the form and the imagebox.
3) if you assigned even OnPaint on the form with do nothing (// as content) you should notice less flicker, as between Delphi and OS the Default paint procedure will be shorter, hence faster than left to Windows Message queue to fill and reach Delphi, as Windows remove and adjust and reorder Paint Messages as see fit.
4) the empty box i see is because the delay between draw the form then draw the image box, this is the meat of this behavior.

DoubleBuffering should help but to make use of it you should fully have drawn your custom and transparent control, at least once, this will complicate the procedure as you need to get all the lower level on your own, but this will leads to not use any ready to use transparent functionality.

My suggestion is : if it is possible and the background is not moving/changing (a lot), then cache it and don't use the InvalidateRect as it is the cause of the flickering box, and just redraw that box from you cache to remove your old red circle. (here you also can use smaller box at the size of the red circle)
Also smaller rect to invalidate will be less noticeable like using aRect := Rect(FX - 4, FY - 4, FX + 4, FY + 4); against aRect := Rect(FX - 3, FY - 3, FX + 3, FY + 3); against 5.
Find the best time to capture the canvas and use it as a cache to draw these small box's.

Hope that helps.
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
213 Beiträge
 
#3

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 10:33
I figured another solution that might solve the whole flickering thing.

try this
Code:
procedure TForm1.FormPaint(Sender: TObject);
begin
  Self.Canvas.CopyRect(Rect(Image1.Left,Image1.Top,Image1.Width,Image1.Height),Image1.Picture.Bitmap.Canvas,Image1.ClientRect);
end;
And make sure Image1.Visible := False; of course adjust the drawing rectangles accordingly, mine are might be off, also ImageBox should have TBitmap in the above solution.

I think you got the idea, and you can figure the best solution for your self, the idea here is we flatten everything under your Dingos (just like PhotoShop flattening the layers) on the form forcing it to draw the same content instead of the empty black box.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.149 Beiträge
 
Delphi 12 Athens
 
#4

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 11:01
Why useless a TImage in the GUI instead of a TBitmap directly?


But you know that you not only deactivate the theme, but also the new APIs of RichEdit, the TreeView, the Open and SaveDialogs, the TaskDialogs and who knows what else because you switch to the ancient versions of these DLLs?
Microsoft is also in the process of finally removing this old junk.

If it's about speed and resources, e.g. in VMs, Remote Desktop and Co., then deactivate menu and window animations, as well as transparencies and AeroPeek.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.149 Beiträge
 
Delphi 12 Athens
 
#5

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 11:08
Transparent wird es, wenn der Parent vorher seinen Hintergrund malt und du es den dann nur teilweise wieder übermalst.

DoubleBuffered malt auf ein internes Bitmap, anstatt direkt auf den Canvas.
Dieses Buffered-Bitmap wird aber ohne Tansparenz gemalt, also immer vollflächig.

Wird bei Transparent mit DoubleBuffered gearbeitet, dann malst du "transparent" in dieses Bitmap,
also ohne selbst "deinen" Hintergrund zu malen (der Parent mals sich dort leider niemals rein)
und bei der Transparenz ohne Hintergrund zeichnen, malst du dann auf den schwarzen Inhalt eines leeren Bitmaps, welche anschließend auf die Form kommt.

Benutzt du selbst ein eigenes TBitmap, oder einen anderen TGraphic-Typ, dann kannst du beim Kopieren/Malen dieses Bitmaps, auf den Canvas, dessen Transparenz-Funktion benutzen.
Bei TBitmap z.B. die TransparenceColor.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
213 Beiträge
 
#6

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 11:42
Why useless a TImage in the GUI instead of a TBitmap directly?
It it solve OP problem then it would be better solution of course, but he might need the TImage for Better control over the design in the IDE.

But you know that you not only deactivate the theme, but also the new APIs of RichEdit, the TreeView, the Open and SaveDialogs, the TaskDialogs and who knows what else because you switch to the ancient versions of these DLLs?
I really don't care about all the above, I don't need the fancy look, just working PC without wasting energy or burning CPU cycles as total waste.
My CPU is already 13 years old and i am happy with it, almost i can lie and say i can hear the cycles clicking inside it based on the running code ,so yes, performance has something to do with that fetish.

When i need fancy look, i delegate all that to AlphaSkin, it does great job and handle multimonitor with different scaling better than my own code also can integrate with the default Windows theming just fine, also i put the ability to change skins for the users as almost all of them love that.

Still missing the XP look
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
213 Beiträge
 
#7

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 11:58
Off-Topic : One more point i forgot to mention, with all Windows Theme disabled (or removed from the root), Delphi IDE performs more responsively and shows more stability at noticeable behavior, yet my latest IDE is Seattle, so may be it is better with the newer ones.
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
847 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 18:00
Danke für die Antworten! Ich verbuche das dann mal unter der Rubrik "Schöne Idee, aber lass ma lieber." Je mehr ich dazu im Netz rumsuche, desto mehr finde ich User, die an dem Thema verzweifeln, irgendwelche Krücken bauen, oder es einfach sein lassen. Jetzt gibt es ein weiteres Thema dazu.

DoubleBuffered malt auf ein internes Bitmap, anstatt direkt auf den Canvas.
Dieses Buffered-Bitmap wird aber ohne Tansparenz gemalt, also immer vollflächig.
Ok, dann mache ich da also im Prinzip keinen Fehler. Dass das Buffered-Bitmap, das bei DoubleBuffered genutzt wird, den Transparenz-Wunsch des Controls ignoriert, war mir nicht bewusst. Dann kann man da mit vertretbarem Aufwand nichts dran ändern. Denn ein eigenes "TWinControl" abzuleiten, dass eine andere Form von DoubleBuffering unterstützt, ist an der Stelle zu viel Aufwand. Auch andere Tricksereien werde ich dann eher sein lassen. (In einem Thread hier hat z.B. einer als Basis TGraphicControl genommen, das ein ein verstecktes TCustomControl erzeugt, dass dann die Tastatureingaben und Fokus etc. erhält.)
Da werde ich eher das Konzept für meine Control etwas überdenken, so dass ich auch gut ohne Transparenz leben kann. Dann ist der Hintergrund halt einfarbig.

My suggestion is : if it is possible and the background is not moving/changing (a lot), then cache it and don't use the InvalidateRect as it is the cause of the flickering box, and just redraw that box from you cache to remove your old red circle. (here you also can use smaller box at the size of the red circle)
Yes, this would simulate the transparency - which I already do in some cases. I just thought that there is a more elegant way to do this. It seems, that this is not the case. Maybe I'll add this as well for this component in a later version. But this should be easy to implement afterwards, when the component is otherwise ready.

Ist übrigens nichts wildes - soll eine skinbare Progress-Track-Range-Bar für meinen Player werden, bei der man zusätzlich einen Bereich für A-B-Wiederholung einstellen kann. Also quasi eine Trackbar mit bis zu drei Buttons und einer Fortschrittsanzeige. Bisher ist das zusammengefrickelt mit Shapes, Buttons und Images, und der ganze Code wird auf der Form erledigt (Verschieben per Drag&Drop, Umrechnung des Fortschritts von Sekunden in Pixel etc.). Das muss mal besser gemacht werden.
The angels have the phone box.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.014 Beiträge
 
Delphi 12 Athens
 
#9

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 18:33
In den Konopka Signature VCL Controls (vormals Raize Components), die es mittlerweile über GetIt gibt, wird das über eine procedure DrawParentImage realisiert. Du kannst dir das ja mal anschauen und ausprobieren, ob das performant genug ist und nicht flackert.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Transparentes TCustomControl

  Alt 26. Sep 2023, 19:15
Zitat von Gausi:
soll eine skinbare Progress-Track-Range-Bar für meinen Player werden, bei der man zusätzlich einen Bereich für A-B-Wiederholung einstellen kann
Brauchst Du dafür wirklich eine TCustomControl?. Müsste doch per TGraphicControl funktionieren.
Renate
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz