![]() |
Transparentes TCustomControl
Liste der Anhänge anzeigen (Anzahl: 1)
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
Delphi-Quellcode:
geht die Transparenz komplett flöten. Irgendwo fehlt mir noch ein Puzzlestück in der Paint-Behandlung von Windows.:gruebel:
myForm.DoubleBuffered := True;
Hat da einer Erfahrung mit, oder versteht jemand den Paint-Zyklus von Windows besser als ich, insbesondere mit Blick auf DoubleBuffered?
Delphi-Quellcode:
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.
TCustomTransparentControl
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:
Kleine Mini-Projekt im Anhang, bei dem die Komponente teilweise über einem TImage liegt.
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; |
AW: Transparentes TCustomControl
Zitat:
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. |
AW: Transparentes TCustomControl
I figured another solution that might solve the whole flickering thing.
try this
Code:
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.
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; 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 :lol: (just like PhotoShop flattening the layers) on the form forcing it to draw the same content instead of the empty black box. |
AW: Transparentes TCustomControl
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. |
AW: Transparentes TCustomControl
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. |
AW: Transparentes TCustomControl
Zitat:
Zitat:
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 :stupid: ,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 :oops: |
AW: Transparentes TCustomControl
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.
|
AW: Transparentes TCustomControl
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. :lol:
Zitat:
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. Zitat:
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. |
AW: Transparentes TCustomControl
In den Konopka Signature VCL Controls (vormals Raize Components), die es mittlerweile über GetIt gibt, wird das über eine
Delphi-Quellcode:
realisiert. Du kannst dir das ja mal anschauen und ausprobieren, ob das performant genug ist und nicht flackert.
procedure DrawParentImage
|
AW: Transparentes TCustomControl
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:21 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