delphi – VirtualStringTree – 指针存储<>指针检索!我
我正在使用TVirtualStringTree来存储指向记录的指针.
最初有一个包含记录列表的TList. 我正在使用OnInitNode事件迭代TList并将每个记录的数据分配给树的节点. 但是,在检索与OnNewText事件处理程序中的节点关联的数据时,返回的指针具有与最初存储在树中的指针不同的地址. 此外,我可以通过调试看到从节点检索的指针(到记录数据)与最初存储在节点中的指针不同.我需要将更改的数据保存到数据库,并需要使用更改的数据引用记录.引用指针应该很简单,但问题是指针不一样. 我不确定我做错了什么,希望有人可以帮我解决这个问题. 提前致谢. 这是我的代码: 数据结构和声明: TTherapData = record TherapID: Integer; TherapName: String[120]; TherapInstr: String[120]; Selected_DB: Byte; Selected: Byte; end; PTherapData = ^TTherapData; FTherapDataList: TList<PTherapData>; FTherapDataListAsg_Iter: Integer; vstRxList_Asg: TVirtualStringTree; 将数据加载到TList中,然后加载到树中: procedure TfmPatient_Conslt.LoadTherapList(const ADBLoad: Boolean = False); var TherapData: PTherapData; d,x: Integer; begin datamod.uspLKTHERAP_S.First; while not datamod.uspLKTHERAP_S.Eof do begin New(TherapData); TherapData^.TherapID := datamod.uspLKTHERAP_SROW_ID.AsInteger; TherapData^.TherapName := datamod.uspLKTHERAP_SIMPRTHERAP.AsString; TherapData^.TherapInstr := EmptyStr; TherapData^.Selected := 0; TherapData^.Selected_DB := 0; FTherapDataList.Add(TherapData); datamod.uspLKTHERAP_S.Next; end; datamod.uspCONSLT_RX_S.First; while not datamod.uspCONSLT_RX_S.Eof do begin d := datamod.uspCONSLT_RX_SRX_ID.AsInteger; TherapData := FTherapDataList[TherapDataList_GetIndexOfID(d)]; TherapData^.TherapInstr := datamod.uspCONSLT_RX_SRX_INSTRUCTION.AsString; TherapData^.Selected := 1; TherapData^.Selected_DB := 1; datamod.uspCONSLT_RX_S.Next; end; x := TherapDataList_CountSelectedItems; FTherapDataListAsg_Iter := 0; vstRxList_Asg.NodeDataSize := SizeOf(TTherapData); vstRxList_Asg.RootNodeCount := 0; vstRxList_Asg.RootNodeCount := x; end; procedure TfmPatient_Conslt.vstRxList_AsgInitNode(Sender: TBaseVirtualTree; ParentNode,Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); var TherapData: PTherapData; begin TherapData := Sender.GetNodeData(Node); while (FTherapDataList[FTherapDataListAsg_Iter]^.Selected <> 1) do Inc(FTherapDataListAsg_Iter); TherapData^.TherapID := FTherapDataList[FTherapDataListAsg_Iter]^.TherapID; TherapData^.TherapName := FTherapDataList[FTherapDataListAsg_Iter]^.TherapName; TherapData^.TherapInstr := FTherapDataList[FTherapDataListAsg_Iter]^.TherapInstr; { TherapData := FTherapDataList[FTherapDataListAsg_Iter]; } // { TherapData^ := FTherapDataList[FTherapDataListAsg_Iter]^; } // Inc(FTherapDataListAsg_Iter); end; procedure TfmPatient_Conslt.vstRxList_AsgGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var TherapData: PTherapData; begin TherapData := Sender.GetNodeData(Node); if Assigned(TherapData) then if (Column = 0) then CellText := TherapData^.TherapName else if (Column = 1) then CellText := TherapData^.TherapInstr; end; procedure TfmPatient_Conslt.vstRxList_AsgEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean); begin Allowed := (Column = 1); end; 检索数据.我注意到这里的问题: procedure TfmPatient_Conslt.vstRxList_AsgNewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; NewText: string); var TherapData: PTherapData; begin if (Column = 1) then begin TherapData := Sender.GetNodeData(Node); if Assigned(TherapData) then // <---- There is a debug breakpoint here // and the watch window screen-shot // is taken here TherapData^.TherapInstr := NewText; // Showmessage(Format('%p',[TherapData])); // <---- The pointer value is not the same // as that originally stored ! end; end; 这是我将列表数据保存到数据库的地方,以及我需要树来更改原始数据而不是副本的原因: procedure TfmPatient_Conslt.SaveRxListToDB; var TherapData: PTherapData; begin for TherapData in FTherapDataList do begin if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 0) then begin // Add new entries to DB // :ROW_ID,:CONSLT_ID,:RX_ID,:RX_INSTRUCTION datamod.uspCONSLT_RX_I.ParamByName('ROW_ID').AsInteger := 0; datamod.uspCONSLT_RX_I.ParamByName('CONSLT_ID').AsInteger := FConsultationID; datamod.uspCONSLT_RX_I.ParamByName('RX_ID').AsInteger := TherapData^.TherapID; datamod.uspCONSLT_RX_I.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr; datamod.uspCONSLT_RX_I.PrepareSQL(False); datamod.uspCONSLT_RX_I.ExecProc; TherapData^.Selected_DB := 1; end else if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 1) then begin // Update existing DB entries // :CONSLT_ID,:RX_INSTRUCTION datamod.uspCONSLT_RX_U.ParamByName('CONSLT_ID').AsInteger := FConsultationID; datamod.uspCONSLT_RX_U.ParamByName('RX_ID').AsInteger := TherapData^.TherapID; datamod.uspCONSLT_RX_U.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr; datamod.uspCONSLT_RX_U.PrepareSQL(False); datamod.uspCONSLT_RX_U.ExecProc; end else if (TherapData^.Selected = 0) and (TherapData^.Selected_DB = 1) then begin // Delete removed entries from DB // :CONSLT_ID,:RX_ID datamod.uspCONSLT_RX_D.ParamByName('CONSLT_ID').AsInteger := FConsultationID; datamod.uspCONSLT_RX_D.ParamByName('RX_ID').AsInteger := TherapData^.TherapID; datamod.uspCONSLT_RX_D.PrepareSQL(False); datamod.uspCONSLT_RX_D.ExecProc; TherapData^.Selected_DB := 0; end; end; end; 以下是Debug-> Watch List窗口的屏幕截图: 解决方法
要回答标题中的问题,我会说是的,你的编码方法是错误的.
错误是您没有将指向数据记录的指针保存到VT的节点,而是为每个节点分配整个(单独的)TTherapData记录!所以“错误”就是这条线 vstRxList_Asg.NodeDataSize := SizeOf(TTherapData); 在TfmPatient_Conslt.LoadTherapList方法中.你可能想要的是一个附加记录,它保存指向数据记录的指针: type TVTNodeData = record TherapData: PTherapData; end; PVTNodeData = ^TVTNodeData; 并将该记录用作节点数据记录: vstRxList_Asg.NodeDataSize := SizeOf(TVTNodeData); 和节点init变成类似的东西 procedure TfmPatient_Conslt.vstRxList_AsgInitNode(Sender: TBaseVirtualTree; ParentNode,Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); var NodeData: PVTNodeData; begin NodeData := Sender.GetNodeData(Node); while (FTherapDataList[FTherapDataListAsg_Iter]^.Selected <> 1) do Inc(FTherapDataListAsg_Iter); NodeData^.TherapData := FTherapDataList[FTherapDataListAsg_Iter]; Inc(FTherapDataListAsg_Iter); end; 并使用其他树事件中的数据 procedure TfmPatient_Conslt.vstRxList_AsgGetText(Sender: TBaseVirtualTree; Node:PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var NodeData: PVTNodeData; TherapData: PTherapData; begin NodeData := Sender.GetNodeData(Node); if Assigned(NodeData) and Assigned(NodeData.TherapData) then begin TherapData := NodeData.TherapData; if (Column = 0) then CellText := TherapData^.TherapName else if (Column = 1) then CellText := TherapData^.TherapInstr; end; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |