• VirtualStringTree 动态建树/Checktree


    //相关生成代码,VirtualStringTree有点难入门,研究了二天半,终于入门了。

    PTagCustomListItem = ^TTagCustomListItem;

    TTagCustomListItem = record
        Name: string;
        Id: string;
    end;

    var
    MainFrm: TMainFrm;
    SysPath: string;
    List: TStringList;

    implementation

    {$R *.dfm}

    uses fDMfrm;

    procedure TMainFrm.BuildTree;
    begin
    List.Clear;
    Self.VirtualStringTree1.BeginUpdate;
    Self.VirtualStringTree1.Clear;
    DMfrm.UniQuery1.First;
    while not DMfrm.UniQuery1.Eof do
    begin
        AddTreeNode;
        DMfrm.UniQuery1.Next;
    end;
    Self.VirtualStringTree1.EndUpdate;

       {
          注:在这里把数据添加进树后,树里并不能显示出结点
          要在几个事件里写代码才行:
          OnInitNode:在这个事件里初始化结点,如指定复选框以及状态
          OnGetText:在这个事件里指定结点的显示文本
          OnGetPopupMenu:在这个事件里指定下拉菜单
          OnGetImageIndex:指定结点的图片索引
          OnFreeNode:释放结点时您要做的一些释放动作

          通过这些事件,才能把结点的显示情况描述清楚。而您的
          结构体是用来持有您每个结点的数据的。
       }

    end;

    procedure TMainFrm.AddTreeNode;
    var
    index: integer;
    RootNode, RNode, PRNode: PVirtualNode;
    MyRec: PTagCustomListItem;
    begin
    if DMfrm.UniQuery1.FieldByName('M_FatherCode').Value = '0' then
    begin
        RootNode := Self.VirtualStringTree1.AddChild(nil);
        RootNode.CheckType := ctTriStateCheckBox; // ctCheckbox
        RootNode.CheckState := csUncheckedNormal;
        MyRec := Self.VirtualStringTree1.GetNodeData(RootNode);
        MyRec^.Name := DMfrm.UniQuery1.FieldByName('M_name').Value;
        MyRec^.Id := DMfrm.UniQuery1.FieldByName('M_ID').Value;
    end
    else
    begin
        Index := List.IndexOf(DMfrm.UniQuery1.FieldByName('M_FatherCode').AsString);
        RNode := Self.VirtualStringTree1.AddChild
          (PVirtualNode(List.Objects[Index]));
        RNode.CheckType := ctTriStateCheckBox; // ctCheckbox
        RNode.CheckState := csUncheckedNormal;
        MyRec := Self.VirtualStringTree1.GetNodeData(RNode);
        MyRec^.Name := DMfrm.UniQuery1.FieldByName('M_name').Value;
        MyRec^.Id := DMfrm.UniQuery1.FieldByName('M_ID').Value;
    end;
    List.AddObject(DMfrm.UniQuery1.FieldByName('M_ID').AsString,
        TObject(RootNode));
    end;

    procedure TMainFrm.Button1Click(Sender: TObject);
    begin
    DMfrm.UniQuery1.Close;
    DMfrm.UniQuery1.Open;

    //此句非常关键,一开始,因这一句没写,N次报内存出错。我查了好久资料才试出来。默认为-1.没有设NodeDataSize的值肯定报错!至于为什么定为记录数呢,你遍历时就会明白。定少了,遍历肯定报错
    Self.VirtualStringTree1.NodeDataSize := DMfrm.UniQuery1.RecordCount;
    BuildTree;
    end;

    //树的遍历

    procedure TMainFrm.Button2Click(Sender: TObject);
    var
    _pNodeData: PTagCustomListItem;
    Node: PVirtualNode;
    begin
    Self.Memo1.Clear;
    Node := Self.VirtualStringTree1.GetFirst(False); // GetFirstSelected 与 GetNextSelected(Node) 的做法。
    _pNodeData := Self.VirtualStringTree1.GetNodeData(Node);
    while Assigned(_pNodeData) do
    begin
        if Node.CheckState in [csMixedNormal, csCheckedNormal] then
        begin
          Self.Memo1.Lines.Add(_pNodeData^.Id);
        end;
        Node := Self.VirtualStringTree1.GetNext(Node);
        _pNodeData := Self.VirtualStringTree1.GetNodeData(Node);
    end;
    end;

    {

    结点显示的图片索引。注意:要在结点显示图片必须TreeOptions.MiscOptions包含toCheckSuppot
    示例取点击结点的数据。注意:TreeOptions.SelectionOptions必须包含toRightClickSelect

    }

    procedure TMainFrm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    var
    Node: PVirtualNode;
    begin
    // 释放,我想出来的有效方法,但想不明白为什么要这样,(加了ReportMemoryLeaksOnShutdown:=True),不然就报内存泄漏
    Node := Self.VirtualStringTree1.GetFirst;
    while Assigned(Node) do
    begin
        Node := Self.VirtualStringTree1.GetNext(Node);
    end;
    //
    if List <> nil then
    begin
        List.Free;
        List := nil;
    end;
    end;

    procedure TMainFrm.FormCreate(Sender: TObject);
    begin
    SysPath := ExtractFilePath(ParamStr(0));
    List := TStringList.Create;
    end;

    procedure TMainFrm.VirtualStringTree1FreeNode(Sender: TBaseVirtualTree;
    Node: PVirtualNode);
    var
    Data: PTagCustomListItem;
    begin
    Data := Sender.GetNodeData(Node);
    if Assigned(Data) then
        Finalize(Data^);
    end;

    procedure TMainFrm.VirtualStringTree1GetText(Sender: TBaseVirtualTree;
    Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
    var CellText: string);
    var
    _pNodeData: PTagCustomListItem;
    begin
    _pNodeData := Sender.GetNodeData(Node);

    if Assigned(_pNodeData) then
        CellText := _pNodeData^.Name;
    end;

    {建多列
    Data := Sender.GetNodeData(Node);
    if Assigned(Data) then
    begin
        case Column of
          0:
            CellText := Data^.ID;
          1:
            CellText := Data^.Name;
          2:
            CellText := FormatFloat('0.00', Data^.NUM);
          3:
            CellText := Data^.BZ;
        end;
    end;
    }

    http://hi.baidu.com/vbz007/blog/item/c6f3efd378f250d1a8ec9a73.html

  • 相关阅读:
    C#委托 delegate
    认识反射
    【译】修改大XML文件的有效方法
    学习javascript并解读JQuery
    ASP.Net用户验证的实现
    渴望
    C++中常见的一些小问题总结(一)
    struts2:关于EL能够获得action的属性
    排序算法总结
    WebService开发实例
  • 原文地址:https://www.cnblogs.com/sunsoft/p/1966289.html
Copyright © 2020-2023  润新知