Z-Order ermitteln
-
Hallo,
gibt es eine Möglichkeit, die Z-Order der Objekte, die sich auf einem Panel befinden, während der Laufzeit zu ermitteln?Es geht um mehrere TLabel-Objekte, die während der Laufzeit dynamisch eingefügt werden und sich teilweise überlappen können.
Mit BringToFront() und SendToBack() lege ich die Reihenfolge (Z-Order) für die Überlappungen fest.Wie kann ich beim Schließen des Formulars die exakte Reihenfolge vom obersten bis zum untersten Objekt ermitteln, um sie abzuspeichern und um beim nächsten Öffnen des Formulars die Labels wieder in die gleiche Reihenfolge bringen zu können?
Bin für jede Hilfe dankbar!
-
Jedes
TComponent
Objekt hat die EigenschaftComponents
undComponentCount
, in der die untergeordneten Komponenten abgelegt sind. Ob die Reihenfolge der Z-Order entspricht weiß ich nicht, aber das kannst du ja einfach herausfinden.
-
das habe ich schon versucht. Ist aber eine andere Reihenfolge, Z-Order kann daran nicht abgeleitet werden.
-
j.halder schrieb:
das habe ich schon versucht. Ist aber eine andere Reihenfolge, Z-Order kann daran nicht abgeleitet werden.
Müsste eigentlich (wie von DocShoe geschrieben) was mit der Erstellungsreigenfolge zu tun haben den:
Button 2 wird über den Button 1 gezeichnet
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 199 ClientWidth = 325 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Button1: TButton <<< 1 <<< Left = 72 Top = 60 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 0 end object Button2: TButton <<< 2 <<< Left = 106 Top = 72 Width = 75 Height = 25 Caption = 'Button2' TabOrder = 1 end end
Nach bring to front ist Button 2 hinter Button 1
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 199 ClientWidth = 325 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Button2: TButton <<< 2 <<< Left = 106 Top = 72 Width = 75 Height = 25 Caption = 'Button2' TabOrder = 1 end object Button1: TButton <<< 1 <<< Left = 72 Top = 60 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 0 end end
Somit musste die Erstellungsreihenfolge für die Labels speichern
-
Z-Order schrieb:
Müsste eigentlich (wie von DocShoe geschrieben) was mit der Erstellungsreigenfolge zu tun haben den:
Button 2 wird über den Button 1 gezeichnetDas hilft mir leider auch nicht weiter, da die Objekte erst zur Laufzeit eingefügt werden und die Reihenfolge in der Eigenschaft Components nicht der optischen Anordnung auf dem Formular entspricht.
Zum besseren Verständnis:
Das Ganze ist ein Reporteditor auf Basis der Jedi-Komponenten (TJyDesignPanel, TJvDesignSurface, TJvDesignImp usw.).
Der Anwender kann zur Laufzeit Objekte (TLabel, TImage, TShape) einfügen, löschen und verschieben. Außerdem können überlappende Objekte in den Vorder- oder Hintergrund gesetzt werden.
Und hier liegt das Problem: Wird ein Objekt, das sich im Hintergrund befindet und halb verdeckt ist, mit der Funktion BringToFront() in den Vordergrund geholt, so dass es voll sichtbar ist, ändert sich dadruch in der Eigenschaft Components nichts. Die Reihenfolge in Components bleibt unverändert.Nach dem Editieren lese ich die in JyDesignPanel eingefügten Objekte mittels Components bzw ComponentCount aus und erstelle daraus einen Report. Das funktioniert auch alles tadellos, mit Ausnahme von überlappenden Objekten. Ich kann nicht erkennen, welches im Vordergrund und welches im Hintergrund ist.
TJyDesignPanel ist von TPanel abgeleitet. Ich hatte gehofft, dass es eine Möglichkeit gibt, die Z-Order aus den Basisklassen zu ermitteln.
-
Wenn deine Label von TWinControl abgeleitet sind und ein Fensterhandle besitzen kannst du Folgendes Probieren:
std::vector<HWND> ZOrderWindows; HWND ChildWindow = ::GetTopWindow( ParentPanel->Handle ); while( ChildWindow ) { ZOrderWindows.push_back( ChildWindow ); ChildWindow = ::GetNextWindow( ChildWindow, GW_HWNDNEXT ); }
Damit hast du die Z-Order Reihenfolge aller Kindfenster, über das Handle musst dir dann das zugehörige Label raussuchen.
-
DocShoe schrieb:
Wenn deine Label von TWinControl abgeleitet sind und ein Fensterhandle besitzen kannst du Folgendes Probieren:
std::vector<HWND> ZOrderWindows; HWND ChildWindow = ::GetTopWindow( ParentPanel->Handle ); while( ChildWindow ) { ZOrderWindows.push_back( ChildWindow ); ChildWindow = ::GetNextWindow( ChildWindow, GW_HWNDNEXT ); }
Damit hast du die Z-Order Reihenfolge aller Kindfenster, über das Handle musst dir dann das zugehörige Label raussuchen.
Funktioniert leider auch nicht. Das sind "normale" TLabel-Objekte. TLabel hat aber kein HWND.
Ich habe es nun so gelöst, dass ich parallel zu JvDesignPanel eine Liste anlege und dort die Z-Order selbst verwalte. Ist zwar etwas aufwendig, aber es funktioniert.Vielen Dank und Grüße