如何在InitNode事件中将数据分配给VirtualStringTree的节点 [英] How to assign data to node of VirtualStringTree in InitNode event

查看:97
本文介绍了如何在InitNode事件中将数据分配给VirtualStringTree的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定如何将数据分配给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.

此外,您对数据类型感到困惑.您说FDiagDataListTObjectList,但是您显然在其中存储了不是是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆