Итак, я работаю с Delphi 2010, и прошло некоторое время с тех пор, как я начал использовать VirtualTreeView (именно VirtualStringTree).. и кажется, что я делаю что-то не так.. поскольку все работает не так, как я ожидание.
Я пытаюсь заполнить свой VST узлами, которые указывают на описания файлов/подпапок, хранящиеся в записях данных и сгенерированные путем сканирования пути, указанного пользователем.. (более подробная информация показана на следующем изображении)
Как показано, узлы отображаются странным образом ... и независимо от того, что я делаю, данные узлов не инициализируются должным образом ... заголовки узлов для столбца «Файл» - единственное, что работает хорошо.
и вот код, который я использую:
1- Объявление данных узла:
type nodeData=record
Text, Size, Path:String;
ImageIndex:Integer;
end;
PNodeData=^nodeData;
var hashmap:TDictionary<String, PVirtualNode>; // hashmap-> to store parent nodes (Folder)
filesList:TDictionary<Integer,nodeData>; // fileList to store records of data
2-Методы
а) сканировать путь, заданный пользователем
procedure AddAllFilesInDir(const Dir:String);
begin
// it scans the path 'Dir' and extract the "name & size" of each file/folder found in this dir
end;
b) создать словарь filesList... и изображения сохраняются в "treeImageLIst", который связан со свойством treeview.images.
procedure addFileToList(Name, Size:String);
var d:nodeData;
parent:String;
SHFileInfo :TSHFileINfo;
Icon:TIcon;
begin
parent:=ExtractFileDir(Name);
//Get The Icon That Represents The File/Folder
SHGetFileInfo(PChar(Name), 0, SHFileInfo, SizeOf(SHFileInfo),
SHGFI_ICON or SHGFI_SMALLICON );
Icon := TIcon.Create;
Icon.Handle := SHFileInfo.hIcon;
// set The Name, Size, Path
d.Name:=ExtractFileName(Name);
d.Size:=Size;
d.Path:=parent;
// set the ImageIndex
d.ImageIndex:=Form1.treeImageList.AddIcon(Icon);
// add the node to fileList
filesList.Add(filesList.Count, d);
// Destroy the Icon
DestroyIcon(SHFileInfo.hIcon);
Icon.Free;
end;
в) создать дерево "theTree"
procedure createTree();
var theNode, Node:PVirtualNode;
d:PNodeData;
parent:String;
nData:nodeData;
i:integer;
begin
for i := 0 to filesList.Count - 1 do
begin
nData:=filesList.Items[i]; parent:=nData.Path;
if(hashmap.ContainsKey(parent))then theNode:=hashmap.Items[parent]
else theNode:=nil;
Node:=Form1.theTree.AddChild(theNode);
// add a checkbox and make it checked
Node.CheckType:=ctCheckBox;
Node.CheckState:=csCheckedNormal;
// get the newly created node data
d:=Form1.theTree.GetNodeData(Node);
// assign a data to the newly created node
d^:=nData;
// add the node to hashmap if it's a new folder node
if((ExtractFileExt(nData.Text)='')and(not hashmap.ContainsKey(nData.Path+'\'+nData.Text)))
then hashmap.Add(nData.Path+'\'+nData.Text, Node);
end;
Form1.theTree.Expanded[Form1.theTree.TopNode]:=True;
end;
г) древовидные события
procedure TForm1.theTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var d:PNodeData;
begin
d := Sender.GetNodeData(Node);
Finalize(d^);
end;
procedure TForm1.theTreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var d:PNodeData;
begin
d:=Sender.GetNodeData(Node);
case Column of
0:CellText:=d^.Text;
1:CellText:=d^.Size;
end;
end;
procedure TForm1.theTreeGetImageIndex(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer);
var d:PNodeData;
begin
d:=Sender.GetNodeData(Node);
if(Kind in [ikNormal, ikSelected])then
begin
if(Column=0)then ImageIndex:=d^.ImageIndex;
end;
end;
Я действительно расстроен прямо сейчас ... и я не знаю, почему узлы не создаются должным образом ... хотя я проверил данные записей, и они созданы хорошо, но когда я тестировал событие onNodeClick, я обнаружил, что запись данных, указанная узлом, возвращает только первое поле... в то время как другие поля либо пусты, либо генерируют исключение нарушения прав доступа.
theTree.NodeDataSize:=SizeOf(nodeData)
(обратите внимание на отсутствие P) - person Marjan Venema   schedule 02.04.2013GetNodeData
. Если у вас есть запись с данными вашего узла, вы должны всегда говоритьNodeDataSize := SizeOf(TNodeData)
. - person Rob Kennedy   schedule 02.04.2013AddChild
. Это для совместимости при переносе сTTreeView
. Вместо этого вы должны использоватьOnInitNode
илиOnInitChildren
и использовать его для подключения дерева к вашим виртуальным данным вTDictionary
, а затем получать данные при запуске событияOnGetText
. Вы пытаетесь использовать его какTTreeView
, который не находится в виртуальном режиме. Демонстрации доступны в репозитории Google Code. - person Ken White   schedule 03.04.2013Minimal
есть очень простой пример правильного использования здесь на Main.pas - person Ken White   schedule 03.04.2013