如何在InitNode事件中将数据分配给VirtualStringTree的节点 [英] How to assign data to node of VirtualStringTree in InitNode event
问题描述
我不确定如何将数据分配给VirtualStringTree中的节点.我需要在树控件的InitNode事件中将指向记录对象的指针分配给Node的Data属性.但是,我遇到了需要指针类型"的编译时错误.
I am not sure how to assign data to a node in a VirtualStringTree. I'm need to assign a pointer to a record object to the Node's Data property in the tree control's InitNode event. However I'm getting a 'Pointer type required' compile-time error.
type
TDiagData = record
DiagID: Integer;
DiagName: String;
Selected: Byte;
end;
PDiagData = ^TDiagData;
var
FDiagDataList: TObjectList;
c: Integer; // used as an iterator for the list // incremented in vst1InitNode
procedure Btn1Click;
var
DiagData : PDiagData;
begin
try
FDiagDataList := TObjectList.Create; // TODO: Move this to form constructor
for c := 1 to 10 do
begin
New(DiagData);
DiagData.DiagID := c;
DiagData.DiagName := Format('Diag# %d', [c]);
FDiagDataList.Add(DiagData);
end;
c := 0;
vst1.NodeDataSize := SizeOf(TDiagData);
vst1.RootNodeCount := 10; // test
finally
// FDiagDataList.Free; //TODO: Move this to form destructor
end
end;
procedure vst1InitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
var InitialStates: TVirtualNodeInitStates);
var
DiagData: PDiagData;
begin
DiagData = TDiagData(FDiagDataList.Items[c]); // FDiagDataList is a TObjectlist
Node.Data^ := DiagData; // <--- this is not working ..
// The error is: Pointer type required.
Inc(c);
end;
我需要在InitNode事件中将数据分配给节点,但是不确定如何分配数据.
I need to assign the data to the node in the InitNode event, but not am sure how to assign it.
推荐答案
请勿直接读取或写入Node.Data
.您需要的数据不一定完全位于该字段的地址. (树控件具有允许子代为其自身保留其他数据的机制.)相反,请调用Sender.GetNodeData
.
Do not read or write Node.Data
directly. The data you need won't necessarily be exactly at the address of that field. (The tree control has a mechanism for allowing descendants to reserve additional data for themselves.) Instead, call Sender.GetNodeData
.
var
NodeData: PDiagData;
begin
NodeData := Sender.GetNodeData(Node);
NodeData^ := TDiagData(FDiagDataList.Items[c]);
end;
您的代码失败,因为Node.Data
的类型为record
;您不能使用^
取消引用它.在简单的情况下,GetNodeData
返回的值将等于该字段的地址(即GetNodeData(Node) = @Node.Data
).但是,不要以为所有情况都是简单的.就像我说的那样,树控件的后代可以保留自己的数据空间,因此您将使用不在您控件范围内的代码来共享该空间,这取决于树控件来管理 数据空间是您的.始终致电GetNodeData
.
Your code fails because Node.Data
has type record
; you cannot dereference it with ^
. In the simple case, the value returned by GetNodeData
will be equal to the address of that field (i.e., GetNodeData(Node) = @Node.Data
). But don't assume all cases are simple. As I said, tree-control descendants can reserve data space of their own, so you're sharing that space with code that's outside your control, and it's up to the tree control to manage which data space is yours. Always call GetNodeData
.
此外,您对数据类型感到困惑.您说FDiagDataList
是TObjectList
,但是您显然在其中存储了不是是TObject
的后代的东西.当您不使用对象时,请勿使用TObjectList
.如果您使用的Delphi版本早于2009,请使用TList
并将 pointers 存储到TDiagData
:
Furthermore, you're confused about your data types. You say FDiagDataList
is a TObjectList
, but you're clearly storing something in it that isn't a descendant of TObject
. When you're not using objects, don't use TObjectList
. If you're using a version of Delphi earlier than 2009, then use TList
and store pointers to TDiagData
:
NodeData^ := PDiagData(FDiagDataList[c])^;
如果您使用的是Delphi 2009或更高版本,请使用TList<TDiagData>
,然后删除强制类型转换:
If you're using Delphi 2009 or later, then use TList<TDiagData>
, and then get rid of the type cast:
NodeData^ := FDiagDataList[c];
无论哪种方式,如果每个事件处理程序以相同的方式启动,并且调用GetNodeData
来获取指向当前节点的类型安全指针,则可能会发现更易于管理.数据.
Either way, you'll probably find things easier to manage if every event handler starts out the same way, with a call to GetNodeData
to fetch the type-safe pointer to the current node's data.
这篇关于如何在InitNode事件中将数据分配给VirtualStringTree的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!