AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Event bei Z-Order Änderung o.ä.

Ein Thema von Medium · begonnen am 22. Nov 2012 · letzter Beitrag vom 23. Nov 2012
Antwort Antwort
Seite 2 von 3     12 3      
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#11

AW: Event bei Z-Order Änderung o.ä.

  Alt 22. Nov 2012, 16:56
Hui, das schaut nett aus. Ich glaube, ich hatte auch einen halben Meter zu kurz gedacht vorhin. Schade, dass Komponenten nicht standardmäßig ihren Index in der Parent-Liste bei sich tragen, weil so muss ich teilweise eine ganze Menge durchnudeln um es zu finden, was in jedem Repaint irgendwie unschön aussieht. Praktisch dürfte das glaube ich aber kaum zu merken sein. Probier ich morgen mal umzusetzen, danke!

Nebenfrage:
Die Labels werden mit der Balken-Komponente als Owner erstellt, und bekommen dann den Parent der Balken-Kompo selbst auch als Parent. Tauchen die dann überhaupt in der Controls- bzw. Components-Liste des Formulars auf?

Edit: Rote Box - das sollte diese Frage beantwortet haben
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#12

AW: Event bei Z-Order Änderung o.ä.

  Alt 22. Nov 2012, 17:14
Du durchläufst p.ControlCount (Parent-Beziehung) und greifst dann auf p.Components (Owner-Beziehung) zu. Ist das Absicht?
Wohl eher absichtlich unabsichtlich vertippt.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#13

AW: Event bei Z-Order Änderung o.ä.

  Alt 22. Nov 2012, 17:57
Das kann aber fatal enden, deshalb meine Frage
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#14

AW: Event bei Z-Order Änderung o.ä.

  Alt 22. Nov 2012, 18:19
@DeddyH , nein , danke für den Hinweis, habe es korrigiert.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#15

AW: Event bei Z-Order Änderung o.ä.

  Alt 22. Nov 2012, 18:24
@Sir Rufo

Zitat:
Eigentlich könnte man nach dem Label1.BringToFront die OnPaint Methode verlassen
ich hatte kurz über diese Option nachgedacht, dann aber beschlossen sicherheitshalber in jedem Fall zeichnen zu lassen, für den Fall dass das Label kein intersect mit dem control hat, das Label in der zOrder tiefer liegt und erstmalig gezeichnet wird.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#16

AW: Event bei Z-Order Änderung o.ä.

  Alt 23. Nov 2012, 12:36
Problem gelöst! Allerdings ein Eckchen aufwendiger

Zu erreichen war ja, dass meine Sub-Controls in Z-Richtung immer möglichst nahe an meinem eigentlichen Control (Balken) liegen, zumindest aber so, dass folgendes gewährleistet ist:
- alle Lables müssen immer über dem Balken liegen
- alle Controls, die den Balken verdecken, sollen auch die Labels verdecken
- alle Controls, die durch den Balken verdeckt werden, sollen auch hinter den Labels liegen

Letztlich also so, als wären die Labels (und Skalenstriche, die ich ebenfalls als Subkomponente gebaut habe weil sie ausserhalb liegen sollen) fester Bestandteil des Balkens, und lägen in der selben Z-Plane wie dieser.

Ärgerlich ist mal wieder, dass CodeGear (ja, D2007 ) ja recht freizügig mit private-Deklarationen in der VCL war. Um o.g. zu erreichen, wäre die Methode TControl.SetZOrderPosition() ideal gewesen, aber eben leider private. Gut, kann man sich abgucken und kopieren, aber leider ist auch das darin benötigte Feld "FControls", sowie die Methode InvalidateControl() private. Und die Methode PaletteChanged() ist protected
Also musste ein ekeliger Hack her, womit das ganze erstmal nur gesichert in meiner Version klappt. Das ist zunächst auch okay, weil wir D2007 hier überall haben, und die Komponente nur für den hausinternen Gebrauch ist. Lange Rede, kurzer Pin: Die Hack-Klasse:

Delphi-Quellcode:
type
  // Liegt in der selben Unit wie TKATBalken, wodurch dank Friend-Beziehung Zugriff auf private Felder geht
  // Feld-Layout ist identisch mit dem von TWinControl
  THackedControl = class(TControl)
  private
    FAlignLevel: Word;
    FBevelEdges: TBevelEdges;
    FBevelInner: TBevelCut;
    FBevelOuter: TBevelCut;
    FBevelKind: TBevelKind;
    FBevelWidth: TBevelWidth;
    FBorderWidth: TBorderWidth;
    FPadding: TPadding;
    FBrush: TBrush;
    FDefWndProc: Pointer;
    FDockClients: TList;
    FDockManager: IDockManager;
    FHandle: HWnd;
    FImeMode: TImeMode;
    FImeName: TImeName;
    FObjectInstance: Pointer;
    FParentWindow: HWnd;
    FTabList: TList;
    FControls: TList;
    FWinControls: TList;
    FTabOrder: Integer;
    FTabStop: Boolean;
    FCtl3D: Boolean;
    FShowing: Boolean;
    FUseDockManager: Boolean;
    FDockSite: Boolean;
    FParentCtl3D: Boolean;
    FOnDockDrop: TDockDropEvent;
    FOnDockOver: TDockOverEvent;
    FOnEnter: TNotifyEvent;
    FOnExit: TNotifyEvent;
    FOnGetSiteInfo: TGetSiteInfoEvent;
    FOnKeyDown: TKeyEvent;
    FOnKeyPress: TKeyPressEvent;
    FOnKeyUp: TKeyEvent;
    FOnUnDock: TUnDockEvent;
    FOnAlignInsertBefore: TAlignInsertBeforeEvent;
    FOnAlignPosition: TAlignPositionEvent;
    FMouseInClient: Boolean;
    FMouseControl: TControl;
  public
    function PaletteChanged(Foreground: Boolean): Boolean; override;
  end;

implementation

function THackedControl.PaletteChanged(Foreground: Boolean): Boolean;
begin
  result := inherited PaletteChanged(Foreground);
end;
Dann waren InvalidateControl() und SetZOrderPosition() zu re-implementieren, und zwar so, dass es als Prozedur/Funktion geht, nicht Methode:
Delphi-Quellcode:
procedure InvalidateControl(IsVisible, IsOpaque: Boolean; self: TControl; aParent: THackedControl);
var
  Rect: TRect;

  function BackgroundClipped: Boolean;
  var
    R: TRect;
    List: TList;
    I: Integer;
    C: TControl;
  begin
    Result := True;
    List := aParent.FControls;
    I := List.IndexOf(Self);
    while I > 0 do
    begin
      Dec(I);
      C := List[I];
      with C do
        if C.Visible and (csOpaque in ControlStyle) then
        begin
          IntersectRect(R, Rect, BoundsRect);
          if EqualRect(R, Rect) then Exit;
        end;
    end;
    Result := False;
  end;

begin
  if (IsVisible or (csDesigning in self.ComponentState) and
    not (csNoDesignVisible in self.ControlStyle)) and (self.Parent <> nil) and
    self.Parent.HandleAllocated then
  begin
    Rect := self.BoundsRect;
    InvalidateRect(self.Parent.Handle, @Rect, not (IsOpaque or
      (csOpaque in self.Parent.ControlStyle) or BackgroundClipped));
  end;
end;

procedure SetZOrderPosition(Position: Integer; self: TControl; aParent: THackedControl);
var
  I, Count: Integer;
  ParentForm: TCustomForm;
begin
  if aParent <> nil then
  begin
    I := aParent.FControls.IndexOf(Self);
    if I >= 0 then
    begin
      Count := aParent.FControls.Count;
      if Position < 0 then Position := 0;
      if Position >= Count then Position := Count - 1;
      if Position <> I then
      begin
        aParent.FControls.Delete(I);
        aParent.FControls.Insert(Position, Self);
        InvalidateControl(self.Visible, True, self, aParent);
        if not (csLoading in self.ComponentState) then
        begin
          ParentForm := ValidParentForm(Self);
          if csPalette in ParentForm.ControlState then
            THackedControl(ParentForm).PaletteChanged(True);
        end;
      end;
    end;
  end;
end;
Und dann meine Helfer-Methoden:
Delphi-Quellcode:
function GetControlParentIndex(aControl: TControl): Integer;
var
  i: Integer;
begin
  result := -1;
  if not Assigned(aControl.Parent) then Exit;
  for i := 0 to aControl.Parent.ControlCount-1 do
  begin
    if aControl.Parent.Controls[i] = aControl then
    begin
      result := i;
      Exit;
    end;
  end;
end;

function RectsOverlap(aRect1, aRect2: TRect): Boolean;
begin
  result := not((aRect1.Right < aRect2.Left) or (aRect1.Left > aRect2.Right) or (aRect1.Bottom < aRect2.Top) or (aRect1.Top > aRect2.Bottom));
end;

procedure TKATBalken.CorrectSubControlZOrder(aSubControl: TControl; aBaseIndex: Integer);
var
  i, subIndex: Integer;
begin
  subIndex := GetControlParentIndex(aSubControl);
  if subindex<0 then Exit;

  if subIndex<aBaseIndex then
  begin
    SetZOrderPosition(aBaseIndex+1, aSubControl, THackedControl(Parent));
  end
  else
  begin
    for i := 0 to Parent.ControlCount-1 do
    begin
      if RectsOverlap(Parent.Controls[i].BoundsRect, aSubControl.BoundsRect) then
      begin
        if ((i>aBaseIndex) and (i<subIndex)) or ((i<aBaseIndex) and (i>subIndex)) then
        begin
          SetZOrderPosition(aBaseIndex+1, aSubControl, THackedControl(Parent));
          Exit;
        end;
      end;
    end;
  end;
end;

procedure TKATBalken.CorrectZOrders;
var
  i, selfIndex: Integer;
begin
  selfIndex := GetControlParentIndex(self);
  CorrectSubControlZOrder(ValueLabel, selfIndex);
  CorrectSubControlZOrder(ScaleLeft, selfIndex);
  CorrectSubControlZOrder(ScaleRight, selfIndex);
  for i := 0 to High(ScaleLabelsLeft) do
  begin
    CorrectSubControlZOrder(ScaleLabelsLeft[i], selfIndex);
    CorrectSubControlZOrder(ScaleLabelsRight[i], selfIndex);
  end;
end;

procedure TKATBalken.Paint;
begin
  inherited;
  CorrectZOrders;
  // Restlicher Code...
Mit "CorrectZOrders" werden dann genau die o.g. Bedingungen hergestellt. Vor allem aber wird nichts geändert wenn diese schon bestehen, so dass dies nicht mehr zu einer Endlosrekursion wird. Zwar finde ich das ganze im Paint noch immer deutlich zu oft, zumal dann ja zumindest immer noch die Prüfungen laufen, aber es scheint einfach keine bessere Stelle zu geben. Läuft prima, auch auf ziemlich gut gefüllten Forms!

Danke nochmals an alle
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (23. Nov 2012 um 12:40 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#17

AW: Event bei Z-Order Änderung o.ä.

  Alt 23. Nov 2012, 13:22
ich will ja nicht unken, aber ich bin immer noch der Meinung dass es sinnvoller wäre alles in einer Komponente abzufackeln, Alignments, Ausrichtungen und Längen lassen sich ja auch berechnen.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#18

AW: Event bei Z-Order Änderung o.ä.

  Alt 23. Nov 2012, 13:30
Nicht, wenn die Breite der Skalentexte zur Runtime erst bekannt wird. Dann ist das Control längst platziert, und ich will im Code des eigentlichen Projektes keine Fetzen rumfliegen haben, die die Neuausrichtung machen müssen. Zudem ist es so auch noch etwas gefälliger im Umgang im Designer, da der ja doch recht große Freiraum zwischen den Skalentexten nicht mehr zum Balken gehört, und man die nicht mehr so oft aus Versehen erwischt, wenn man eigentlich ein anderes in der näheren Umgebung haben wollte. Für unsere Zwecke erscheint mir das zunächst als guter Weg, es sei denn da hat noch jemand konkrete Killer-Argumente die ich bisher nicht bedacht habe.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#19

AW: Event bei Z-Order Änderung o.ä.

  Alt 23. Nov 2012, 14:49
Ich mag TLabeledEdit nicht, weil es sich völlig anders verhält als andere Controls.

Es beansprucht mehr Platz als es die Abfrage (Width,Height) vermuten lässt.
Align ist auch nicht sinnvoll möglich.

Es ist also ein Konstrukt, was den Benutzer in einigen Punkten überrascht, und solche Ü-Eier gelten im Allgemeinen als schlechter Code.

Einen Vorteil kann ich da auch nicht entdecken, nur Faulheit.

Es geht nicht darum, dass eine Komponente TLabeledEdit unnütz ist, sondern darum, dass diese schlecht implementiert ist. Die Gründe dafür sind mir egal weil man sich alles schönreden kann.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#20

AW: Event bei Z-Order Änderung o.ä.

  Alt 23. Nov 2012, 15:20
Nun, da das Teil nur für einen sehr speziellen Zweck eingesetzt wird (Prozessvisualisierung, ähnlich WinCC, nur dass wir quasi Formulare+Kompos dazu missgebrauchen), bei dem Alignment ohnehin bestenfalls zu einem unvorhersehbarem Verhalten führen würde, da so viele Einzelteile und Verbindungen zwischen diesen existieren. Praktisch nicht machbar, also auch kein Thema. Vorläufig bin ich auch der einzige, der damit arbeitet. Die Lage der Teile muss auch im Code niemals angefasst werden. Es mag nicht deinem Geschmack entsprechen, aber für Einsatzgebiet empfinde ich das als sehr praktisch. Diese Subjektivität ist für mich jetzt kein Killer-Argument
Warum ist Faulheit schlecht? Bzw. an welcher Stelle empfindest du das als faul? Wäre es dir dann lieber in ~10 Formularen mit je 6-30 solcher Balken alle Beschriftungen von Hand mit Labels zu machen, und diese dann auch noch von Hand auf Werte aus einer DB zu setzen UND noch korrekt zu positionieren da die Zahlenbreite sich ggf. ändert? Da es für alle Balken gleich abläuft, ist das so doch der Inbegriff von Modularität und funktional orientierter Kapselung. Ich kann leider echt nicht folgen.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:32 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