private
    pRootNode: ^XRootNode;procedure TfrmDesignerGeneral.ManageAllProject;
var
  s:String;
  root:TTreeNode;
begin
  tvwProject.Items.Clear;
  root:= tvwProject.Items.Add(tvwProject.Selected,'aaa');  New(pRootNode);  pRootNode^.id:= '';
  pRootNode^.name:= 'aaa';  root.Data:= pRootNode;  tvwProject.Items.AddChild(root,'tmp');
end;程序编译没问题。运行后出现:access violation at address 00404518 in module 'MyApp.exe'.read of address 00000004
project MyApp raisei exception class EInvalidPointer with message 'Invalid pointer operation'.为什么出现这样的问题?我照着帮助写的。

解决方案 »

  1.   

    Type 
      pRootNode: ^XRootNode;
      XRootNode = Record
               id:string;
               name:string;
               ......
               end;//end of record
      

  2.   

    用class不成吗?我还想继承这个的。type  PxTreeNode = ^XTreeNode;
      XTreeNode = class(TObject)
      private
      protected
      public
        name:String;
        id:String;
        nodeType: integer;
      end;  PxRootNode = ^XRootNode;
      XRootNode = class(XTreeNode)
      public
        subtype: integer;
        value: string;
      end; 
      

  3.   

    New(pRootNode);
    pRootNode^.id:= '';
    ^.name:= 'aaa';
    root:= tvwProject.Items.AddObject(tvwProject.Selected,'aaa',pRootNode);
      

  4.   

    procedure TfrmDesignerGeneral.ManageAllProject;
    var
      s:String;
      root:TTreeNode;
    begin
      tvwProject.Items.Clear;  New(pRootNode);  pRootNode^.id:= '';
      pRootNode^.name:= 'aaa';
      pRootNode^.nodeType:= 1;
      pRootNode^.subtype:= 0;
      pRootNode^.value:= '';  root:= tvwProject.Items.AddObject(tvwProject.Selected,'aaa',pRootNode);  tvwProject.Items.AddChild(root,'tmp');
    end;可是当我把pRootNode^.*** 之类的注释掉就好了。类的定义在前面,为什么?我第一次用Delphi定义类
      

  5.   

    procedure TfrmDesignerGeneral.ManageAllProject;
    var
      s:String;
      root:TTreeNode;
    begin
      tvwProject.Items.Clear;
      New(pRootNode);
      pRootNode^.id:= '';
      pRootNode^.name:= 'aaa';
      pRootNode^.nodeType:= 1;
      pRootNode^.subtype:= 0;
      pRootNode^.value:= '';
      root:= tvwProject.Items.AddChildObject(tvwProject.Selected,'tmp',pRootNode);
      Dispose(pRootNode);
    end;
      

  6.   

    指针和类不会用,别瞎用。
    类是create的,不是new的
      

  7.   

    是这样,调试发现运行到
    pRootNode^.id:= '';
    时发现错误 。id成员是父类的成员。在向父类成员赋值时出现错误。如果执行
    pRootNode^.subtype:= 0;
    则不会发生错误。后来定义了一个
    rootNode: XRootNode;执行rootNode:= XRootNode.create;
    pRootNode:= @rootNode
    pRootNode^.id:= '';就好用了。那么,诸如
    New(pRootNode);
    getmem(pRootNode,sizeof(XRootNode));
    pRootNode:= @XRootNode.Create;
    这样的语句为什么不能起到为XRootNode的父类成员分配内存的效果?
      

  8.   

    我喜欢这样用
    TuserNode=class(Tobject)
    firstname:string;
    lastName:string;
    UserID:string;
    end;aUser:=TuserNode.Create();
    aUser.firstName='xxx';
    aUser.lastName='xxx';
    aUser.UserID='xxx';TreeView.Items.item[0].Data:=aUser;
    TuserNode(TreeView.Items.item[0].Data).firstName;
    TuserNode(TreeView.Items.item[0].Data).UserID;呵呵,感觉不到指针
      

  9.   

    to zhboy(孔方兄)
    谢谢提出来,一时弄错了
      

  10.   

    给你一例子慢慢看吧。
    对了,差点忘了最重要的一点:删除节点之前,一定要把Node.Data指向的
    变量(内存)释放了!否则会造成内存泄漏的。
    function funFreeTreeViewNodeData(aNode: TTreeNode): integer;
    var
     p: Pointer;
    begin
     Result := -1;
     if Assigned(aNode.Data) then
     begin
       try
         p := aNode.Data;
         Dispose(p);
         aNode.Data := nil;
       except
         on E: Exception do
           Application.MessageBox(PChar(E.Message),
             '释放树型节点指针(Data)时发生错误', 0);
       end;
     end;
     Result := 1;
    end;// 删除节点时释放内存
    procedure TGZLLLBMainFrm.trvGZLLreplyDeletion(Sender: TObject;
     Node: TTreeNode);
    begin
     wintelconst.funFreeTreeViewNodeData(Node);
    end;
    {展开TreeView节点}procedure TGZLLLBMainFrm.trvGZLLreplyExpanding(Sender: TObject; Node:
     TTreeNode;
     var AllowExpansion: Boolean);
    begin
     if Node.Level <> 0 then
       funGetNodeChildren(1, Node);
    end;{刷新TreeView节点,传递"层"参数,
    aLevel=0:根节点;aLevel为其它值,非根节点}function TGZLLLBMainFrm.funGetNodeChildren(aLevel: Byte; aNode: TTreeNode):
     Byte;
    var
     I, j: integer;
     NodeData: PGZLLNodeData;
     trvNode, curNode: TTreeNode;
    begin
     Result := 0;                          {失败}
     try
       trvGZLLreply.Items.BeginUpdate;     {更改节点期间禁止刷新}
       case aLevel of
         {第一层不再使用!!!}
         0:                                {根节点, 一次取两层的数据}
           begin
             {释放占用内存, 清除所有原来的节点}
             vChooseIndexL2 := -1;
             if trvGZLLreply.Items.Count > 0 then
             begin
               {for i := 0 to trvGZLLreply.Items.Count-1 do
                 wintelconst.prcFreeNodeData(trvGZLLreply.Items[i],False);}
               for I := trvGZLLreply.Items.Count - 1 downto 0 do
                 trvGZLLreply.Items[I].Delete;
             end;
             with adoqryGZLLL21 do         {取第一层节点数据}
             begin
               Active := False;
               Filter := '';
               Filtered := False;
               SQL.Clear;
               SQL.Append(wintelconst.cSQLGZLLLevel1); //cSQLLevel1 Format(,[0])
               Active := True;
               if not IsEmpty then
               begin
                 for I := 0 to RecordCount - 1 do
                 begin
                   new(NodeData);
                   NodeData^.ID := FieldByName('id').AsInteger;
                   NodeData^.fjr := FieldByName('fjr').AsString;
                   curNode := trvGZLLreply.Items.AddObject(nil,
                     FieldValues['llzt'], NodeData);
                   {取第二层节点}
                   with adoqryGZLLL22 do
                   begin
                     Active := False;
                     //SQL.Clear;
                     //SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
                     Parameters.ParamValues['ID'] :=
                       PGZLLNodeData(curNode.Data)^.ID;
                     Active := True;
                     if not IsEmpty then
                     begin
                       for j := 0 to RecordCount - 1 do
                       begin
                         new(NodeData);
                         NodeData^.ID := FieldValues['id'];
                         NodeData^.fjr := FieldValues['fjr'];
                         trvGZLLreply.Items.AddChildObject(curNode,
                           FieldValues['llzt'], NodeData); //curCNode :=
                         Next;
                       end;                {end for(j)}
                     end;
                     Active := False;
                   end;                    {end with adoqryGZLL2}
                   Next;
                 end;                      {end for(i)}
               end;
               Active := False;
               //EmptyRec := IsEmpty;
             end;                          {end with adoqryGZLL}
             Result := 1;
           end;                            {end case(0)}
         1: {非根节点,取本层的子节点以及孙节点,相当于刷新}
           begin
             trvNode := aNode;
             {如果有子节点,先把所有的删除}
             if trvNode.HasChildren then
             begin
               {for i := 0 to trvNode.Count-1 do
                 wintelconst.prcFreeNodeData(trvNode.Item[i],False); }
               trvNode.DeleteChildren;
             end;
             with adoqryGZLLL21 do         {子节点}
             begin
               Active := False;
               Filter := '';
               Filtered := False;
               SQL.Clear;
               SQL.Append(Format(wintelconst.cSQLGZLLLevel2,
                 [PGZLLNodeData(trvNode.Data)^.ID]));
               //SQL.Append(fun
               Active := True;
               Sort := 'id DESC';
               for I := 0 to RecordCount - 1 do
               begin
                 new(NodeData);
                 NodeData^.ID := FieldValues['id'];
                 NodeData^.fjr := FieldValues['fjr'];
                 curNode := trvGZLLreply.Items.AddChildObject(trvNode,
                   FieldValues['llzt'], NodeData); //curCNode :=
                 {取第二层节点}
                 with adoqryGZLLL22 do
                 begin
                   Active := False;
                   //SQL.Clear;
                   //SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
                   Parameters.ParamValues['ID'] :=
                     PGZLLNodeData(curNode.Data)^.ID;
                   Active := True;
                   Sort := 'id DESC';
                   if not IsEmpty then
                   begin
                     for j := 0 to RecordCount - 1 do
                     begin
                       new(NodeData);
                       NodeData^.ID := FieldValues['id'];
                       NodeData^.fjr := FieldValues['fjr'];
                       trvGZLLreply.Items.AddChildObject(curNode,
                         FieldValues['llzt'], NodeData); //curCNode :=
                       Next;
                     end;                  {end for(j)}
                   end;
                   Active := False;
                 end;                      {end with adoqryGZLL2}
                 Next;
               end;
               Active := False;
             end;                          {end with adoqryGZLL}
             Result := 1;
           end;                            {end case(1)}
       end;                                {end case}
     finally
       trvGZLLreply.Items.EndUpdate;       {开始刷新}
     end;
    end;
      

  11.   

    给你一例子慢慢看吧。
    对了,差点忘了最重要的一点:删除节点之前,一定要把Node.Data指向的
    变量(内存)释放了!否则会造成内存泄漏的。
    function funFreeTreeViewNodeData(aNode: TTreeNode): integer;
    var
     p: Pointer;
    begin
     Result := -1;
     if Assigned(aNode.Data) then
     begin
       try
         p := aNode.Data;
         Dispose(p);
         aNode.Data := nil;
       except
         on E: Exception do
           Application.MessageBox(PChar(E.Message),
             '释放树型节点指针(Data)时发生错误', 0);
       end;
     end;
     Result := 1;
    end;// 删除节点时释放内存
    procedure TGZLLLBMainFrm.trvGZLLreplyDeletion(Sender: TObject;
     Node: TTreeNode);
    begin
     wintelconst.funFreeTreeViewNodeData(Node);
    end;
    {展开TreeView节点}procedure TGZLLLBMainFrm.trvGZLLreplyExpanding(Sender: TObject; Node:
     TTreeNode;
     var AllowExpansion: Boolean);
    begin
     if Node.Level <> 0 then
       funGetNodeChildren(1, Node);
    end;{刷新TreeView节点,传递"层"参数,
    aLevel=0:根节点;aLevel为其它值,非根节点}function TGZLLLBMainFrm.funGetNodeChildren(aLevel: Byte; aNode: TTreeNode):
     Byte;
    var
     I, j: integer;
     NodeData: PGZLLNodeData;
     trvNode, curNode: TTreeNode;
    begin
     Result := 0;                          {失败}
     try
       trvGZLLreply.Items.BeginUpdate;     {更改节点期间禁止刷新}
       case aLevel of
         {第一层不再使用!!!}
         0:                                {根节点, 一次取两层的数据}
           begin
             {释放占用内存, 清除所有原来的节点}
             vChooseIndexL2 := -1;
             if trvGZLLreply.Items.Count > 0 then
             begin
               {for i := 0 to trvGZLLreply.Items.Count-1 do
                 wintelconst.prcFreeNodeData(trvGZLLreply.Items[i],False);}
               for I := trvGZLLreply.Items.Count - 1 downto 0 do
                 trvGZLLreply.Items[I].Delete;
             end;
             with adoqryGZLLL21 do         {取第一层节点数据}
             begin
               Active := False;
               Filter := '';
               Filtered := False;
               SQL.Clear;
               SQL.Append(wintelconst.cSQLGZLLLevel1); //cSQLLevel1 Format(,[0])
               Active := True;
               if not IsEmpty then
               begin
                 for I := 0 to RecordCount - 1 do
                 begin
                   new(NodeData);
                   NodeData^.ID := FieldByName('id').AsInteger;
                   NodeData^.fjr := FieldByName('fjr').AsString;
                   curNode := trvGZLLreply.Items.AddObject(nil,
                     FieldValues['llzt'], NodeData);
                   {取第二层节点}
                   with adoqryGZLLL22 do
                   begin
                     Active := False;
                     //SQL.Clear;
                     //SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
                     Parameters.ParamValues['ID'] :=
                       PGZLLNodeData(curNode.Data)^.ID;
                     Active := True;
                     if not IsEmpty then
                     begin
                       for j := 0 to RecordCount - 1 do
                       begin
                         new(NodeData);
                         NodeData^.ID := FieldValues['id'];
                         NodeData^.fjr := FieldValues['fjr'];
                         trvGZLLreply.Items.AddChildObject(curNode,
                           FieldValues['llzt'], NodeData); //curCNode :=
                         Next;
                       end;                {end for(j)}
                     end;
                     Active := False;
                   end;                    {end with adoqryGZLL2}
                   Next;
                 end;                      {end for(i)}
               end;
               Active := False;
               //EmptyRec := IsEmpty;
             end;                          {end with adoqryGZLL}
             Result := 1;
           end;                            {end case(0)}
         1: {非根节点,取本层的子节点以及孙节点,相当于刷新}
           begin
             trvNode := aNode;
             {如果有子节点,先把所有的删除}
             if trvNode.HasChildren then
             begin
               {for i := 0 to trvNode.Count-1 do
                 wintelconst.prcFreeNodeData(trvNode.Item[i],False); }
               trvNode.DeleteChildren;
             end;
             with adoqryGZLLL21 do         {子节点}
             begin
               Active := False;
               Filter := '';
               Filtered := False;
               SQL.Clear;
               SQL.Append(Format(wintelconst.cSQLGZLLLevel2,
                 [PGZLLNodeData(trvNode.Data)^.ID]));
               //SQL.Append(fun
               Active := True;
               Sort := 'id DESC';
               for I := 0 to RecordCount - 1 do
               begin
                 new(NodeData);
                 NodeData^.ID := FieldValues['id'];
                 NodeData^.fjr := FieldValues['fjr'];
                 curNode := trvGZLLreply.Items.AddChildObject(trvNode,
                   FieldValues['llzt'], NodeData); //curCNode :=
                 {取第二层节点}
                 with adoqryGZLLL22 do
                 begin
                   Active := False;
                   //SQL.Clear;
                   //SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
                   Parameters.ParamValues['ID'] :=
                     PGZLLNodeData(curNode.Data)^.ID;
                   Active := True;
                   Sort := 'id DESC';
                   if not IsEmpty then
                   begin
                     for j := 0 to RecordCount - 1 do
                     begin
                       new(NodeData);
                       NodeData^.ID := FieldValues['id'];
                       NodeData^.fjr := FieldValues['fjr'];
                       trvGZLLreply.Items.AddChildObject(curNode,
                         FieldValues['llzt'], NodeData); //curCNode :=
                       Next;
                     end;                  {end for(j)}
                   end;
                   Active := False;
                 end;                      {end with adoqryGZLL2}
                 Next;
               end;
               Active := False;
             end;                          {end with adoqryGZLL}
             Result := 1;
           end;                            {end case(1)}
       end;                                {end case}
     finally
       trvGZLLreply.Items.EndUpdate;       {开始刷新}
     end;
    end;