Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi [UpdateLayeredWindow] Vergrößerbare Form realisieren (https://www.delphipraxis.net/94113-%5Bupdatelayeredwindow%5D-vergroesserbare-form-realisieren.html)

Yheeky 16. Jun 2007 15:13


[UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Hi,

ich habe eine Optionsform, die ich mit einem transparenten Rahmen zeichne lasse. Das mache ich so:

Delphi-Quellcode:
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;
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?

Khabarakh 16. Jun 2007 15:16

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Was geschieht denn beim Vergrößern? Passt du währenddessen auch den Parameter "Size" an?

Yheeky 16. Jun 2007 15:34

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:

Khabarakh 16. Jun 2007 15:45

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.

Yheeky 16. Jun 2007 15:59

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?

Khabarakh 16. Jun 2007 16:14

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.

Yheeky 16. Jun 2007 16:29

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Okay, ich versuche es mal zu erklären. So ist mein Fenster zur Zeit aufgebaut:

Delphi-Quellcode:
Icon ----- X
|          |
|          |
|          |
|----------|
Angenommen ich vergrößere das Fenster nun minimal, dann brauche ich ja schon ein komplett neues Bild, was ich auf die Form zeichne.

Delphi-Quellcode:
Icon ------ X
|           |
|           |
|           |
|           |
|-----------|
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?

Wenn du´s immer noch nicht verstanden hast, kein Problem. Dann versuche ich mal eine Grafik zu machen...

OregonGhost 16. Jun 2007 16:47

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Zitat:

Ich kann also kein festes Bild nehmen, sondern muss Einzelteile erstellen. Nur wie bekomme ich die als PNG?
UpdateLayeredWindow will kein PNG. Du übergibst ihm eine 32-Bit-Grafik mit Alphakanal. Und die musst du ganz einfach selbst zeichnen, wie du im Prinzip ja schon selbst gesagt hast. Das geht zum Beispiel, indem du die Einzelteile (z.B. vier Ecken, vier Kanten und einen Mittelteil) entweder als einzelne Grafiken oder als eine große Grafik, die sie alle enthält, lädst und diese dann entsprechend wie in deinem ASCII-Bild dargestellt auf eine Bitmap zeichnest. Und die gibst du dann UpdateLayeredWindow.

Yheeky 16. Jun 2007 19:00

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Okay, klingt logisch...werde ich die Tage mal austesten. Danke schonmal!

Yheeky 17. Jun 2007 14:38

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:

Khabarakh 17. Jun 2007 14:50

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:
1-2
| |
4-3
(kleiner geht es nur noch, wenn du einfach nur eine Ecke speicherst und diese dann drehst)
z.B. soetwas generieren lassen:
Code:
1-----------2
|           |
|           |
|           |
|           |
|           |
4-----------3

Yheeky 17. Jun 2007 15:56

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:
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;
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.

Khabarakh 17. Jun 2007 16:14

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 ;) .

Yheeky 17. Jun 2007 17:01

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
TImage hat kein OnPaint :???:

Khabarakh 17. Jun 2007 17:15

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: .

Yheeky 17. Jun 2007 17:43

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:

Khabarakh 17. Jun 2007 17:58

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: .

Yheeky 18. Jun 2007 00:24

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Ja, habe ich ja versucht, aber bei Form1.OnResize bzw. OnPaint geht´s nicht :-(

EWeiss 18. Jun 2007 06:36

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

http://www.delphipraxis.net/download.php?id=22588

gruss Emil

Yheeky 18. Jun 2007 09:14

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.

EWeiss 18. Jun 2007 14:39

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Zitat:

Zitat von Yheeky
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.

???

Warum klar kannst du die größe verändern.
Unten in der rechten Ecke MouseDown und ziehen.

gruss Emil

Khabarakh 18. Jun 2007 14:55

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Zitat:

Zitat von Yheeky
Ja, habe ich ja versucht, aber bei Form1.OnResize bzw. OnPaint geht´s nicht :-(

:gruebel: Dann kann der Fehler aber so langsam nicht mehr in der VCL oder meinem Sieb von Gedächtnis liegen, sondern definitiv in deinem Code.

Yheeky 18. Jun 2007 15:07

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:
Image1.Picture.Graphic.Width := Image1.Width;
Image1.Picture.Graphic.Height := Image1.Height;
Danke an alle, die mir bei der Problemlösung geholfen haben :) :thumb:

Yheeky 18. Jun 2007 16:21

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?

EWeiss 18. Jun 2007 17:28

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Zitat:

Zitat von Yheeky
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?

Ich verstehe nicht so ganz was du vorhast.
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

Khabarakh 18. Jun 2007 19:01

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
Zitat:

Zitat von Yheeky
Wie mache ich das denn nun?

Benutzt man die Graphics32-Lib, ist es nicht unklug, auch die Graphics32-Funktionen zu benutzen ;) . Es existiert keine TCanvas32, alle Routinen sind direkt in TBitmap32 enthalten. Und unter denen wirst du auf jeden Fall etwas Passendes finden (afair besitzt Draw(To) zum Bleistift einige Überladungen mehr als das VCL-Äquivalent).

Yheeky 18. Jun 2007 21:33

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;

Yheeky 19. Jun 2007 13:00

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!

Yheeky 21. Jun 2007 15:17

Re: [UpdateLayeredWindow] Vergrößerbare Form realisieren
 
*push* :(

Keiner eine Idee oder eine Erklärung warum das nicht funktioniert? :cry:

Yheeky 30. Jun 2007 19:24

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 15:40 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