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 Regionen, Rahmen und Schatten (https://www.delphipraxis.net/185374-regionen-rahmen-und-schatten.html)

stahli 3. Jun 2015 23:56

Regionen, Rahmen und Schatten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich bastle an eigenen Controls. Solange das nur Rechtecke waren, war das alles recht gut zu lösen.

Nun habe ich Page-Controls, die unregelmäßig sind. Im Bild mal 10 hintereinander und etwas versetzt.
Man erkennt, dass die Controls aus Regionen bestehen und oben solche "Laschen" haben.
Neben den Laschen sind sie sowohl transparent als auch für die Maus nicht erfassbar.

So weit so gut.

Ich habe nun zwei Fragen:

1) Wenn ich für den Rahmen ein Polygon definiere und dieses Polygon dann auch mit CreatePolygonRgn benutze, um den Zeichenbereich zu begrenzen, dann werden die rechts und unten positionierten Rahmenlinien nicht mehr gezeichnet.
Daher habe ich das Polygon für die Region nach Rechts und unten um 1 Pixel vergrößert.

Delphi-Quellcode:
  SetLength(fPolygonF, 8);
  SetLength(fPolygonR, 8);

  PolygonF[0] := Point(ClientRect.Left, ClientRect.Top + 24);
  PolygonF[1] := Point(ClientRect.Left + RL, ClientRect.Top + 24);
  PolygonF[2] := Point(ClientRect.Left + RL, ClientRect.Top);
  PolygonF[3] := Point(ClientRect.Left + (RL + RW), ClientRect.Top);
  PolygonF[4] := Point(ClientRect.Left + (RL + RW), ClientRect.Top + 24);
  PolygonF[5] := Point(ClientRect.Right, ClientRect.Top + 24);
  PolygonF[6] := Point(ClientRect.Right, ClientRect.Bottom);
  PolygonF[7] := Point(ClientRect.Left, ClientRect.Bottom);

  PolygonR[0] := Point(ClientRect.Left, ClientRect.Top + 24);
  PolygonR[1] := Point(ClientRect.Left + RL, ClientRect.Top + 24);
  PolygonR[2] := Point(ClientRect.Left + RL, ClientRect.Top);
  PolygonR[3] := Point(ClientRect.Left + (RL + RW) + 1, ClientRect.Top);
  PolygonR[4] := Point(ClientRect.Left + (RL + RW) + 1, ClientRect.Top + 24);
  PolygonR[5] := Point(ClientRect.Right + 1, ClientRect.Top + 24);
  PolygonR[6] := Point(ClientRect.Right + 1, ClientRect.Bottom + 1);
  PolygonR[7] := Point(ClientRect.Left, ClientRect.Bottom + 1);
Für den Zweck ist das ja noch ok, aber kann man das irgendwie automatisieren?
Man könnte ja auch mal ein unregelmäßiges (z.B. sternförmiges mit schrägen und vielen Zacken) Polygon haben.

Gibt es eine Funktion, die ein Polygon nach rechts und unten um 1 Pixel vergrößert?
Man müsste ja erst einmal erkennen, welche Linien rechts oder unten liegen.


2) Den Controls habe ich auf Wunsch Schatten zugewiesen.
Jetzt wird der Schatten natürlich rechts am ClientRect des Controls gezeichnet.
(Der Schatten wird natürlich außerhalb des ControlRects gezeichnet, da er ja nicht zum Control gehört.)
Nun ist der Schatten neben dem freigestellten Bereich natürlich unsinnig und sollte dafür neben der Lasche oben gezeichnet werden.

Ich könnte das natürlich als Sonderfall für das Control explizit regeln, aber gibt es vielleicht eine günstige generelle Lösung?

Auch hier müsste (wie bei Punkt 1) ermittelt werden, welche Kanten (rechts und unten) einen Schatten werfen müssen.


Natürlich will ich hier keine 3D-Graphicengine bauen.
Ein Ausstanzen unregelmäßiger Polygone mit sichtbarem Rahmen und einem kleinen Schatten wäre völlig ausreichend.


Hat jemand Ideen dazu?


Edit: ich habe eine idee. Schreibe später weiter.

Dejan Vu 4. Jun 2015 06:46

AW: Regionen, Rahmen und Schatten
 
Wieso müssen das denn Regions sein? Macht man das so? Zeichne deine PageControls doch einfach direkt auf den Canvas der Form... Und wie im vorherigen Thread auch hier: Erst alle Controls ohne Schatten, dann die Schatten und zum Schluss die Controls mit Schatten zeichnen. Dann musst Du Dir :gruebel: überhaupt keine Sorgen mehr machen (außer um das Clipping, weswegen Du vielleicht Regions verwendest :stupid:)

stahli 4. Jun 2015 08:47

AW: Regionen, Rahmen und Schatten
 
So, jetzt kann ich mal kurz... Die Lösung (bzw. Idee) fiel mir gestern vor´m Einschlafen ein - kennt Ihr ja sicher auch...

Ja, es geht um Clipping und Schatten.

Bisher habe ich den Schatten als Linien rechts und unterhalb des Controls gezeichnet. Die Ebenen (wie von Dejan Vu beschrieben) berücksichtige ich schon.
Ich habe darüber hinaus auch noch "richtige" Ebenen (Tier). So kann ich z.B. Controls in einem Formular staffeln, das ist dann quasi eine zweite Z-Ordnung und legt fest, welche Controls über anderen zu zeichnen sind (ohne sichtbare Erhöhung).

Innerhalb der Tiers werden schattierte Controls nochmal extra behandelt (und "erhöht" dargestellt).
Erst werden nicht schattierte gezeichnet, dann Schatten, dann die erhöhten Controls.

Soweit als Zusammenfassung.

Die Schatten werde ich jetzt anders versuchen. Dazu werde ich die Regionen der schattierten Controls in einer großen Region sammeln (so dass man eine große Ebene mit "Flecken" hat, das ganze um ein paar Pixel verschieben und den Hintergrund einfärben.
Dann können die Controls auf die Schattenflächen gezeichnet werden, so dass nur rechts und unten etwas Schatten über steht.
=> Ich muss dann wohl doch nochmal nach einer Blur-Funktion schauen.

Für die Frame- und Clipping-Regionen habe ich auch eine Idee:
- Controlregion kopieren
- Kopie 1px nach rechts verschieben
- beide vereinigen
- Ergebnis kopieren
- Kopie 1px nach unten verschieben
- beide vereinigen
- Clipping auf das Ergebnis festlegen
So sollte das Clipping immer erst hinter/unter dem Rahmen erfolgen
=> Gibt es dafür eine fertige Funktion (oder bessere Ansätze)?

Namenloser 4. Jun 2015 15:54

AW: Regionen, Rahmen und Schatten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von stahli (Beitrag 1304133)
Die Schatten werde ich jetzt anders versuchen. Dazu werde ich die Regionen der schattierten Controls in einer großen Region sammeln (so dass man eine große Ebene mit "Flecken" hat, das ganze um ein paar Pixel verschieben und den Hintergrund einfärben.
Dann können die Controls auf die Schattenflächen gezeichnet werden, so dass nur rechts und unten etwas Schatten über steht.
=> Ich muss dann wohl doch nochmal nach einer Blur-Funktion schauen.

Ich hatte mal eine Blur-Funktion gepostet.

Zitat:

Zitat von stahli (Beitrag 1304119)
1) Wenn ich für den Rahmen ein Polygon definiere und dieses Polygon dann auch mit CreatePolygonRgn benutze, um den Zeichenbereich zu begrenzen, dann werden die rechts und unten positionierten Rahmenlinien nicht mehr gezeichnet.
Daher habe ich das Polygon für die Region nach Rechts und unten um 1 Pixel vergrößert.

[...]

Für den Zweck ist das ja noch ok, aber kann man das irgendwie automatisieren?
Man könnte ja auch mal ein unregelmäßiges (z.B. sternförmiges mit schrägen und vielen Zacken) Polygon haben.

Auch das ginge. Du müsstest an jeder Ecke prüfen, ob der Vektor, in dessen Richtung sich der Schatten ausbreiten soll, ins Polygon reingeht oder aus dem Polygon rauskommt. Das kannst du leicht tun, indem schaust, ob das Skalarprodukt des Vektors mit den Normalen der beiden angrenzenden Kanten positiv oder negativ ist. Ich habe mal eine Skizze dazu gemacht. Positives Skalarprodukt ist in der Skizze blau, negatives Skalarprodukt ist rot. Somit ergeben sich für die Ecken drei verschiedene Fälle:
  • Rot/Rot: Die Ecke bleibt wo sie ist.
  • Blau/Blau: Die Ecke wird verschoben.
  • Rot/Blau: Eine zusätzliche Kante wird eingefügt.

Wobei bei dieser Lösung zu beachten ist, dass die Richtung der Normalen davon abhängt, in welcher Richtung das Polygon gewickelt ist. Man muss also definieren, welche Richtung positiv ist.

stahli 4. Jun 2015 16:14

AW: Regionen, Rahmen und Schatten
 
Zitat:

Zitat von Namenloser (Beitrag 1304161)
Ich hatte mal eine Blur-Funktion gepostet.

Da bin ich schon bei meiner Schattenrecherche drauf gestoßen. Jetzt kann ich mir die Suche danach heute Abend sparen und bin eher fertig. :-)


Zitat:

Zitat von Namenloser (Beitrag 1304161)
Auch das ginge. Du müsstest an jeder Ecke prüfen, ob der Vektor, in dessen Richtung sich der Schatten ausbreiten soll, ins Polygon reingeht oder aus dem Polygon rauskommt. Das kannst du leicht tun, indem schaust, ob das Skalarprodukt des Vektors mit den Normalen der beiden angrenzenden Kanten positiv oder negativ ist. Ich habe mal eine Skizze dazu gemacht. Positives Skalarprodukt ist in der Skizze blau, negatives Skalarprodukt ist rot. Somit ergeben sich für die Ecken drei verschiedene Fälle:
  • Rot/Rot: Die Ecke bleibt wo sie ist.
  • Blau/Blau: Die Ecke wird verschoben.
  • Rot/Blau: Eine zusätzliche Kante wird eingefügt.

Wobei bei dieser Lösung zu beachten ist, dass die Richtung der Normalen davon abhängt, in welcher Richtung das Polygon gewickelt ist. Man muss also definieren, welche Richtung positiv ist.

Ich beneide Euch Studiosos oft! Da kann ich leider nicht folgen.
Wenn das mit meiner oben beschriebenen Regionen-Kopier-und-Vereinigungsorgie einigermaßen performant funktioniert werde ich es erst mal damit versuchen.
Ansonsten ... mal schauen ...


EDIT: Ahh! Doch!!! Cool! Jetzt habe ich es verstanden! :-)
Vielleicht kriege ich das sogar umgesetzt. :thumb:

stahli 7. Jun 2015 23:28

AW: Regionen, Rahmen und Schatten
 
Liste der Anhänge anzeigen (Anzahl: 2)
Wie kann man jemandem danken, der keinen Namen hat?
Am besten: Ey, Du da - Danke! ;-)

Ich habe jetzt ein brauchbares Ergebnis erreicht.
Es war nicht ganz einfach, aber durchaus interessant.

Graphics32 wollte ich erst mal vermeiden. Funktionen, die dort verwendet werden, habe ich nicht verstanden und daher selbst welche geschrieben.
Für meine Zwecke reicht das so.

Für den Fall, dass es mal jemand braucht oder sich einfach dafür interessiert, habe ich meine Entwicklungsfortschritte mal zusammengefasst: https://youtu.be/sKfh7SaHt7s


Anbei noch zwei Quelltextauszüge als mögliche Anregungen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:16 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