![]() |
[UpdateLayeredWindow] Vergrößerbare Form realisieren
Hi,
ich habe eine Optionsform, die ich mit einem transparenten Rahmen zeichne lasse. Das mache ich so:
Delphi-Quellcode:
Das Problem hierbei ist nun, dass das Zeichnen der Form nur funktioniert, wenn die Form in der Größe nicht verändert werden kann. Wie kann ich mit diesem Prinzip Sizable Forms erstellen?
procedure TfrmOptionen_Maske.FormCreate(Sender: TObject);
var Alpha : Boolean; ResStream : TResourceStream; begin Bit := TBitmap32.Create; ResStream := TResourceStream.Create(Hinstance, 'BackOpt', PChar('RC_DATA')); try LoadPNGIntoBitmap32(Bit, ResStream, Alpha); finally ResStream.Free; end; SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED {or WS_EX_TRANSPARENT}); BlendF.BlendOp := AC_SRC_OVER; BlendF.BlendFlags := 0; BlendF.SourceConstantAlpha := 255; BlendF.AlphaFormat := AC_SRC_ALPHA; P := Point(0, 0); Size.cx := Bit.Width; Size.cy := Bit.Height; UpdateLayeredWindow(Handle, 0, nil, @Size, Bit.Handle, @P, 0, @BlendF, ULW_ALPHA); Left := frmOptionen.Left; Top := frmOptionen.Top; end; |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Was geschieht denn beim Vergrößern? Passt du währenddessen auch den Parameter "Size" an?
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Bisher mache ich noch nichts, da das Bild ja nur in einer fixen Größe vorlag. Ich hatte das Fenster 350x330 groß und dementsprechend war die PNG groß, welche dann auf die Maskenform gezeichnet wurde.
Nun soll sich aber die Größe der Form verändern lassen...und da liegt das Problem. :roll: |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Dann probier es doch einfach mal aus. Übergib Update[...] ein größeres Bitmap und passe entsprechend Size an. Ich habe es noch nie ausprobiert, aber das sollte eigentlich funktionieren, schließlich schafft das WPF auch.
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Das Problem ist ja aber, dass ich die neue Größe nicht kenne. Das heisst ein Bild von der neuen Größe muss "erstellt" werden. Länge der Titelleiste und der Rahmen muss ja bei einer größeren Form auch größer sein...weisst du was ich meine?
PS: Was ist WPF? |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Nein, ich verstehe nicht wirklich, was du meinst ;) . Nehmen wir mal an, das Fenster ließe sich durch Ziehen an der unteren rechten Ecke vergrößern. Dann musst dir die Mausposition beim OnMouseDown merken, aus der Differenz zur Position aus jedem OnMouseMove/Up kannst du dann die neue Größe des Fensters errechnen. Dann erstellst du ein Bitmap dieser Größe, füllst es mit deinem Fensterinhalt (wie auch immer dieser gestaltet sein mag) und rufst UpdateLayeredWindow auf.
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Okay, ich versuche es mal zu erklären. So ist mein Fenster zur Zeit aufgebaut:
Delphi-Quellcode:
Angenommen ich vergrößere das Fenster nun minimal, dann brauche ich ja schon ein komplett neues Bild, was ich auf die Form zeichne.
Icon ----- X
| | | | | | |----------|
Delphi-Quellcode:
Nun sind es 6 "-" in der Titelleiste anstatt 5. Dass auch der Rahmen "verlängert" werden muss, kann man ja auch erkennen. Ich kann also kein festes Bild nehmen, sondern muss Einzelteile erstellen. Nur wie bekomme ich die als PNG?
Icon ------ X
| | | | | | | | |-----------| Wenn du´s immer noch nicht verstanden hast, kein Problem. Dann versuche ich mal eine Grafik zu machen... |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Zitat:
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Okay, klingt logisch...werde ich die Tage mal austesten. Danke schonmal!
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Liste der Anhänge anzeigen (Anzahl: 1)
Ich muss nochmal nachfragen: Ich habe in meinem festen Fenster einen Schattenverlauf und somit benötige ja ein 32-Bit Bild als Alpha-Channel. Wie erstelle ich das?
Hier mal ein Teil der Beispielform: |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Erstelle ein PNG, das den kleinstmöglichen Rahmen beinhaltet. Daraus kannst du nun alle benötigten Größen erstellen, indem du die Kanten streckst (kachelst). Es seien 1,2,3,4 die Ecken und - & | die Kanten, dann kannst du aus dem Ausgangsbitmap
Code:
(kleiner geht es nur noch, wenn du einfach nur eine Ecke speicherst und diese dann drehst)
1-2
| | 4-3 z.B. soetwas generieren lassen:
Code:
1-----------2
| | | | | | | | | | 4-----------3 |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Liste der Anhänge anzeigen (Anzahl: 1)
Okay, nächstes Problem ;-)
Ich habe mir mal eine neue Testanwendung geschrieben, mit der ich die einzelnen Teile zeichnen lasse. Die Funktion Zeichnen sieht so aus:
Delphi-Quellcode:
Vom Prinzip her funktioniert es schon, aber wenn ich die Form vergrößere, scheint sich das Programm nur die Position vom Image zu merken, die es beim Start hatte (s.Screenshot). Image1 ist bei Align auf alClient gestellt.
procedure TForm1.Zeichnen;
var ObenLinks, ObenMitte, ObenRechts : TImage; FormBreite, ObenLinksBreite, ObenMitteBreite, ObenRechtsBreite : SmallInt; I: Integer; begin Image1.Canvas.FillRect(Rect(0, 0, Image1.Width, Image1.Height)); ObenLinks := TImage.Create(Form1); ObenMitte := TImage.Create(Form1); ObenRechts := Timage.Create(Form1); ObenLinks.Picture.LoadFromFile('C:\Dokumente und Einstellungen\Chris\Desktop\SkinForm\ObenLinks.png'); ObenMitte.Picture.LoadFromFile('C:\Dokumente und Einstellungen\Chris\Desktop\SkinForm\ObenMitte.png'); ObenRechts.Picture.LoadFromFile('C:\Dokumente und Einstellungen\Chris\Desktop\SkinForm\ObenRechts.png'); ObenLinksBreite := ObenLinks.Picture.Width; ObenMitteBreite := ObenMitte.Picture.Width; ObenRechtsBreite := ObenRechts.Picture.Width; FormBreite := Image1.Width; // Ecke Links oben zeichnen Image1.Canvas.Draw(0,0, ObenLinks.Picture.Graphic); // Mitte zeichnen for I := ObenLinksBreite to FormBreite - ObenRechtsBreite-1 do Image1.Canvas.Draw(I, 0, ObenMitte.Picture.Graphic); // Ecke Rechts oben zeichnen Image1.Canvas.Draw(FormBreite - ObenRechtsBreite,0, ObenRechts.Picture.Graphic); end; |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Rufst du "Zeichnen" auch im OnPaint des Images auf? Sonst ist es logisch, dass der Inhalt ein wenig statisch ist ;) .
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
TImage hat kein OnPaint :???:
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Tut mir leid, habe die VCL nicht (mehr) im Kopf und auch keine OH installiert - versuch es mal mit OnResize, sollte dieses Event existieren :mrgreen: .
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Das Image hat kein Event, was das Zeichnen oder das Verändern der Größe abfragt.
Was nun? :roll: |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Das Image bezieht seine Größe doch von einem gewissen anderen Control. Also könnte man statt Image.OnResize ebenso gut auf das Event jenes gewissen Controls zurückgreifen ;) .
Memo @myself: Die Unterschiede zwischen VCL und Windows Forms sind doch größer, als ich sie in Erinnerung hatte :duck: . |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Ja, habe ich ja versucht, aber bei Form1.OnResize bzw. OnPaint geht´s nicht :-(
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Im grunde ist das doch nichts anderes als ein Skin der auf einer Form aufgesetzt wird.
Schau dir mal mein beispiel an vielleicht kannst du was von brauchen,. Welche Bitmaps du letztendlich verwendest liegt in deinen ermessen. Ist aber vom händling so gut wie das selbe ![]() gruss Emil |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Also vom Zeichnen her klappt bei mir alles. Es geht lediglich darum, dass das Image beim Vergrößern der Form, auch nach wie vor die Zeichenfläche der Form benutzt. Das ist irgendwie nicht der Fall, wie man in meinem letzten Posting an dem Bild im Anhang erkennt kann.
Bei deinem Beispiel kann ich das leider auch nicht finden, weil du bei deiner Form auch keine Veränderung der Größe zulässt. |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Zitat:
Warum klar kannst du die größe verändern. Unten in der rechten Ecke MouseDown und ziehen. gruss Emil |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Zitat:
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
@EWeiss: Okay, sorry, hatte ich nicht gesehen.
Habe nun das Problem gefunden. Man muss die Größe unter Picture.Graphic noch anpassen, dann geht es:
Delphi-Quellcode:
Danke an alle, die mir bei der Problemlösung geholfen haben :) :thumb:
Image1.Picture.Graphic.Width := Image1.Width;
Image1.Picture.Graphic.Height := Image1.Height; |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Nun kommt es wieder zum Problem mit der Transparenz :cry:
Ich kann auf das Bit vom Typ TBitmap32 nicht zeichnen :-( Wenn ich auf das Canvas zeichnen möchte kommt die Meldung "Zeichnen auf Leinwand nicht erlaubt". Wie mache ich das denn nun? |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Zitat:
Du hast ne Form und willst dieser ein aussehen ala Vista spendieren ? oder was! Wenn ja dann mach dir ein standart Picture in dem sich einzelne bereiche der Pictures welche du auf die Form setzen willst befinden. Dann kannst du über 2 API's auf ein Image kopieren. Das geht dann über BitBlt und StretchBlt gruss Emil |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Zitat:
|
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Okay, danke für den Hinweis, dass ich direkt auf die Funktionen Draw und DrawTo zugreifen muss.
Das habe ich nun gemacht und bin dann nach dem gewohnten Schema vorgegangen, doch leider ist es wohl nur "oberflächlich" gezeichnet werden. Die Form jedenfalls bleibt leer. Hier der Code:
Delphi-Quellcode:
procedure TfrmMain_Maske.FormCreate(Sender: TObject);
var Alpha : Boolean; I : Integer; ObenLinks, ObenMitte, ObenRechts, RandLinks, RandRechts, UntenLinks, UntenMitte, UntenRechts : TBitmap32; ObenLinksStream, ObenMitteStream, ObenRechtsStream, RandLinksStream, RandRechtsStream, UntenLinksStream, UntenMitteStream, UntenRechtsStream : TResourceStream; begin // Hintergrundbild erstellen Background := TBitmap32.Create; Background2 := TBitmap32.Create; // Formkacheln erstellen ObenLinks := TBitmap32.Create; ObenMitte := TBitmap32.Create; ObenRechts := TBitmap32.Create; RandLinks := TBitmap32.Create; RandRechts := TBitmap32.Create; UntenLinks := TBitmap32.Create; UntenMitte := TBitmap32.Create; UntenRechts := TBitmap32.Create; try // Formkacheln laden ObenLinksStream := TResourceStream.Create(Hinstance, 'ObenLinks', PChar('RC_DATA')); ObenMitteStream := TResourceStream.Create(Hinstance, 'ObenMitte', PChar('RC_DATA')); ObenRechtsStream := TResourceStream.Create(Hinstance, 'ObenRechts', PChar('RC_DATA')); RandLinksStream := TResourceStream.Create(Hinstance, 'RandLinks', PChar('RC_DATA')); RandRechtsStream := TResourceStream.Create(Hinstance, 'RandRechts', PChar('RC_DATA')); UntenLinksStream := TResourceStream.Create(Hinstance, 'UntenLinks', PChar('RC_DATA')); UntenMitteStream := TResourceStream.Create(Hinstance, 'UntenMitte', PChar('RC_DATA')); UntenRechtsStream := TResourceStream.Create(Hinstance, 'UntenRechts', PChar('RC_DATA')); LoadPNGIntoBitmap32(ObenLinks, ObenLinksStream, Alpha); LoadPNGIntoBitmap32(ObenMitte, ObenMitteStream, Alpha); LoadPNGIntoBitmap32(ObenRechts, ObenRechtsStream, Alpha); LoadPNGIntoBitmap32(RandLinks, RandLinksStream, Alpha); LoadPNGIntoBitmap32(RandRechts, RandRechtsStream, Alpha); LoadPNGIntoBitmap32(UntenLinks, UntenLinksStream, Alpha); LoadPNGIntoBitmap32(UntenMitte, UntenMitteStream, Alpha); LoadPNGIntoBitmap32(UntenRechts, UntenRechtsStream, Alpha); // FormSkin in Kacheln auf die Form zeichnen // Oben links Background.Draw(0,0, ObenLinks); // Oben Mitte for I := ObenLinks.Width to Self.ClientWidth-ObenRechts.Width do Background.Draw(I,0, ObenMitte); // Oben Rechts Background.Draw(Self.ClientWidth-ObenRechts.Width,0, ObenRechts); finally ObenLinksStream.Free; ObenMitteStream.Free; ObenRechtsStream.Free; RandLinksStream.Free; RandRechtsStream.Free; UntenLinksStream.Free; UntenMitteStream.Free; UntenRechtsStream.Free; end; SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED {or WS_EX_TRANSPARENT}); // WS_EX_TRANSPARENT macht das Fenster für Mausklicks transparent BlendF.BlendOp := AC_SRC_OVER; BlendF.BlendFlags := 0; BlendF.SourceConstantAlpha := 255; BlendF.AlphaFormat := AC_SRC_ALPHA; P := Point(0, 0); Size.cx := Background.Width; Size.cy := Background.Height; UpdateLayeredWindow(Handle, 0, nil, @Size, Background.Handle, @P, 0, @BlendF, ULW_ALPHA); Left := 0; Top := 0; end; |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Hatte die LoadPNGIntoBitmap32 - Aufrufe im Quellcode vergessen...dachte schon das Problem sei nun gelöst, aber leider gelingt mir das "Zusammensetzen" einer PNG-Datei mit anschließendem Zeichnen über UpdateLayeredWindow immer noch nicht. :cry:
Wenn jemand eine Idee hat einfach posten! |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
*push* :(
Keiner eine Idee oder eine Erklärung warum das nicht funktioniert? :cry: |
Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
so, ich bin inzwischen etwas weiter gekommen. Soweit funktioniert das Zeichnen, aber der Alpha-Kanal ist irgendwie nicht richtig. Sind das wommöglich die falschen Alpha-Bilder? Habe mal ein Beispiel geschrieben. Vielleicht kann sich das mal einer ansehen und mir einen Tipp geben, woran das liegt, dass das Bild nicht richtig transparent angezeigt wird. Wäre super, danke! Noch eine Info zum Beispiel: Mit den Pfeiltasten "Hoch" und "Runter" wird die Form in der Größe verändert. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:49 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