Delphi-PRAXiS
Seite 1 von 2  1 2      

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)

TUX_der_Pinguin 4. Apr 2017 07:55

TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Hallo,

ich arbeite schon lange mit der Komponente TVirtualStringTree aber das Verhalten habe ich bisher noch nicht erlebt. Aber was passiert, ich versuche mit 'AutoFitColumns' die Spalten an den Inhalt bzw. die Überschrift anzupassen aber in einer Situation wird partout die erste Spalte ignoriert und erst die darauf folgenden Spalten korrekt angepasst.

Wie sonst auch führe ich nach dem Ändern eines Eintrags folgenden Befehl aus um alle Spalten anzupassen, aber die erste Spalte bleibt unverändert und wird nicht vergrößert.
Delphi-Quellcode:
vstTable.Header.AutoFitColumns(False, smaUseColumnOption, 0, vstTable.Header.Columns.Count-1);
Das kuriose ist das es beim ersten befüllen der Komponente klappt nur nicht wenn ich Einträge ändern will. Ich hoffe jemand von euch hat einen Tipp. Leider kann ich nicht ohne das halbe Projekt online zu stellen euch mehr Quellcode zeigen.

Aviator 4. Apr 2017 09:05

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Hallo Tux,

ich nutze die Funktion zwar nicht da ich immer selbst die Breite der Columns angebe, habe aber im SourceCode gesehen, dass vor dem Ausführen des Sizing das Event
Delphi-Quellcode:
OnBeforeAutoFitColumns
ausgelöst wird (wenn denn ein EventHandler existiert).

Hier gibt es einen Parameter
Delphi-Quellcode:
var SmartAutoFitType: TSmartAutoFitType
. Setzt du diesen an irgendeiner Stelle auf einen anderen Wert oder nutzt du das Event überhaupt?

Wenn nicht, dann steht (wie du es beim Aufruf auch übergibst) die Option auf
Delphi-Quellcode:
smaUseColumnOption
.

Und das ist der Knackpunkt. Hast du auch bei deiner ersten Column die Option in den ColumnOptions eingeschaltet?

TUX_der_Pinguin 4. Apr 2017 09:30

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Aviator (Beitrag 1366343)
Hallo Tux,

ich nutze die Funktion zwar nicht da ich immer selbst die Breite der Columns angebe, habe aber im SourceCode gesehen, dass vor dem Ausführen des Sizing das Event
Delphi-Quellcode:
OnBeforeAutoFitColumns
ausgelöst wird (wenn denn ein EventHandler existiert).

Hier gibt es einen Parameter
Delphi-Quellcode:
var SmartAutoFitType: TSmartAutoFitType
. Setzt du diesen an irgendeiner Stelle auf einen anderen Wert oder nutzt du das Event überhaupt?

Wenn nicht, dann steht (wie du es beim Aufruf auch übergibst) die Option auf
Delphi-Quellcode:
smaUseColumnOption
.

Und das ist der Knackpunkt. Hast du auch bei deiner ersten Column die Option in den ColumnOptions eingeschaltet?

Delphi-Quellcode:
OnBeforeAutoFitColumns
verwende ich nicht in dem Projekt, das komische ist es das ja eigentlich alles funktioniert und richtig ist nur beim Ändern eines Eintrags will er einfach nicht die erste Spalte anpassen. Füge ich einen weiteren Eintrag hinzu, wird die Spalte korrekt angepasst.

Delphi-Quellcode:
var
  Node: PVirtualNode;
  Data: PDataset;

begin
Node := vstTable.FocusedNode;
if Assigned(Node) then
begin
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data.Name := edtName.Text; //1. Spalte, hier wird eine längere Bezeichnung eingegeben
    Data.Type := edtType.Text; //2. Spalte, hier wird ebenfalls etwas längeres Eingetragen
  end;
end;

//Spalten anpassen...
vstTable.Header.AutoFitColumns(False, smaUseColumnOption, 0, vstTable.Header.Columns.Count-1);
Jetzt passiert folgendes, Spalte 2 hat die korrekte und angepasste Breite und Spalte 1 bleibt unverändert und somit zu klein. Dazu kommt noch das erst wenn ich auf eine andere Zeile wechsle werden in der 1. Spalte die drei Punkte gezeichnet.

madas 4. Apr 2017 09:54

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366346)
Zitat:

Zitat von Aviator (Beitrag 1366343)
Hallo Tux,

ich nutze die Funktion zwar nicht da ich immer selbst die Breite der Columns angebe, habe aber im SourceCode gesehen, dass vor dem Ausführen des Sizing das Event
Delphi-Quellcode:
OnBeforeAutoFitColumns
ausgelöst wird (wenn denn ein EventHandler existiert).

Hier gibt es einen Parameter
Delphi-Quellcode:
var SmartAutoFitType: TSmartAutoFitType
. Setzt du diesen an irgendeiner Stelle auf einen anderen Wert oder nutzt du das Event überhaupt?

Wenn nicht, dann steht (wie du es beim Aufruf auch übergibst) die Option auf
Delphi-Quellcode:
smaUseColumnOption
.

Und das ist der Knackpunkt. Hast du auch bei deiner ersten Column die Option in den ColumnOptions eingeschaltet?

Delphi-Quellcode:
OnBeforeAutoFitColumns
verwende ich nicht in dem Projekt, das komische ist es das ja eigentlich alles funktioniert und richtig ist nur beim Ändern eines Eintrags will er einfach nicht die erste Spalte anpassen. Füge ich einen weiteren Eintrag hinzu, wird die Spalte korrekt angepasst.

Delphi-Quellcode:
var
  Node: PVirtualNode;
  Data: PDataset;

begin
Node := vstTable.FocusedNode;
if Assigned(Node) then
begin
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data.Name := edtName.Text; //1. Spalte, hier wird eine längere Bezeichnung eingegeben
    Data.Type := edtType.Text; //2. Spalte, hier wird ebenfalls etwas längeres Eingetragen
  end;
end;

//Spalten anpassen...
vstTable.Header.AutoFitColumns(False, smaUseColumnOption, 0, vstTable.Header.Columns.Count-1);
Jetzt passiert folgendes, Spalte 2 hat die korrekte und angepasste Breite und Spalte 1 bleibt unverändert und somit zu klein. Dazu kommt noch das erst wenn ich auf eine andere Zeile wechsle werden in der 1. Spalte die drei Punkte gezeichnet.

Hm, also intern wird für den Aufruf von AutoFitColumns die Position der Spalte benutzt:

Delphi-Quellcode:
AutoFitColumns(True, smaUseColumnOption, FColumns[FColumns.FTrackIndex].FPosition, FColumns[FColumns.FTrackIndex].FPosition)
Diese muss jedoch nicht immer zwingend mit dem ColumnIndex übereinstimmen. Vielleicht liegt es ja daran.
Ansonsten kann es fast nur noch an den Optionen für die Spalte bzw. den Tree liegen

madas

Aviator 4. Apr 2017 09:59

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Hast du dir denn auch die ColumnOptions der ersten Column angeschaut? Ist dort die entsprechende Option aktiviert?

TUX_der_Pinguin 4. Apr 2017 10:03

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Aviator (Beitrag 1366349)
Hast du dir denn auch die ColumnOptions der ersten Column angeschaut? Ist dort die entsprechende Option aktiviert?

Ich weiß zwar nicht welche Option du meinst, aber müsste das dann nicht generell funktionieren bzw. generell nicht funktionieren. Weil es klappt ja beim hinzufügen von neuen Einträgen, nur ändern geht nicht.

madas 4. Apr 2017 10:06

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366350)
Zitat:

Zitat von Aviator (Beitrag 1366349)
Hast du dir denn auch die ColumnOptions der ersten Column angeschaut? Ist dort die entsprechende Option aktiviert?

Ich weiß zwar nicht welche Option du meinst, aber müsste das dann nicht generell funktionieren bzw. generell nicht funktionieren. Weil es klappt ja beim hinzufügen von neuen Einträgen, nur ändern geht nicht.

Delphi-Quellcode:
DefaultColumnOptions = [coAllowClick, coDraggable, coEnabled, coParentColor, coParentBidiMode, coResizable, coShowDropmark, coVisible, coAllowFocus, coEditable];
nix
Delphi-Quellcode:
coSmartResize
zu sehen.

TUX_der_Pinguin 4. Apr 2017 10:11

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von madas (Beitrag 1366351)
Delphi-Quellcode:
DefaultColumnOptions = [coAllowClick, coDraggable, coEnabled, coParentColor, coParentBidiMode, coResizable, coShowDropmark, coVisible, coAllowFocus, coEditable];
nix
Delphi-Quellcode:
coSmartResize
zu sehen.

Selbst wenn ich coSmartResize hinzufüge ändert sich am Verhalten nichts, Spalte 1 bleibt Stur und das komische ist sie wird ja nicht mals neu gezeichnet, erst wenn man das manuell anstößt mit
Delphi-Quellcode:
vstTable.invalidate
Ändere ich den Inhalt z.B. in Spalte 2 wird die Spalte sofort angepasst, neu gezeichnet und alles ist wunderbar.

madas 4. Apr 2017 10:23

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366352)
Zitat:

Zitat von madas (Beitrag 1366351)
Delphi-Quellcode:
DefaultColumnOptions = [coAllowClick, coDraggable, coEnabled, coParentColor, coParentBidiMode, coResizable, coShowDropmark, coVisible, coAllowFocus, coEditable];
nix
Delphi-Quellcode:
coSmartResize
zu sehen.

Selbst wenn ich coSmartResize hinzufüge ändert sich am Verhalten nichts, Spalte 1 bleibt Stur und das komische ist sie wird ja nicht mals neu gezeichnet, erst wenn man das manuell anstößt mit
Delphi-Quellcode:
vstTable.invalidate
Ändere ich den Inhalt z.B. in Spalte 2 wird die Spalte sofort angepasst, neu gezeichnet und alles ist wunderbar.

Hm. Dann könnte eventuell nur noch durch irgend etwas die AutoFit-Operation gecancelt werden.

Delphi-Quellcode:
procedure DoAutoFitColumn(Column: TColumnIndex);

  begin
    with FColumns do
      if ([coResizable, coVisible] * Items[FPositionToIndex[Column]].FOptions = [coResizable, coVisible]) and
            DoBeforeAutoFitColumn(FPositionToIndex[Column], SmartAutoFitType) and not TreeView.OperationCanceled then
      begin
        if Animated then
          AnimatedResize(FPositionToIndex[Column], Treeview.GetMaxColumnWidth(FPositionToIndex[Column],
            GetUseSmartColumnWidth(FPositionToIndex[Column])))
        else
          FColumns[FPositionToIndex[Column]].Width := Treeview.GetMaxColumnWidth(FPositionToIndex[Column],
            GetUseSmartColumnWidth(FPositionToIndex[Column]));

        DoAfterAutoFitColumn(FPositionToIndex[Column]);
      end;
  end;
not TreeView.OperationCanceled

Binde doch die Unit einfach mal in Dein Projekt ein und debugge das Ganze.

Viel Erfolg.

madas

TUX_der_Pinguin 4. Apr 2017 10:35

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Es wird immer lustiger, ich gucke gerade was den
Delphi-Quellcode:
AutoFitColumns
so tatsächlich macht.

Delphi-Quellcode:
  ShowMessage(vstTable.GetMaxColumnWidth(0, True).ToString); //Hier ist die Spalte 69px breit
  ShowMessage(vstTable.GetMaxColumnWidth(1, True).ToString); //Hier ist die Spalte 49px breit

  Node := vstTable.FocusedNode;
  if Assigned(Node) then
  begin
    Data := vstTable.GetNodeData(Node);
    if Assigned(Data) then
    begin
      Data.Name := 'skljglsjfgskjfsldjfksjlfkjsd'; //neuer Text ist länger als alle anderen
      Data.Type := 'dfkgjdkjgfklgjdkjgkljgkdjkkgdljgkdjgdgfdgld'; //neuer Text ist länger als alle anderen
    end;
  end;

  ShowMessage(vstTable.GetMaxColumnWidth(0, True).ToString); //Hier ist die Spalte 69px breit -> FALSCH
  ShowMessage(vstTable.GetMaxColumnWidth(1, True).ToString); //Hier ist die Spalte 129px breit -> RICHTIG
Irgendwie scheint
Delphi-Quellcode:
GetMaxColumnWidth
beim Ändern des Inhaltes von Spalte 1 zu versagen ..

madas 4. Apr 2017 10:56

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Dann mache die Berechnung doch selber. :)
Wir machen das bei uns so (ist ein Frame mit einem VST drauf, der Tree als Name hat):

Delphi-Quellcode:
function TFrameVST.GetMaxHeaderWidth(const Column: TColumnIndex): Integer;
var
  col: TVirtualTreeColumn;
  Size: TSize;
begin
  col := Tree.Header.Columns[Column];
  Result := 2 * col.Margin;
  if (Length(col.Text) > 0) then
  begin
    Tree.Canvas.Font := Tree.Header.Font;
    GetTextExtentPoint32W(Tree.Canvas.Handle, PWideChar(col.Text), Length(col.Text), Size);
    Inc(Result, Size.cx + 4);
  end;
  if (hoShowImages in Tree.Header.Options)and(Assigned(Tree.Header.Images)) then
    Inc(Result,(Tree.Header.Images.Width + col.Spacing));
  if (hoShowSortGlyphs in Tree.Header.Options)and(Tree.Header.SortColumn = Column) then
  begin
    Inc(Result, 20); // Platz für Sortimage
    if (col.CaptionAlignment = taCenter) then
      Inc(Result, 14); // mehr Platz für Sortimage berücksichtigen
  end;
  if Result < col.MinWidth then
    Result := col.MinWidth;
  if Result > col.MaxWidth then
    Result := col.MaxWidth;
end;

procedure TFrameVST.AutoFitColumn(Column: TColumnIndex);
var
  cWidth, hWidth: Integer;
begin
  if [coResizable, coVisible] * Tree.Header.Columns[Column].Options = [coResizable, coVisible] then
  begin
    if (hoVisible in Tree.Header.Options) then
    begin    
      hWidth := GetMaxHeaderWidth(Column);
      cWidth := Tree.GetMaxColumnWidth(Column);
      if cWidth < hWidth then
        cWidth := hWidth;
      if cWidth > Tree.Header.Columns[Column].MaxWidth then
        cWidth := Tree.Header.Columns[Column].MaxWidth;
      Tree.Header.Columns[Column].Width := cWidth;
    end;
  end;
end;

procedure TFrameVST.AutoFitColumns;
var
  Column: TColumnIndex;
  merkCursor: TCursor;
begin
  merkCursor := Screen.Cursor;
  Tree.BeginUpdate;
  try
    Screen.Cursor := crHourGlass;
    for Column := 0 to Tree.Header.Columns.Count-1 do
      AutoFitColumn(Column);
  finally
    Screen.Cursor := merkCursor;
    Tree.EndUpdate;
  end;
end;

FmerkOnBeforeCellPaint: TVTBeforeCellPaintEvent;

procedure TFrameVST.TreeBeforeGetMaxColumnWidth(Sender: TVTHeader; Column: TColumnIndex; var UseSmartColumnWidth: Boolean);
begin
  if Assigned(Tree.OnBeforeCellPaint) then
  begin
    FmerkOnBeforeCellPaint := Tree.OnBeforeCellPaint;
    Tree.OnBeforeCellPaint := nil;
  end;
end;

procedure TFrameVST.TreeAfterGetMaxColumnWidth(Sender: TVTHeader; Column: TColumnIndex; var MaxWidth: Integer);
begin
  if Assigned(FmerkOnBeforeCellPaint) then
  begin
    Tree.OnBeforeCellPaint := FmerkOnBeforeCellPaint;
    FmerkOnBeforeCellPaint := nil;
  end;
end;

Codehunter 4. Apr 2017 10:57

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Am Rande bemerkt: Du könntest das auch ein bisschen abkürzen, weil GetNodeData Failsafe ist:

Delphi-Quellcode:
  Node := vstTable.FocusedNode;
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data.Name := 'skljglsjfgskjfsldjfksjlfkjsd'; //neuer Text ist länger als alle anderen
    Data.Type := 'dfkgjdkjgfklgjdkjgkljgkdjkkgdljgkdjgdgfdgld'; //neuer Text ist länger als alle anderen
  end;
Davon abgesehen, du hast nicht zufällig Header.AutoSizeIndex auf 0 stehen?

TUX_der_Pinguin 4. Apr 2017 11:03

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von madas (Beitrag 1366361)
Dann mache die Berechnung doch selber. :)
Wir machen das bei uns so (ist ein Frame mit einem VST drauf, der Tree als Name hat):

Delphi-Quellcode:
procedure TFrameVST.AutoFitColumn(Column: TColumnIndex);
var
  cWidth, hWidth: Integer;
begin
  if [coResizable, coVisible] * Tree.Header.Columns[Column].Options = [coResizable, coVisible] then
  begin
    if (hoVisible in Tree.Header.Options) then
    begin    
      hWidth := GetMaxHeaderWidth(Column);
      cWidth := Tree.GetMaxColumnWidth(Column);
      if cWidth < hWidth then
        cWidth := hWidth;
      if cWidth > Tree.Header.Columns[Column].MaxWidth then
        cWidth := Tree.Header.Columns[Column].MaxWidth;
      Tree.Header.Columns[Column].Width := cWidth;
    end;
  end;
end;

Irgendwas scheint bei mir noch anders zu sein, den ihr verwendet ja auch
Delphi-Quellcode:
GetMaxColumnWidth
, und das führt bei mir ja zu einem Falschen Ergebnis.

Wäre es möglich mir die Optionen und Eigenschaften der Komponente zu zeigen, also das was in der *.dfm Datei steht? Damit ich das mit meinen Eigenschaften vergleichen kann.

Codehunter 4. Apr 2017 11:05

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Nochwas: müssten das nicht dereferenzierte Pointer sein?
Delphi-Quellcode:
  Node := vstTable.FocusedNode;
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data^.Name := 'skljglsjfgskjfsldjfksjlfkjsd'; //neuer Text ist länger als alle anderen
    Data^.Type := 'dfkgjdkjgfklgjdkjgkljgkdjkkgdljgkdjgdgfdgld'; //neuer Text ist länger als alle anderen
  end;

TUX_der_Pinguin 4. Apr 2017 11:06

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366362)
Am Rande bemerkt: Du könntest das auch ein bisschen abkürzen, weil GetNodeData Failsafe ist:

Delphi-Quellcode:
  Node := vstTable.FocusedNode;
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data.Name := 'skljglsjfgskjfsldjfksjlfkjsd'; //neuer Text ist länger als alle anderen
    Data.Type := 'dfkgjdkjgfklgjdkjgkljgkdjkkgdljgkdjgdgfdgld'; //neuer Text ist länger als alle anderen
  end;
Davon abgesehen, du hast nicht zufällig Header.AutoSizeIndex auf 0 stehen?

Danke für den Tipp, und nein AutoSizeIndex steht nicht auf 0 es steht auf -1

Zitat:

Zitat von Codehunter (Beitrag 1366362)
Nochwas: müssten das nicht dereferenzierte Pointer sein?

Ähm... glaube nicht aber sagen wir mal so es funktioniert ja, zumindest der Zugriff nicht die Spaltenbreite ;-) Und selbst mit
Delphi-Quellcode:
Data^.Name :=
ändert sich nichts.

Codehunter 4. Apr 2017 11:12

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zeig mal bitte die Deklaration von PDataSet. Mein Verdacht ist, weil ich das beim VST schon mehrfach hatte: Speichersalat wegen wildem Pointergeschubse.

EDIT: Den Kommentar in der Implementierung von GetMaxColumnWidth hast du gesehen?
Delphi-Quellcode:
// This method determines the width of the largest node in the given column.
// If UseSmartColumnWidth is True then only the visible nodes which are in view will be considered
// Note: If UseSmartColumnWidth is False then every visible node in the tree will be initialized contradicting so
//       the virtual paradigm.
So wie du das machst bezieht sich die Kalkulation nur auf die im Viewport sichtbaren Nodes. Falls der betreffende Node aber gerade out-of-Scroll ist oder Collapsed, dann wird der nicht einbezogen.

TUX_der_Pinguin 4. Apr 2017 11:34

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Bei PDataset handelt es sich um einen Zeiger auf eine Klasse.
Delphi-Quellcode:
TDataset = class(TObject)
  private
    FName: String;
    FType: String;
  public
    constructor Create;
    destructor Destroy; override;
    property Name: String read FName write FName;
    property Type: String read FType write FType;

  end;
  PDataset = ^TDataset;
Beim befüllen bzw. hinzufügen von Einträgen wird entsprechend das Objekt erstellt
Delphi-Quellcode:
Node := vstTable.AddChild(nil);
if Assigned(Node) then
begin
  Data := vstTable.GetNodeData(Node);
  if Assigned(Data) then
  begin
    //init
    Data^ := TDataset.Create;
     
    Data.Name := 'bla bla';
    Data.Type := 'bla bla';
     
  end;
end;
Die Zelle die ich versuche zu ändern ist nicht nur sichtbar sondern hat auch noch den Focus.

Codehunter 4. Apr 2017 11:47

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Oh je....

Ich ahnte es. Speichersalat.

Ich habe zumindest noch nie gesehen, dass man den VST mit Klasseninstanzen statt Records verwendet. Habe es auch noch nie probiert, weil alle Beispiele und Tutorials die ich so kenne alle auf Records basieren.

Ändere die Deklaration von TDataSet doch bitte mal testweise so um:
Delphi-Quellcode:
TDataset = record
  Name: String;
  Type: String;
end;

Aviator 4. Apr 2017 11:49

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366378)
Oh je....

Ich ahnte es. Speichersalat.

Ich habe zumindest noch nie gesehen, dass man den VST mit Klasseninstanzen statt Records verwendet. Habe es auch noch nie probiert, weil alle Beispiele und Tutorials die ich so kenne alle auf Records basieren.

Ne nix Speichersalat. Klappt wunderbar. Mache ich auch immer so (seit Jahren) und es hat noch nie Probleme gegeben. Ich speichere mir meine Objekte allerdings immer noch in einer ObjectList<T> und gebe dem NodeObject dann nur noch eine Referenz zur Object-Instanz.

Also daran ist nichts falsch und es ist auch definitiv nicht die Ursache warum das AutoSizing nicht funktioniert.

Codehunter 4. Apr 2017 12:05

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Aviator (Beitrag 1366380)
Ne nix Speichersalat. Klappt wunderbar. Mache ich auch immer so (seit Jahren) und es hat noch nie Probleme gegeben. Ich speichere mir meine Objekte allerdings immer noch in einer ObjectList<T> und gebe dem NodeObject dann nur noch eine Referenz zur Object-Instanz.

Naja, ich mache sowas ähnliches:
Delphi-Quellcode:
type
  TNodeData = record
    ObjRef: Pointer;
  end;
Und dann da die Klasseninstanzen angehangen.

Aber so wie hier gemacht, stelle ich mir das seltsam vor. GetNodeData erzeugt erst eine neue Variableninstanz vom Typ Pointer mit der Größe von [was eigentlich? -> OnGetNodeDataSize], dann lässt man den Speichermanager durch TDataSet.Create eine neue Klasseninstanz auf der selben Adresse erzeugen und dann überlässt man das der internen Speicherverwaltung vom VST?

Hmm, ok, ich arbeite immer noch mit der letzten Lischke-Version vom VST. Vielleicht sind neuere dahingehend flexibler. Wie gesagt, ich habe das nie so gemacht.

NACHTRAG:

Um wieder auf das eigentliche Problem zurück zu kommen: GetMaxColumnWidth arbeitet ja intern mit Canvas.TextWidth. Wenn man da jetzt dummerweise nicht den String sondern eine getypcastete Referenz auf den String rein wirft, erhält man recht gern den Effekt, dass TextWidth immer identische Werte ausspuckt. Würde also theoretisch das Problem erklären.

TUX_der_Pinguin 4. Apr 2017 12:31

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366383)
NACHTRAG:

Um wieder auf das eigentliche Problem zurück zu kommen: GetMaxColumnWidth arbeitet ja intern mit Canvas.TextWidth. Wenn man da jetzt dummerweise nicht den String sondern eine getypcastete Referenz auf den String rein wirft, erhält man recht gern den Effekt, dass TextWidth immer identische Werte ausspuckt. Würde also theoretisch das Problem erklären.

Ja aber warum nur bei der ersten Spalte und nicht bei allen, das finde ich ja das total merkwürdige an der Sache.

Jetzt habe mich mal für Spaß die Option
Delphi-Quellcode:
vstTable.Header.MainColumn
auf 1 gesetzt und siehe da es funktioniert, die erste und auch die zweite Spalte werden angepasst. So bald aber MainColumn wieder auf 0 oder -1 steht klappt es nicht.

TUX_der_Pinguin 4. Apr 2017 13:39

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Ok, ich verstehe es zwar nicht so ganz aber ich glaube ich habe die Ursache gefunden. Weil die Zeile ja immer noch den Focus hat und ausgewählt ist wird wohl intern der Inhalt für die erste Spalte geändert so das bei der Berechnung der maximalen Breite keine Veränderung erkannt wird. Hebe ich die Auswahl vor dem Ändern auf klappt es und auch die erste Spalte wird korrekt geändert.

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

  vstTable.ClearSelection; //Auswahl aufheben
 
  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;

  vstTable.FocusedNode := Node; //Zeile wieder auswählen
  vstTable.Selected[Node] := True; //und markieren

  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(0, False))); //106px
  ShowMessage(IntToStr(vstTable.GetMaxColumnWidth(1, False))); //127px

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

TUX_der_Pinguin 4. Apr 2017 14:16

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Nachtrag:

An Stelle davon die Auswahl aufzuheben und wieder zu setzen kann man auch per
Delphi-Quellcode:
vstTable.InvalidateNode(Node);
den einzelnen Knoten aktualisieren und dann klappt auch wieder die Berechnung. Trotz alle dem scheint mir das Verhalten etwas merkwürdig zu sein, aber gut mit dieser Lösung kann ich arbeiten.

Vielen Dank bei allen Beteiligten, wünsche euch noch einen schönen Tag ;-)

Aviator 4. Apr 2017 15:24

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Hallo TUX,

nachdem du das jetzt so sagst erinnere ich mich an etwas. Ich hatte mir mal die Funktion angeschaut wie der VST denn die Berechnung macht ab wann er den Text abschneiden soll. Und das kann er ja nur dann wissen, wenn er die Font Größe und die Breite des Textes auf dem entsprechenden Canvas kennt.

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 manuelle Invalidate musst du aufrufen, da du, ohne das Wissen des Trees, die internen Daten veränderst. Würdest du das über einen Editor machen, dann wüsste er es und würde automatisch ein Invalidate veranlassen.

Also von daher ganz logisch! :thumb:

TUX_der_Pinguin 4. Apr 2017 15:35

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Aviator (Beitrag 1366416)
Hallo TUX,

nachdem du das jetzt so sagst erinnere ich mich an etwas. Ich hatte mir mal die Funktion angeschaut wie der VST denn die Berechnung macht ab wann er den Text abschneiden soll. Und das kann er ja nur dann wissen, wenn er die Font Größe und die Breite des Textes auf dem entsprechenden Canvas kennt.

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 manuelle Invalidate musst du aufrufen, da du, ohne das Wissen des Trees, die internen Daten veränderst. Würdest du das über einen Editor machen, dann wüsste er es und würde automatisch ein Invalidate veranlassen.

Also von daher ganz logisch! :thumb:

Im Grunde ist es logisch da gebe ich dir recht, nur müsste es dann nicht für alle Spalten NICHT funktionieren. :gruebel:

Codehunter 6. Apr 2017 08:52

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Die Spalte 0 ist insofern etwas besonderes weil dort der Baum, die Nodebuttons, Treelines usw. gezeichnet werden. Da wird intern beim VST sehr viel anders gemacht als bei anderen Spalten. Weil es nicht immer die Möglichkeit gab, die MainColumn zu verstellen, also in früheren VST-Versionen mal hartcodiert "0" war, möchte ich auch nicht ausschließen dass irgendwo noch so eine "harte Null" überlebt hat.

Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366400)
Weil die Zeile ja immer noch den Focus hat und ausgewählt ist wird wohl intern der Inhalt für die erste Spalte geändert so das bei der Berechnung der maximalen Breite keine Veränderung erkannt wird. Hebe ich die Auswahl vor dem Ändern auf klappt es und auch die erste Spalte wird korrekt geändert.

Das ist eher unwahrscheinlich. Der VST ändert eigentlich nicht den Textinhalt von Spalten. Der liest das eigentlich nur aus deinen externen Daten (wie gesagt bei mir immer Records) und pinselt es dann auf die Canvas. Da würde ich vielleicht mehr etwas in der Richtung OnChange vermuten, dass sich externe Dateninhalte bei der Fokussierung eines Node ändern. Mit dem Umweg über das Löschen und Resetten der Selection löst du übrigens OnChange "künstlich" noch einmal aus, das bitte bedenken.

Gerade weil der VST so ein Featuremonster ist, hat man eben auch 1001 Möglichkeiten, im Zusammenspiel mit der externen Logik Bugs einzubauen. Das Herumraten bringt eigentlich nicht sehr viel, man kann das wahrscheinlich nur am konkreten Code debuggen.

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.

TUX_der_Pinguin 6. Apr 2017 08:57

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366571)
Die Spalte 0 ist insofern etwas besonderes weil dort der Baum, die Nodebuttons, Treelines usw. gezeichnet werden. Da wird intern beim VST sehr viel anders gemacht als bei anderen Spalten. Weil es nicht immer die Möglichkeit gab, die MainColumn zu verstellen, also in früheren VST-Versionen mal hartcodiert "0" war, möchte ich auch nicht ausschließen dass irgendwo noch so eine "harte Null" überlebt hat.

Das habe ich mir auch schon gedacht das die Spalte 0 doch noch etwas besonders ist und deshalb die Komponente sich anders verhält als bei den anderen Spalten.

Ich habe inzwischen eine Lösung gefunden wenn ich nach dem Ändern des Inhalt
Delphi-Quellcode:
vstTable.InvalidateNode(Node);
durchführe funktioniert die Berechnung und Anpassung aller Spalten in der Zeile.

Aviator 6. Apr 2017 09:03

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Codehunter (Beitrag 1366571)
Zitat:

Zitat von TUX_der_Pinguin (Beitrag 1366400)
Weil die Zeile ja immer noch den Focus hat und ausgewählt ist wird wohl intern der Inhalt für die erste Spalte geändert so das bei der Berechnung der maximalen Breite keine Veränderung erkannt wird. Hebe ich die Auswahl vor dem Ändern auf klappt es und auch die erste Spalte wird korrekt geändert.

Das ist eher unwahrscheinlich. Der VST ändert eigentlich nicht den Textinhalt von Spalten. Der liest das eigentlich nur aus deinen externen Daten (wie gesagt bei mir immer Records) und pinselt es dann auf die Canvas.

Das ist falsch. :shock:
Der VirtualStringTree liest die Daten nicht selbst aus. Er kennt diese nicht einmal. Er reserviert lediglich den Speicher für dich, den du im OnGetNodeDataSize Event oder per Setzen der Property übergeben hast. Die Texte werden immer per OnGetText Event an den Tree weitergegeben. Du musst dem Tree sagen was er in die einzelnen "Cells" reinschreiben soll.

Deshalb ist es auch kein Problem eine Klasse dafür zu verwenden. Das was dann nämlich in NodeData gespeichert wird, ist nur eine Referenz auf die Klasseninstanz. Und die ist (wenn ich mich richtig erinnere) immer 4 Byte (Win32) und 8 Byte (Win64) groß (was nebenbei bemerkt schon der Standardwert der NodeDataSize Property bei Win32 ist).

Wenn man dann zu der Klasse noch eine TObjectList mitführt, dann braucht man auch das OnFreeNode Event nicht mehr zu nutzen. Denn die Daten und die Anzahl der Nodes kommen immer aus der TObjectList. Und die Instanzen die darin gespeichert sind, die werden sowieso von dir verwaltet.

Codehunter 6. Apr 2017 09:18

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Haste vollkommen recht. Siehe mein Edit oben. Hat sich jetzt zeitlich nur überschnitten.

Codehunter 6. Apr 2017 09:22

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
 
Zitat:

Zitat von Aviator (Beitrag 1366574)
Deshalb ist es auch kein Problem eine Klasse dafür zu verwenden. Das was dann nämlich in NodeData gespeichert wird, ist nur eine Referenz auf die Klasseninstanz. Und die ist (wenn ich mich richtig erinnere) immer 4 Byte (Win32) und 8 Byte (Win64) groß (was nebenbei bemerkt schon der Standardwert der NodeDataSize Property bei Win32 ist).

Daran habe ich mich ja auch gar nicht gestört sondern an der Art und Weise wie das hier konkret umgesetzt wurde. Ich denke, da werden im Grunde Memleaks produziert. Denn besagter Zeiger muss ja auch irgendwo hin zeigen. Hier sah es so aus als wäre das zunächst ein Zeiger auf einen Zeiger (also 2x4 bzw. 2x8 Byte) und würde dann durch einen Zeiger auf eine Klasseninstanz überschrieben.

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 16:21 Uhr.
Seite 1 von 2  1 2      

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