listbox,连treeview等控件的每一个选择项(节点)都有data指针,可以指向选择项对应的属性结构。
但是,这样,需要人为预先为所有的选择项分配空间存储选择项对应的属性,才能使用,最后还要释放这个空间,
如果选择项的数量是运行时增加或减少的,每次都得分配、使用、释放,麻烦而且容易疏漏。我是很希望当时borland能把这个指针类型的data改为string类型就好了,
这样,只要把选择项对应的属性编码为string就行了,省事多了——可以是xml,也可以是ini(name=value;...)
或者为选择项(节点)多增加一个datastring的属性。现在,只能退而求其次:如何为listbox/treeview的每一个选择项(节点)增加一个datastring的属性?
如果能不需要修改vcl的源代码,直接通过一个外部的pas文件实现,就最好了;
如果必需修改vcl的源代码,也最好是修改得最少最简洁的。

解决方案 »

  1.   

    有必要改源码吗TreeView1.Items.AddObject(nil,'abc',PChar('aaaaa'));ShowMessage(PChar(TreeView1.Selected.Data));
      

  2.   

    function AddChildObject(Node: TTreeNode; const S: string; Ptr: Pointer): TTreeNode;C++ syntax:TTreeNode* __fastcall AddChildObject(TTreeNode* Node, const AnsiString S, void * Ptr);DescriptionThe node is added as the last child of the node specified by the Node parameter. The S parameter specifies the Text property of the new node. The Ptr parameter specifies the Data property value of the new node. AddChildObject returns the node that has been added.Note: The memory referenced by Ptr is not freed when the tree nodes object is freed.不过试验了一下,好像没有内存泄漏。。
      

  3.   

    加个常量做 Ptr 当然不会有内存泄漏了
    当然,用string变量做 Ptr 也不会有内存泄漏,string生存期结束就自然被释放了,只不过再在别的地方引用PChar(Data)的时候容易蹦出来了错儿之类的
      

  4.   

    自己定义一个Class,在每个节点被删除的时候,自动释放Data指针指向的Class,很方便的,我很久以前就这样处理了,没有问题!
      

  5.   

    汗.VOID * DATA....这样不好.非要用STRING类型.晕.VOID也能直接用与AnsiString类的值的保存的.
    你把
    AnsiString pp;
    DATA=(Void *) pp;保存.用(AnsiString *) node->data;取值就行了.最后关闭时,删除.
      

  6.   


    我试验的是 一个动态生成的string的表达式,没有问题,————[1]
    如果把这个表达式先赋给一个局部string变量s,再把s赋给data或addChildObject(p,t,s),退出s所在的函数后,这个t对应的data是不是还有效?————[2]如果[2]有问题,addChildObject(p,t,''+s)是不是反而就没有问题了?delphi的string真的是很方便,就怕很多时候delphi的应用做服务容易出问题,是不是也就是string没处理好?
      

  7.   

    这个class是Ttreenode的派生还是Ttreeview的派生,如果是前者,使得Ttreeview使用你的class而不是原来的Ttreenode?
    如果一定要人为删除,是可以在Ttreeview的OnDelete事件里释放,但是感觉还是不太好——相比string的不用释放
    主要是 需要代码去删除,麻烦,容易疏漏。。
      

  8.   

    怎么个动态生成法?'abc'+'bcd'么?这还是一个常量字符串。
    还有是怎么试的,短字符串又没几行代码一般不会有啥问题;如果你给局部变量设个超过1M的长度,生存期结束之后的效果应该是立竿见影的
    ''+S 由一个编译器生成的临时局部变量来接收,还是局部变量的生存期string是很好用,了解它怎么运作之后也不会出问题。像这种地方应该用StrNew/StrDispose或者NewStr/DisposeStr之类管理,想偷懒的话还是换.net或者java吧
      

  9.   

    动态生成法==红色部分:
            c:=TVer.Items.AddChildObject(p,Qer.FieldByName('fname').AsString,
              pchar(makeTaskInfo(Qer.FieldByName('fid').AsString
                ,Qer.FieldByName('forder').AsString
                ,Qer.FieldByName('fdeleted').AsString
                ,Qer.FieldByName('fdept').AsString)
              )
    哦,不行!内存泄漏是没有,但是pchar(node.data)已经不是原来的字符串了,好像是后来处理的节点的。看来还是需要预先分配一个全局的字符串??
      

  10.   

    内存泄漏检测是明确的:
    ---------------------------
    xxxx.exe: Memory Leak Detected
    ---------------------------
    This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):21 - 28 bytes: TCriticalSection x 1
    61 - 68 bytes: TlogThread x 1
    (这2项是正常的)Note: To obtain a log file containing detail on memory leaks, enable the "FullDebugMode" and "LogMemoryLeakDetailToFile" conditional defines. To disable this memory leak check, undefine "EnableMemoryLeakReporting".---------------------------
    确定   
    ---------------------------
      

  11.   

    看来是白高兴一场开始没有泄漏,以为delphi对于string空间是以 被引用次数(降到0) 为自动释放的条件的
    看来还是没这么智能
      

  12.   

    没错啊,delphi是这么做的,只不过cast成指针类型不增加引用计数。而且这个也没法增加,因为转指针的时候判断增加好办,判断该怎么减少就难了另外,如果重用率挺高的,你又不是特在乎那点儿内存的话,用TStringList维护也许操作起来比StrNew/StrDispose简单,虽然后者也不一定多多少代码
      

  13.   

    我现在是使用 动态数组,每个元素是一个结构,node.data指向元素的下标(因为node是只增不减,要么是全部清除再重新加载)这样看来,由回到最初的希望了:Ttreenode增加一个string类型的属性
    这样是不用 分配、释放 的了
      

  14.   

    为Ttreenode增加一个string类型的属性DataString
    如果是新写一个Ttreenode类,如何让Ttreeview也能转用新类而不是原来的Ttreenode?
    还需要重新写一个Ttreeview?
    实在不想使用第三方的控件,哪怕是自己写的如果有类似面向方面的“切入”就好了,随时为已经存在的类增加一个属性、方法、方法的前置处理、后续处理。
    这个估计是得语言支持才行了
      

  15.   

    直接在comctrl.pas的Ttreenode的类定义里增加一个public的DataString:String;使用多天,好像没发现什么问题:
    可以直接使用treenode.datastring,最后也没有内存泄漏。看来只能这样了:简单,但是需要修改标志库的代码
      

  16.   

    treeview 是treenode 吧,要想有string 修改Ttreenode,在treeview里应该有个object数组吧,相应的修改下