数据库字段
code      name
--------------------------------
110000    北京市
110100     市辖区
110101      东城区
110102      西城区
110103      崇文区
110104      宣武区
120000    天津市
440000    广东省
440100     广州市
450000    广西壮族自治区
450100     南宁市
450101      市辖区
450102       兴宁区
450102107         五塘镇
450102107201        西龙村委会
450102107202        英广村委会
450102107203        永宁村委会
--------------------------------
代码的规则是:2-2-2-3-3要解决的问题是:生成树型结构,选择树节点时获取code来查询数据库内容(怎么获取TreeView的Data数据)我根据网上的代码修改,老是会提示出错unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, DB, ADODB, StdCtrls;
type
  PMyRec=^TMyRec; //记录类型的指针变量
  TMyRec=record //声明一个记录类型
  ID: string;
  AddressName: string;
end;type
  TForm1 = class(TForm)
    con1: TADOConnection;
    qry1: TADOQuery;
    tv1: TTreeView;
    btn1: TButton;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure tv1Change(Sender: TObject; Node: TTreeNode);
  private
    { Private declarations }
  public
    { Public declarations }
    function LoadCode(crTbl: TADOQuery):Integer;
    function GetLevel(sFormat,sCode:String):Integer;  end;var
  Form1: TForm1;const
  CodeRule = '22233';    //单位代码规则
  SFirstNodeTxt   = '全国';   //首节点显示的文字implementation{$R *.dfm}function TForm1.GetLevel(sFormat, sCode: String): Integer;
var
  i,Level,iLen:Integer;
begin
  Level:=-1;//如果代码不符合标准,则返回-1
  iLen:=0;
  if (sFormat<>'')and(sCode<>'')then
  for i:=1 to Length(sFormat) do
  begin
    iLen:=iLen+StrToInt(sFormat[i]);
    if Length(sCode)=iLen then
    begin
      Level:=i;
      Break;
    end;
  end;
  Result:=Level;
end;function TForm1.LoadCode(crTbl: TADOQuery): Integer;
var
  MyRecPtr: PMyRec;
  TreeViewIndex: LongInt;
  i,Level:Integer;
  MyNode:array[0..6]of TTreeNode;
begin
  Screen.Cursor:=crHourGlass;
  Level:=0;
  New(MyRecPtr);
  With crTbl do
  begin
    try
      if not Active then Open;
        First;
      tv1.Items.Clear;
      //以下是增加第一项
      MyNode[Level]:=tv1.Items.Add(tv1.TopItem,SFirstNodeTxt);
      MyNode[Level].ImageIndex:=0;
      MyNode[Level].SelectedIndex:=0;      //以上是增加第一项
      While Not Eof do
      begin
        MyRecPtr^.ID := Trim(FieldByName('code').AsString);
        MyRecPtr^.AddressName:= Trim(FieldByName('name').AsString);
        Level:=GetLevel(CodeRule,MyRecPtr^.ID); //返回代码的级数
        //以下是增加子项
        //以下用上一级节点为父节点添加子节点
        if Level>0 then//确保代码符合标准
        begin
          MyNode[Level]:=tv1.Items.AddChildObject(MyNode[Level-1],
                   MyRecPtr^.AddressName, MyRecPtr);
          //cur_node:=tvAddress.Items.AddChild(MyNode[Level-1],ShowTxt);
          MyNode[Level].ImageIndex:=1;
          MyNode[Level].SelectedIndex:=2;
          MyNode[Level].Data:= MyRecPtr;
        end;
        //以上是增加子项
        Next;
      end;
    finally
      Close;
    end;
  end;
  MyNode[0].Expand(False);//将首节点展开
  Screen.Cursor:=crDefault;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
  with qry1 do
  begin   
  SQL.Add('select code,name from tunitinfo order by code');
  Open;   
  LoadCode(qry1);
  end;
end;procedure TForm1.tv1Change(Sender: TObject; Node: TTreeNode);
begin
  Edit1.Text:=PMyRec(tv1.Selected.Data).id;
end;end.

解决方案 »

  1.   

    全局 
    var
      PMyRec1: pointer;procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
    begin
      PMyRec1:= Node.Data;
      showmessage(TMyRec(PMyRec1^).AddressName);
    end;
      

  2.   

    PMyRec1是FORM的成员较好,全局的话麻烦(内存)
      

  3.   

      ID: string;
      AddressName: string;
    将string类型改为 array [0..254] of char,生命周期结束,string类型访问不到
      

  4.   

    你的树挂上Data后,没有得到安全释放,这有可能会产生严重问题。
      

  5.   

    你的树挂上Data后,没有得到安全释放,这有可能会产生严重问题。
      

  6.   

    給你一個demo,參考之:
    1.生成tree過程:procedure TRES_BOM_VIEW_F.CREATETREEVIEWMODEL;
    var
      iLoop:Integer;
      Master,MasterNode:TTreeNode;
    begin
      adoq_getop.Close;
      //SELECT distinct PARN_TYP FROM WWW where parn_typ<>'.' and parn_typ is not null order by PARN_TYP desc
      adoq_getop.SQL.Text:='SELECT distinct PARN_TYP FROM WWW where parn_typ<>''.'' and parn_typ is not null order by PARN_TYP desc';
      adoq_getop.Open;
      adoq_getop.First;
      cx_TV.Items.BeginUpdate;
      cx_TV.Items.Clear;
      Master:=cx_TV.Items.Add(nil,'昆盈BOM表檢視');
      while not adoq_getop.Eof do
      begin
        if adoq_getop.FieldByName('PARN_TYP').AsString<>'' then
        begin
          Screen.Cursor:=crSQLWait;
          MasterNode:=cx_TV.Items.AddChild(Master,VarToStr(adoq_getop.FieldValues['PARN_TYP']));
          Application.ProcessMessages;
          qry_op.Close;
          qry_op.SQL.Text:='SELECT DISTINCT PARN_LITM FROM WWW WHERE PARN_TYP='''+ VarToStr(adoq_getop.FieldValues['PARN_TYP'])+''' GROUP BY PARN_LITM';
          qry_op.Open;
          for iLoop:=0 to qry_op.RecordCount -1 do
          begin
            cx_TV.Items.AddChild(MasterNode,VarToStr(qry_op.FieldValues['PARN_LITM']));
            qry_op.Next;
          end;
          Application.ProcessMessages;
          cx_TV.Items.EndUpdate;
          Screen.Cursor:=crDefault;
        end;
        adoq_getop.Next;
        Application.ProcessMessages;
      end;
     {
      ThreadTView:=cx_TV;
      ViewThread:=TExpandLH.Create;
      ViewThread.Resume;
      }
    end;
      

  7.   

    2.調用過程,生成tree:procedure TRES_BOM_VIEW_F.btnSB_SearchClick(Sender: TObject);
    begin
      inherited;
      try
        RES_LOADING_F:=TRES_LOADING_F.Create(Self);
        RES_LOADING_F.Label1.Caption:='正在檢索相關數據......';
        RES_LOADING_F.Show;
        RES_LOADING_F.Update;
        CREATETREEVIEWMODEL;
      finally
        RES_LOADING_F.Close;
      end;
    end;
      

  8.   

    3.生成树型结构,选择树节点时获取code来查询数据库内容(怎么获取TreeView的Data数据)???最簡單的做法:procedure TRES_BOM_VIEW_F.cx_TVChange(Sender: TObject; Node: TTreeNode);
    begin
      inherited;
      if (cx_TV.Parent<>nil) and Assigned(cx_TV.Selected) and (cx_TV.Selected.Level=1) and (cxPageControl1.ActivePage=cxTabSheet5) then //機種不同明細
      begin
        try
          RES_LOADING_F:=TRES_LOADING_F.Create(Self);
          RES_LOADING_F.Label1.Caption:='正在檢索機種明細數據......';
          RES_LOADING_F.Show;
          RES_LOADING_F.Update;
          Application.ProcessMessages;
          adoq_information.Close;
          adoq_information.SQL.Text:='SELECT A.PARN_TYP,A.PARN_LITM,B.PARN_DSC,B.CHLD_LITM,B.CHLD_DSC,B.EFT_FROM,B.EFT_TO,B.QYT,B.LOCATOR,B.PIN_NO,B.ECO_NO '+
                                   ' FROM RES_BOM_LH A LEFT JOIN (SELECT CHLD_LITM,MAX(PARN_DSC)AS PARN_DSC,MAX(EFT_FROM)AS EFT_FROM,MAX(EFT_TO)AS EFT_TO,MAX(CHLD_DSC)AS CHLD_DSC,MAX(QYT)AS QYT,MAX(LOCATOR)AS LOCATOR,MAX(PIN_NO)AS PIN_NO,MAX(ECO_NO)AS ECO_NO '+
                                   ' FROM RES_BOM_LH GROUP BY CHLD_LITM)B ON A.PARN_LITM=B.CHLD_LITM WHERE PARN_TYP='''+ VarToStr(cx_TV.Selected.Text)+''' GROUP BY A.PARN_TYP,A.PARN_LITM,B.PARN_DSC,B.CHLD_LITM,B.CHLD_DSC,B.EFT_FROM,B.EFT_TO,B.QYT,B.LOCATOR,B.PIN_NO,B.ECO_NO ORDER BY A.PARN_LITM';
          adoq_information.Open;
          cxGrid5DBBandedTableView1Column1.DataBinding.FieldName:='';
          cxGrid5DBBandedTableView1Column2.DataBinding.FieldName:='PARN_TYP';
          cxGrid5DBBandedTableView1Column3.DataBinding.FieldName:='PARN_DSC';
          cxGrid5DBBandedTableView1Column4.DataBinding.FieldName:='PARN_LITM';
          cxGrid5DBBandedTableView1Column5.DataBinding.FieldName:='CHLD_DSC';
          cxGrid5DBBandedTableView1Column6.DataBinding.FieldName:='EFT_FROM';
          cxGrid5DBBandedTableView1Column7.DataBinding.FieldName:='EFT_TO';
          cxGrid5DBBandedTableView1Column8.DataBinding.FieldName:='ECO_NO';
          cxGrid5DBBandedTableView1Column9.DataBinding.FieldName:='LOCATOR';
          cxGrid5DBBandedTableView1Column10.DataBinding.FieldName:='PIN_NO';
          cxGrid5DBBandedTableView1Column11.DataBinding.FieldName:='QYT';
          Application.ProcessMessages;
        finally
          RES_LOADING_F.Close;
        end;
      end;
    end;
      

  9.   

    ((飛飛VS玲玲)-居士):你给我例子是可以用,也可以用递归方式来完成,但是效率不高呀。(黄河古韵):你的树挂上Data后,没有得到安全释放,这有可能会产生严重问题。
    我查个资料别人也是这样结果,但不知怎样才能解决
      

  10.   


    效率不高??你可以變通一下嘛???源程序我是用多線程+遞歸完成的,數據量非常大。。我只是貼了一個demo程序,你完全可以把它寫成線程+遞歸再調用呀...