VirtualTreeView - kilka podstawowych problemów

0

Witam

Mam nadzieję, że to podstawy i znawcy tego komponentu pomogą :)

user image

  1. Jak ustalić, aby trzecia kolumna "Nazwa" automatycznie dostosowywała swoją szerokość ?
    Mam ustalone takie parametry dla trzeciej kolumny:
    [coAllowClick,coEnabled,coParentBidiMode,coResizable,coShowDropMark,coVisible,coSmartResize,coAllowFocus,coWrapCaption,coUseCaptionAlignment]

  2. Jak ustalić własne TCheckBox w pierwszej kolumnie ?
    Chodzi o takie ikony jak są w drugiej kolumnie - ale tam są obrazy przypisane z TImageList, które nie reagują na klikanie.
    Obecnie ustawiony jest CheckImageKind = ckXP.
    Próbowałem ustawić CheckImageKind = ckCustom oraz własny TImageList do CustomCheckImages, ale wtedy pierwsza kolumna jest pusta.

  3. Jak sprawdzić, który wpis zawiera przypisany konkretny ImageIndex ?
    Głównie chodzi mi jak w pętli poruszać się po całej liście rodziców (po samych korzeniach, bez gałęzi).

Tutaj wyrzuca mi AV:

var
 Node: PVirtualNode;
 Data: PTreeData;
begin
 Node := VST.RootNode;

 while Assigned(Node) do
  begin
   Data := VST.GetNodeData(Node);
   if Data.FImage = 0 then ShowMessage(Data.FCaption);   // <--------------------- błąd AV
   Node := VST.GetNext(Node);
  end;
end;
  1. Jak stworzyć wiele linii tekstu w jednym wpisie ?
  2. Czy jest możliwość stworzenia gradientowego tła dla zaznaczonego wpisu ?

Użyty kod:

  PTreeData = ^TTreeData;
  TTreeData = record
    FCheck: Boolean;
    FImage: Byte;
    FCaption: string;
    FSubItem1: string;
  end;

{Odpowiada za dodanie nowego wpisu}
function AddVirtualListItem(CVST: TCustomVirtualStringTree; ANode: PVirtualNode; ARecord: TTreeData): PVirtualNode;
var
 Data: PTreeData;
begin
 Result := CVST.AddChild(ANode);
 Data   := CVST.GetNodeData(Result);
 CVST.ValidateNode(Result, False);
 Data^.FCheck    := ARecord.FCheck;   {Zawiera informację, czy wpis zaznaczony}
 Data^.FImage    := ARecord.FImage;  {Zawiera informację o nr indeksu ikony} 
 Data^.FCaption  := ARecord.FCaption; {Zawiera treść kolumny "Nazwa"}
 Data^.FSubItem1 := ARecord.FSubItem1; {Zawiera treść kolumny "Rozmiar"}
end;

{Wstawia losowe wpisy}
procedure TForm3.Button1Click(Sender: TObject);
var
 i: Byte;
 TreeData: TTreeData;
begin
 VST.NodeDataSize := SizeOf(TTreeData);
 VST.BeginUpdate;

 Randomize;
 for i := 0 to 25 do
   begin
    TreeData.FCheck    := Bool(Random(2));
    TreeData.FImage    := Random(2);
    TreeData.FCaption  := 'Node: ' + InttoStr(i);
    TreeData.FSubItem1 := 'SubItem: ' + InttoStr(i);
    AddVirtualListItem(VST, nil, TreeData);
   end;

 VST.EndUpdate;
end;

{Sprawdza, który wpis jest zaznaczony}
procedure TForm3.Button2Click(Sender: TObject);
var
 Node: PVirtualNode;
 Data: PTreeData;
begin
 Node := VST.RootNode;

 while Assigned(Node) do
  begin
   if Node.CheckState = csCheckedNormal then
     begin
      Data := VST.GetNodeData(Node);
      ShowMessage(Data.FCaption);
     end;
     
   Node := VST.GetNext(Node);
  end;
end;

{Sprawdza, który wpis ma nr indeksu ikony}
procedure TForm3.Button3Click(Sender: TObject);
var
 Node: PVirtualNode;
 Data: PTreeData;
begin
 Node := VST.RootNode;

 while Assigned(Node) do
  begin
   Data := VST.GetNodeData(Node);
   if Data.FImage = 0 then ShowMessage(Data.FCaption);   // <--------------------- błąd AV
  // (jak tu się odwołać do ikony z drugiej kolumny ?

   Node := VST.GetNext(Node);
  end;
end;

{Ustala zmianę zaznaczenia wpisu}
procedure TForm3.VSTChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
  var NewState: TCheckState; var Allowed: Boolean);
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);
 Data.FCheck := (NewState = csCheckedNormal);
end;

{Odpowiada za zmianę wysokości wpisu, gdy jest on aktualnie podświetlony}
procedure TForm3.VSTFocusChanging(Sender: TBaseVirtualTree; OldNode,
  NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
  var Allowed: Boolean);
begin
 with TVirtualStringTree(Sender) do
   begin
    NodeHeight[OldNode] := DefaultNodeHeight;
    NodeHeight[NewNode] := DefaultNodeHeight * 2;
   end;
end;

{Zwalnia zawartość}
procedure TForm3.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);
 if Assigned(Data) then
   begin
    Data.FCaption  := '';
    Data.FSubItem1 := '';
   end;

 Finalize(Data^);
end;

{Przypisuje indeks ikony do drugiej kolumny}
procedure TForm3.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
  var ImageIndex: Integer);
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);

 if Column = 1 then ImageIndex := Data.FImage;
end;

{Przypisuje tekst do drugiej i trzeciej kolumny}
procedure TForm3.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
 Data: PTreeData;
begin
 Data := VST.GetNodeData(Node);
 case Column of
   2: CellText := Data.FCaption;
   3: CellText := Data.FSubItem1;
 end;
end;

{Inicjuje, aby wyświetlić w pierwszej kolumnie TCheckBox}
procedure TForm3.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
 VST.CheckType[Node] := ctCheckBox;
end;
0

Odnośnie problemu 1:

Header > AutoSizeIndex = 2
W ten sposób kolumna trzecia będzie automatycznie dostosowana do szerokości.

Odnośnie problemu 3:

Usunie wpisy z ikoną o indeksie 1.

var
 i: Integer;
 Node: PVirtualNode;
 Data: PTreeData;
begin
 Node := VST.GetFirst;
 for i := 0 to VST.TotalCount-1 do
   begin
    if i <> 0 then Node := VST.GetNext(Node);

    Data := VST.GetNodeData(Node);
    if Data.FImage = 1 then VST.DeleteNode(Node);// ShowMessage(Data.FCaption);
   end;
end;
1
  1. masz jaki imageindex mają poszczególne *boxy
  // Indices for check state images used for checking.
  ckEmpty                  =  0;  // an empty image used as place holder
  // radio buttons
  ckRadioUncheckedNormal   =  1;
  ckRadioUncheckedHot      =  2;
  ckRadioUncheckedPressed  =  3;
  ckRadioUncheckedDisabled =  4;
  ckRadioCheckedNormal     =  5;
  ckRadioCheckedHot        =  6;
  ckRadioCheckedPressed    =  7;
  ckRadioCheckedDisabled   =  8;
  // check boxes
  ckCheckUncheckedNormal   =  9;
  ckCheckUncheckedHot      = 10;
  ckCheckUncheckedPressed  = 11;
  ckCheckUncheckedDisabled = 12;
  ckCheckCheckedNormal     = 13;
  ckCheckCheckedHot        = 14;
  ckCheckCheckedPressed    = 15;
  ckCheckCheckedDisabled   = 16;
  ckCheckMixedNormal       = 17;
  ckCheckMixedHot          = 18;
  ckCheckMixedPressed      = 19;
  ckCheckMixedDisabled     = 20;
  // simple button
  ckButtonNormal           = 21;
  ckButtonHot              = 22;
  ckButtonPressed          = 23;
  ckButtonDisabled         = 24;

checkbox niezaznaczony ma np. indeks 9 (ckCheckUncheckedNormal = 9;), czyli musisz mieć trochę więcej obrazków w imagelist niż tylko 2 :p
4, 5. musisz sam malować komórkę

a i po itemach iteruje się trochę inaczej -

Node := VST.GetFirst;
while not Node = nil do
begin
  //co tam chcesz
  Node := VST.GetNext(Node);
end;
0

Dzięki Misiekd

Zrobiłem tak jak opisałeś. W TPngImageList utworzyłem dwa rodzaje ikon (bo tylko dla TCheckBox potrzebuję) dla następujących indeksów:
0..4, 9..12: unchecked (CheckBox odznaczony)
5..8, 13..15: checked (CheckBox zaznaczony)

user image

Jednak o dziwo nie ma tutaj transparentu tak jak w kolumnie drugiej.
Próbowałem następujących opcji:

ButtonFillMode = fmTransparent
MiscOptions = toFullRepaintOnResize
PaintOptions = toThemeAware
Header.Columns[0].Options = coParentColor
Header.Columns[0].Style = vsOwnerDraw, vsText

Mam jeszcze jeden problem z wyświetlaniem obrazów w VirtualTreeView, ale załadowanych z dysku do TPngImageList - o tym w osobnym wątku.

1

ikonki rysowane są przez ImageList_DrawEx opis na msdn a dokładniej przez ImageList_DrawEx(Handle, Index, Canvas.Handle, XPos, YPos, 0, 0, GetRGBColor(BkColor), ForegroundColor, ILD_TRANSPARENT);

0

Tylko, że ja używam TPngImageList do tego + w drugiej kolumnie te obrazy są wyświetlane poprawnie (nie używam ICO lecz obrazów PNG).

Utworzyłem TImageList i przypisałem mu obrazy BMP 32bit i teraz jest ok.
Dzięki Misiekd ponownie :)

Szkoda tylko, że nie można użyć w tym przypadku normalnych obrazów PNG.

1 użytkowników online, w tym zalogowanych: 0, gości: 1