1

VirtualStringTree のノードにデータを割り当てる方法がわかりません。ツリー コントロールの InitNode イベントで、レコード オブジェクトへのポインターをノードの Data プロパティに割り当てる必要があります。ただし、「ポインター型が必要です」というコンパイル時エラーが発生します。

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 イベントでノードにデータを割り当てる必要がありますが、割り当てる方法がわかりません。

4

1 に答える 1

2

Node.Data直接読み書きしないでください。必要なデータは、必ずしもそのフィールドのアドレスにあるとは限りません。(ツリー コントロールには、子孫が自分自身のために追加のデータを予約できるようにするメカニズムがあります。)代わりに、 を呼び出します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


さらに、データ型について混乱しています。あなたは と言っFDiagDataListていますが、 の子孫ではないTObjectListものを明らかに格納しています。オブジェクトを使用していないときは、使用しないでください。2009 年より前のバージョンの Delphi を使用している場合は、次へのポインタを使用して保存します。TObjectTObjectListTListTDiagData

NodeData^ := PDiagData(FDiagDataList[c])^;

Delphi 2009 以降を使用している場合は、 を使用TList<TDiagData>してから型キャストを取り除きます。

NodeData^ := FDiagDataList[c];

いずれにしても、現在のノードのデータへのタイプ セーフ ポインターを取得するための呼び出しを使用して、すべてのイベント ハンドラーが同じ方法で開始されると、おそらく管理が容易になります。GetNodeData

于 2014-10-29T16:41:14.963 に答える