Delphi-PRAXiS
Seite 4 von 5   « Erste     234 5      

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 TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst (https://www.delphipraxis.net/192260-tvirtualstringtree-autofitcolumns-erste-spalte-wird-nicht-angepasst.html)

Aviator 6. Apr 2017 09:42

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366580)
Haste vollkommen recht. Siehe mein Edit oben. Hat sich jetzt zeitlich nur überschnitten.

:thumb:

Zitat:

Zitat von Codehunter (Beitrag 1366582)
EDIT:

Zitat:

Zitat von Aviator (Beitrag 1366416)
Dein Abwählen der Node hat intern ein Invalidate ausgelöst. Somit ist der Text auf dem Canvas neu gezeichnet worden und die Textbreite kann ermittelt werden. Der Tree weiß ja nicht, wie er auf deine internen Daten zugreifen soll.

Das ist so nicht ganz richtig. Dann müsste der VST die einmal gezeichnete Textbreite intern puffern. Tut er aber nicht. Tatsächlich holt er sich per GetTextMetrics regelmäßig die tatsächlichen Textbreiten vom jeweiligen DeviceContext und berechnet auch jedesmal neu. Da dürfte es eigentlich gar keine Rolle spielen ob der Node focused ist oder nicht. Welcher Text für die Berechnung verwendet werden soll wird über den Event OnGetText gesteuert. Heißt: Wird GetMaxColumnWidth aufgerufen, dann holt sich VST über OnGetText den passenden String und kalkuliert über GetTextMetrics neu.

Hmm. Von Puffern hatte ich ja auch nichts geschrieben, oder? :roll:
Es ist so, dass bei jeder Änderung des Trees, die die Oberfläche betrifft, ein Invalidate des entsprechenden Bereiches ausgelöst wird. Bei ihm wurde das gemacht, weil er die FocusedNode Property gesetzt hat und somit die "Focused Umrandung" (keine Ahnung wie ich das besser beschreiben soll, diese gepunktete Linie die angibt, dass die Node den Focus hat) auf eine andere Node bzw. auf keine Node neu gezeichnet wurde. Hierdurch wurde dann auch gleich wieder das Berechnen der Spaltenbreite ausgelöst.

Die vorherige Spaltenbreite bzw. die Breite der einzelnen Inhalte muss der Tree ja auch nicht kennen. Er durchläuft lediglich die Nodes und holt sich per GetText Event den Inhalt. Die Breite dieses Textes wird dann Canvas bezogen errechnet. Der größte Wert wird dann als Spaltenbreite übernommen. Dazu kommt dann noch TextMargins + NodeLevel(Node) * Indent usw.

Codehunter 6. Apr 2017 09:58

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Ich denke der gedankliche Fehler hierbei ist, dass der gezeichnete Cell-Content in irgendeiner Weise Auswirkung auf das Ergebnis von GetMaxColumnWidth hätte. Dem ist aber IMHO nicht so. Vielmehr sind gerade solche Dinge wie FocusBorder (das gepunktete Dingens) von ihrem Platzbedarf her von vornherein sozusagen reserviert (teilweise über VST-Properties konfigurierbar). Das einzige wo sich hier die MainColumn von anderen unterscheidet ist der dynamische Teil mit den Indents. Also Node expanded oder nicht, mit Childnodes oder nicht, mit NodeButton oder nicht usw.

Deshalb bin ich auch der Ansicht, dass ein InvalidateNode keine Auswirkungen auf das Ergebnis von GetMaxColumnWidth haben dürfte. Es sei denn, man würde eventgesteuert die externen Daten zwischendurch verändern. Was ja, wie bereits geschrieben, nur anhand des konkreten Projektes nachvollziehbar ist und nicht allein anhand des VST-Codes den wir alle haben.

Aviator 6. Apr 2017 11:11

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366589)
Deshalb bin ich auch der Ansicht, dass ein InvalidateNode keine Auswirkungen auf das Ergebnis von GetMaxColumnWidth haben dürfte.

Das ist vollkommen korrekt. GetMaxColumnWidth() berechnet die maximal benötigte Breite um die NodeTexte darin optimal zu zeichnen. Hierbei kommt es darauf an, ob der Aufrufer die Breite aller NodeTexte und nur die der sichtbaren Nodes möchte.

Ein InvalidateNode führt nur dazu, dass der gesamte Tree neu und dementsprechend die im Hintergrund geänderten Daten auf dem Tree gezeichnet werden. Ein Aufruf vom eigentlichen AutoFitColumns() würde ja praktisch implizit ein Invalidate aufrufen.

TUX_der_Pinguin 6. Apr 2017 11:14

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Codehunter (Beitrag 1366589)
Deshalb bin ich auch der Ansicht, dass ein InvalidateNode keine Auswirkungen auf das Ergebnis von GetMaxColumnWidth haben dürfte. Es sei denn, man würde eventgesteuert die externen Daten zwischendurch verändern. Was ja, wie bereits geschrieben, nur anhand des konkreten Projektes nachvollziehbar ist und nicht allein anhand des VST-Codes den wir alle haben.

Naja
Delphi-Quellcode:
InvalidateNode()
hat aber eine Auswirkung darauf, zumindest soweit das die Berechnung danach funktioniert. Ich weiß doch auch nicht wieso das so ist.
Damit ihr euch das auch ansehen könnt habe ich eine Mini Anwendung (siehe Anhang) gebaut die das Verhalten wie mein eigentliches Projekt aufweist.

madas 6. Apr 2017 11:37

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Tja da hat wohl jemand das "^" beim Zugriff auf Data vergessen.

alt:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data.Name := Data.Name + 'xyz 12345';
      Data.Desc := Data.Desc + 'xyz 12345';
    end;
  end;
so wie es muss:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data^.Name := Data^.Name + 'xyz 12345';
      Data^.Desc := Data^.Desc + 'xyz 12345';
    end;
  end;
Beim OnGetText genau so. Usw.

TUX_der_Pinguin 6. Apr 2017 11:43

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von madas (Beitrag 1366613)
Tja da hat wohl jemand das "^" beim Zugriff auf Data vergessen.

alt:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data.Name := Data.Name + 'xyz 12345';
      Data.Desc := Data.Desc + 'xyz 12345';
    end;
  end;
so wie es muss:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data^.Name := Data^.Name + 'xyz 12345';
      Data^.Desc := Data^.Desc + 'xyz 12345';
    end;
  end;
Beim OnGetText genau so. Usw.

Was heißt vergessen, es funktionierte bisher auch gut ohne. Aber auch mit "^" ändert sich nichts am ursprünglichen Problem, das die erste Spalte nicht angepasst wird wenn ich AutoFitColumns aufrufe.

Codehunter 6. Apr 2017 12:03

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von madas (Beitrag 1366613)
Tja da hat wohl jemand das "^" beim Zugriff auf Data vergessen.

Das hatte ich hier schon bemängelt.

madas 6. Apr 2017 12:04

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366615)
Zitat:

Zitat von madas (Beitrag 1366613)
Tja da hat wohl jemand das "^" beim Zugriff auf Data vergessen.

alt:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data.Name := Data.Name + 'xyz 12345';
      Data.Desc := Data.Desc + 'xyz 12345';
    end;
  end;
so wie es muss:

Delphi-Quellcode:
Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data^.Name := Data^.Name + 'xyz 12345';
      Data^.Desc := Data^.Desc + 'xyz 12345';
    end;
  end;
Beim OnGetText genau so. Usw.

Was heißt vergessen, es funktionierte bisher auch gut ohne. Aber auch mit "^" ändert sich nichts am ursprünglichen Problem, das die erste Spalte nicht angepasst wird wenn ich AutoFitColumns aufrufe.

Bei michse schon. Hast Du es auch überall angepasst?

Codehunter 6. Apr 2017 12:29

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
@TUX_der_Pinguin: Mal dumm gefragt: Verwendest du den VST als Tree oder als Grid? Sprich, brauchst du das ganze Aufklapp-Gedönse überhaupt? Denn wenn nicht, setzt du einfach Header.MainColumn auf 1 und der Fehler ist umgangen.

Jetzt kann ich zumindest das Problem nachvollziehen. Hinzu kommt, die drei "Abkürzungspünktchen" werden auch nicht korrekt angezeigt wenn man die Spalte 0 danach manuell verkleinert. Erst nach einem Invalidate (implizit durch Fokuswechsel) wird der Node richtig initialisiert. Das spräche ja dafür, dass der VST doch irgendwas intern puffert. Sehr seltsam.

Besonders deutlich wird das Problem, wenn man TreeOptions.StringOptions.toShowStaticText setzt. Dann überlappen sich in Spalte 0 sogar die Texte. Das ist Mumpitz. Scheint also ein Käferchen im VST zu sein. :-(

Ich würde vorerst bei meiner Vermutung bleiben, dass da irgendwo im VST eine hartcodierte MainColumn = 0 verblieben ist.

TUX_der_Pinguin 6. Apr 2017 12:31

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von madas (Beitrag 1366619)
Bei michse schon. Hast Du es auch überall angepasst?

Ja habe ich und nach wie vor bleibt die erste Spalte nur 62px breit obwohl 106px sein müssten.
Delphi-Quellcode:
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.StdCtrls;

type
  TMyDataSet = record
    Name: String;
    Desc: String;
  end;
  PMyDataSet = ^TMyDataSet;

type
  TForm2 = class(TForm)
    vstTable: TVirtualStringTree;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure vstTableGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
  Node: PVirtualNode;
  Data: PMyDataSet;
 
begin

  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(0, False))); //62px
  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(1, False))); //77px

  vstTable.BeginUpdate;
 
  Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data^.Name := Data^.Name + 'xyz 12345';
      Data^.Desc := Data^.Desc + 'xyz 12345';
    end;
  end;

  vstTable.EndUpdate;

  //Workaround or musst have?
  //vstTable.InvalidateNode(Node);

  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(0, False))); //62px and 106px with the "workaround"
  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(1, False))); //127px

  vstTable.Header.AutoFitColumns(False, smaAllColumns);
end;

procedure TForm2.FormCreate(Sender: TObject);
var
  Node: PVirtualNode;
  Data: PMyDataSet;
  Index: Integer;
 
begin

  vstTable.NodeDataSize := SizeOf(TMyDataSet);
  vstTable.BeginUpdate;

  for Index := 1 to 10 do
  begin
    Node := vstTable.AddChild(nil);
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data^.Name := IntToStr(Index)+'. Bla bla';
      Data^.Desc := 'Bla bla bla bla';
    end;
  end;

  vstTable.EndUpdate;

  vstTable.Header.AutoFitColumns(False, smaAllColumns);
 
end;

procedure TForm2.vstTableGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data: PMyDataSet;
 
begin
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    case Column of
      0: CellText := Data^.Name;
      1: CellText := Data^.Desc;
    end;
  end;
 
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:21 Uhr.
Seite 4 von 5   « Erste     234 5      

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