2014-10-29 119 views
1

我不知道如何將數據分配給VirtualStringTree中的節點。我需要爲樹控件的InitNode事件中的Node的Data屬性指定一個記錄對象的指針。但是,我得到一個'所需的指針類型'編譯時錯誤。如何將數據分配給InitNode事件中的VirtualStringTree節點

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事件中的節點,但不知道如何分配它。

+0

我可以猜到編譯器錯誤是什麼,但要說教,請問編輯問題以包含編譯器錯誤。我其實認爲你在這裏有兩個明顯的錯誤。但是你最好告訴我們他們是什麼。 – 2014-10-29 14:49:00

+1

'DiagData:= Sender.GetNodeData(Node); DiagData.DiagID:= ...'或'DiagData:= Sender.GetNodeData(Node); DiagData ^:= FDiagDataList.Items [c]'但什麼是'c'? – TLama 2014-10-29 14:49:14

+0

@TLama:是的,它的工作原理! – 2014-10-29 14:51:44

回答

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,但你明確存儲的東西不是後裔TObject。當您不使用對象時,請勿使用TObjectList。如果您使用的是版本德爾福於2009年早期,然後用TList和存儲指針TDiagData

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

如果您使用的Delphi 2009或更高版本,然後用TList<TDiagData>,然後擺脫類型轉換:

NodeData^ := FDiagDataList[c]; 

無論哪種方式,你可能會發現事情變得更容易管理,如果事件處理程序開始時以同樣的方式,具有GetNodeData調用獲取類型安全點呃到當前節點的數據。

+0

Eeek!那'c'仍然與我們在一起。 – TLama 2014-10-29 17:03:18

+0

那麼,@Tlama?我們可以用一些元表達式替換它,*'expression-that-selecting-data-for-current-node' *,但是我們也可以假設*'c' *已經*是這樣一個表達式。爲什麼要說話? – 2014-10-29 17:18:24

+0

@RobKennedy:好,相關答案。 – 2014-10-29 17:36:06

相關問題