AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst
Thema durchsuchen
Ansicht
Themen-Optionen

TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

Ein Thema von TUX_der_Pinguin · begonnen am 4. Apr 2017 · letzter Beitrag vom 6. Apr 2017
Antwort Antwort
Seite 5 von 5   « Erste     345   
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#41

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

  Alt 6. Apr 2017, 12:34
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.
Ähm sorry Irrtum vom Amt. War irgendein Cache Effekt.
Mache bei den MiscOptions mal toGridExtensions rein, dann sollte es funzen.
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#42

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

  Alt 6. Apr 2017, 12:35
@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.
Ich verwende in den meisten Fällen die Komponente nur als Grid, aber einfach Header.MainColumn auf '1' zu setzten geht nicht wenn man wie in meinem Projekt teilweise nur eine Spalte hat. Naja und da die Lösung mit InvalidateNode() ja funktioniert, belasse ich es mit der Lösung.

Und das habe ich ja die ganze Zeit auch gemeint da das Verhalten so merkwürdig ist das ich da auch auf einen Bug schließe und nicht auf ein gewolltes Verhalten. Ich hatte das auch so als Bug Report bei GitHub eingestellt.
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
608 Beiträge
 
Delphi 11 Alexandria
 
#43

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

  Alt 6. Apr 2017, 12:36
Mache bei den MiscOptions mal toGridExtensions rein, dann sollte es funzen.
Nein auch mit der Option ändert sich nichts.
  Mit Zitat antworten Zitat
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#44

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

  Alt 6. Apr 2017, 12:48
Bitte sehr. Option toGridExtensions hinzugefügt und die "^" eingebaut. Mehr nicht. Läuft, falls man einen Node selektiert hat.

Delphi-Quellcode:
object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 489
  ClientWidth = 730
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object vstTable: TVirtualStringTree
    Left = 112
    Top = 88
    Width = 505
    Height = 345
    Header.AutoSizeIndex = 0
    Header.Font.Charset = DEFAULT_CHARSET
    Header.Font.Color = clWindowText
    Header.Font.Height = -11
    Header.Font.Name = 'Tahoma'
    Header.Font.Style = []
    Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
    TabOrder = 0
    TreeOptions.MiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toGridExtensions, toInitOnSave, toToggleOnDblClick, toWheelPanning, toEditOnClick]
    TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages]
    TreeOptions.SelectionOptions = [toFullRowSelect]
    OnGetText = vstTableGetText
    Columns = <
      item
        Position = 0
        WideText = 'Name'
      end
      item
        Position = 1
        WideText = 'Description'
      end>
  end
  object Button1: TButton
    Left = 144
    Top = 57
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
end
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
  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;
  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.

Geändert von madas ( 6. Apr 2017 um 12:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#45

AW: TVirtualStringTree AutoFitColumns erste Spalte wird nicht angepasst

  Alt 6. Apr 2017, 12:58
Bitte sehr. Option toGridExtensions hinzugefügt und die "^" eingebaut. Mehr nicht. Läuft, falls man einen Node selektiert hat.
Nix läuft. Dass das mit dem selektierten Node funktioniert ist eher ein Seiteneffekt, aber keine Lösung.

Ich denke aber ich bin des Rätsels Lösung schon sehr sehr nahe. In TCustomVirtualStringTree.DoGetNodeWidth:
Delphi-Quellcode:
    if Column = FHeader.MainColumn then
    begin
      // Primary column or no columns.
      Data := InternalData(Node); // <-- Magic Wunderding !!!
      if Assigned(Data) then
      begin
        Result := Data^;
        if Result = 0 then
        begin
          Data^ := CalculateTextWidth(Canvas, Node, Column, Text[Node, Column]);
          Result := Data^;
        end;
      end
      else
        Result := 0;
    end
Der Schweinehund puffert doch die Textbreite tatsächlich! Wahrscheinlich aus Performancegründen, um eben nicht für jede einzelne Zelle die Textbreite über den DeviceContext berechnen zu müssen. Und hier kommt auch die Erklärung, warum es mit einem InvalidateNode funktioniert:
Delphi-Quellcode:
function TCustomVirtualStringTree.InvalidateNode(Node: PVirtualNode): TRect;

var
  Data: PInteger;

begin
  Result := inherited InvalidateNode(Node);
  // Achtung !!! Hier des Rätsels Lösung:
  // Reset node width so changed text attributes are applied correctly.
  if Assigned(Node) then
  begin
    Data := InternalData(Node);
    if Assigned(Data) then
      Data^ := 0; // !!! InternalData wird auf 0 gesetzt, weshalb GetNodeWidth dann gezwungen ist neu zu berechnen.
    // Reset height measured flag too to cause a re-issue of the OnMeasureItem event.
    Exclude(Node.States, vsHeightMeasured);
  end;
end;
So: Rätsel gelöst! Ich lag falsch, der VST puffert doch die Textbreite. Daher ist die einzig richtige Lösung, ein InvalidateNode zu machen.
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden

Geändert von Codehunter ( 6. Apr 2017 um 13:02 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 5 von 5   « Erste     345   


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 21:38 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