说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

如何给运行中生成节点的treeview控件加图标?????

编辑:说三道四文库 发布时间:2017-08-18 05:30
HTML文档下载 WORD文档下载 PDF文档下载
在运行中生成treeview的节点,然后个他们加上imagelist里面的图标,使用不相同的索引值。可是,当点击字节点的时候,图标会改变成父节点的图标,只是为什么?怎样才能使父节点和子节点有不同,且不改变的图标?
要看效果:http://www.comprg.com.cn/wz055.htm

Delphi环境下灵活的数据库树表实现 

 林琪

   我们目前正在开发的军队武器装备科技档案信息管理网络系统是面对全军的,管理全军武器装备科技档案的信息管理网络系统,由于全军在武器装备科技档案的管理模式上千变万化,对管理系统的需求也不相同,特别是,从调研的结果看:各单位的项目分类(信息分类)的级数是不定的,因此实现时一方面要考虑到通用性,另一方面也要保证用户使用的灵活性。

  

1 数据结构设计

在设计时可以采用两种数据存储方式(数据结构)。

1)信息分类表采用一个分类作为表的一条记录的方式进行存储,并由父类编号建立各类之间的关系,即:

分类号 
 类的含义 
 父类的编号 
 
0001 
 计算机 
   
 
0002 
 无线电 
   
 
… … 
 … … 
 … … 
 

2)这种分类表结构的建立不用动态生成表结构,但使用时相对麻烦。我们采用以下的表结构建立信息分类关系。这样的结构可以实现任意级的树型结构,如M层的一个结构:其中M是本单位的分类最大深度。类号要唯一识别每一个类。最上一级的分类号为全宗号+本级的分类代号,其他任意级的类其类号都为上一级的分类号+本级的分类代号。用户根据本单位档案的信息分类情况输入类信息,由系统动态创建表。

信息分类号
 全宗号
 类1含义
 类2含义
 类M含义
 分类深度
 
0001
 Zzb20
 电子
 计算机
   
 2
 
0002
 Zzb20
 电子
 无线电
   
 2
 
0003
 Zzb20
 通信
 卫星
   
   
 
0004
 Zzb20
 通信
 遥感
   
   
 
C4
 C6
 C20
 C20
 C20
 C1
 
XXFLH
 QZH
 L1
 L2
 LM
 FLSD
 

       在下面的例子中由于安全要求,对数据库表的结构作了简化,同时只使用了一些模拟数据以作说明。

  

2 树表外形设计

       由于Delphi提供的树表控件比较简单,外观不很美观,因此需要作一些“修饰”工作。为了强调重点,忽略了数据库操作如查询等,在例程中只使用了有关树表控件。

1)增加色彩

一般的树表控件没有底图,没有色彩,因此首先要解决色彩问题。解决的方法就是在树表控伯的ONDraw事件响应中增加底图显示代码。

procedure TForm1.Tree1CustomDraw(Sender: TCustomTreeView; const ARect: TRect; var DefaultDraw: Boolean);

begin

     with tree1.Canvas do                        //取树表控件的显示底板

     begin

     brush.color:=RGB(200,200,255);              //设置画笔颜色

     FillRect(ARect);                               //填充底板

 
  

     end; 

end;

这里仅为树表控件设置的底板颜色,实际上还可以设置底图,但由于底图的色彩不易控制,在调整树表结点时,容易出现颜色混乱的情况,而且只设置其颜色使树表控件的显示更加简洁。但只在ONDraw事件中设置颜色是不够的,还需要在其子项(结点)的显示事件中增加以下代码:

procedure TForm1.Tree1CustomDrawItem(Sender: TCustomTreeView;

  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);

var

 Noderect:TRect;

begin

     with tree1.Canvas do

     begin

          case Node.Level of                  //根据不同的层次,设置不同的结点字体颜色

          0:   font.Color:=clBlue;

          …

          5:   font.Color:=clGreen;

          end;

      if node=tree1.Selected then       //为突出选中的结点,将选中结点字体颜色设置为红色

          font.Color:=clRed;

          NodeRect:=Node.DisplayRect(false);              //设置结点的显示方式

          brush.Color:=RGB(200,200,255);

          fillrect(NodeRect);                         //将结点的背景色与控件底板色设置为一致

     end;

end;

      

2)设置图标

       图像列表控件与树表控件可以算是“老搭档”,即为了显示不同层次的结点就需要为树表控件设置一个对应的图像列表,其设置方法比较简单,可以参见有关的Delphi程序设计手册。由于树结构层次不定,因此不能象常规的方法那样建立了树表与图像列表之间的关系即大功告成,这里还需要做的是建立树表结点与图像列表的关系,可以通过以下两个函数实现。

procedure TForm1.Tree1GetImageIndex(Sender: TObject; Node: TTreeNode);

begin

     node.ImageIndex:=node.Level;    //由结点的层次决定其对应图标在图像列表中的位置

end;

  

procedure TForm1.Tree1GetSelectedIndex(Sender: TObject; Node: TTreeNode);

begin

     node.SelectedIndex:=node.ImageIndex;

end;

  

3)  窗体激活事件响应

响应窗体激活事件时,需要作一些设置。由于在原系统中,此窗体涉及的功能和控件较多,许多功能的完成都需要激活另外的窗体。因此需要避免对数据库信息的重复设置。可以如下实现:

procedure TForm1.FormActivate(Sender: TObject);

var

 i:integer;

begin

 if first_in=false then            //区别是否首次激活,从而决定是否需要设置初始状态

 begin

  hint.Caption := '    提示: 正在准备,请稍候...';

  application.ProcessMessages ;

  tree1.Items.Clear;                    //设置第一个树表状态和颜色

  tree1.Color:=RGB(200,200,255);

  tree2.Items.Clear;                    //设置第一个树表状态和颜色

  tree2.Color:=RGB(100,200,255);

  qznode:=nil;                         //为了显示动态结构的分类层次,将各层树结点初始化为空

  for i:=0 to 5 do

   last_node[i]:=nil;

   stackdepth:=0;                       //设置栈初始深度为0

  show_tree1(0);          //调用show_tree1显示分类内容,参数0表示从第一层开始显示

  hint.Caption:='    提示: 数据成功调入';

  Application.ProcessMessages;

  end;

    first_in:=true;        

end;

  

4)  树表内容显示

由于树表结点层次的不确定,我们采用了递归显示的方法完成树表内容的显示。这里设置了4个变量,其含义为;

变量
 类型
 含义
 可选范围
 
cur_cds
 TQuery
 当前的查询集
 dbmd.qz,dbmd.fl1,dbmd.fl2,

dbmd.fl3,dbmd.fl4,dbmd.fl5
 
cur_str
 string
 当前的查询语句
   
 
num_str
 String
 当前的层次数查询语句
   
 
cur_level
 Integer
 当前层次
   
 
cur_node
 TTreeNode
 当前结点
   
 

这里利用栈确定父结点与子结点的关系,若某结点对应的分类深度比当前深度要大,就需要将此结点入栈,并惟此结点为父结点,以插入孩子结点方式递归地显示它的下一层结点,若当前层的结点都已显示完毕,就需要退栈,回到上一层次再作计算。主要的实现过程如下:

procedure TForm1.show_tree1(level:integer);

…                //变量声明

begin

  case level of              //根据输入参数,确定当前数据集、结点和查询语句

  0:

  begin

    cur_cds:=dbmd.qz;

    cur_node:=qznode;

    cur_str:='select distinct QZH from XXFLB ';

  end;

  1:

  begin

    cur_cds:=dbmd.fl1;

    cur_str:='select distinct L1 from XXFLB ';

    cur_str:=cur_str +' where  QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

  end;

  …

  end;

   cur_cds.close;                              //实现查询

   cur_cds.SQL.clear;

   cur_cds.SQL.Add(cur_str);

   cur_cds.open;

       for i:=1 to cur_cds.RecordCount do                     //遍历当前层的所有结点

          begin

            if level=0 then                             //若为第一层则调用add方法创建结点

               cur_node := tree1.Items.Add(cur_node,cur_cds.Fields.Fields[0].value)

            else                //否则,在上一结点基础上调用AddChild方法创建其子结点

      cur_node:=tree1.Items.AddChild(last_node[stackdepth-1],cur_cds.Fields.Fields[0].value);

          if level<5 then            //根据当前结点层次及结点内容确定当前类的分类深度

          begin

          case level of

          0:

          begin

          num_str:='select  FLSD from XXFLB ';

          num_str:=num_str +' where  QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

          end;

          1:

           …

          end;

          dbmd.sd.close;                               //执行深度查询

          dbmd.sd.SQL.Clear;

          dbmd.sd.sql.add(num_str);

          dbmd.sd.Open;

          val(dbmd.sd.Fields.Fields[0].value,cur_level,code); //取其深度

           if  cur_level>level then          //若当前层次未达到其分类深度

            begin

                      last_node[stackdepth]:=cur_node;     //当前结点入栈

                      stackdepth:=stackdepth+1;

                      show_tree1(level+1);                       //递归显示下一层次结点

             end;

           end;

           cur_cds.Next;          //取当前结果集中的下一条记录

           if i > cur_cds.RecordCount -1  then            //若当前层中全部记录显示完毕则退栈

                stackdepth:=stackdepth-1;

          end;

 
  

end; 

       另外第二个树表的内容显示的基本方法与此类似,所不同的是第二个树表的显示函数所带的参数为串型参数,该参数有两种可能,即为‘’或由点击第一个树表的事件产生串参数。若参数为空串,则要在第二个树表中显示所有项目,否则要根据参数创建过滤条件选择显示项目。具体方法可以参见源代码。

  

5)  树表调整

 
  

树表的调整即是对树表当前结点的条件,可以由两种事件产生,即树结点的扩展和点击树结点。由于一个全宗号下的分类种类很多,层次也可能很大,因此用户希望打开一个类时,与其无关的类就关闭,这样就可以保证仅有目前所选择的结点,而不需要用户利用滚动条在打开的结点中寻找。其实现要充分利用树结点的方法和属性。特别强调的是在对点击树表结点的响应事件中用到了结点的扩展方法,尽管对结点扩展事件的响应函数所实现的功能与之类似,但一定不能加入类似的结点扩展方法,如tree1.Selected.Expand(false)等,因为在扩展事件中调用扩展方法会导致事件循环,甚至死机。 

对第二个树表的调整与第一个树表的处理方式类似,但功能不同,这里不多介绍。

procedure TForm1.Tree1Click(Sender: TObject);

…                 //变量声明

begin

 if Tree1.Selected=nil then                  //若未选择结点,重置

 begin

   tree2.Items.Clear;

   tree2.Refresh;

   exit;

 end

 else

 begin

    tree2.Items.Clear;

    tree2.Refresh;

     str:=Tree1.Selected.Text;                   //取当前结点内容

     fatherNode:=Tree1.Selected.Parent;    //取当前结点父结点

     tempnode:=Tree1.Selected;                //设置当前结点

     while fatherNode<>nil do                  //由当前层开始关闭所有非当前结点,

//同时返回由其第一层祖先到当前结点所组成的串,作为第二个树表显示的参数。

      begin

           str:=fatherNode.Text+','+str;          //取父结点内容与当前结点内容联接

           usenode:=fatherNode.getFirstChild; //遍历父结点的所有儿子结点

           while usenode<>nil do

           begin

                if usenode<>tempnode then          //只要不是当前结点,则取消扩展状态

                   usenode.Collapse(true);

                usenode:=fatherNode.GetNextChild(usenode);

           end;

           tempnode:=fathernode;    //当前层结点处理完毕后,调整父结点为当前结点

           fathernode:=tempnode.Parent; //再取当前结点的父结点

      end;

      sibNode:=tree1.Items[0];          // 第一层结点的处理与其它层稍有差异

      while  sibNode<>nil do

      begin

        if  sibNode<>tempNode then

          sibNode.Collapse(true);

      sibNode:=sibNode.getNextSibling;

      end;

      tree1.Selected.Collapse(true);           //强制打开当前结点

      tree1.Selected.Expand(false);

      if tree1.Selected.HasChildren=false then   //若当前结点无孩子,

      begin

        show_tree2(str); //说明已构成一个完整的类,调用show_tree2函数实现第二个树表//的内容显示,参数str为完整的类名

        hint.Caption:='    提示: 数据成功调入';

        Application.ProcessMessages;

  end;

 end;

  

参考文献

1 徐新华,IDE和Object Pascal 语言,人民邮电出版社,1998.12 

2 郑城荣,曾凡奎等,Delphi 运行时间库RTL和组件库VCL技术参考,人民邮电出版社,1999.1 

1 徐新华,GUI编程技术,人民邮电出版社,1998.12
非常感谢!!!!
在你的treeview控件的Onchange事件中:
  if youttv.Selected<>nil then
    youttv.Selected.SelectedIndex:=youttv.Selected.ImageIndex;
即可保证图标不变。
treeview中的点有stateindex是选中后的图标值,你一定没改,所以是默认值,而你父图标可能也是默认值,所以一样了,你只要在生成子node 时同时设置imageindex和stateindex就可以了
在F#中将函数作为一等对象的值 PHP获取Google PR值 ASP.NET(C#)获取Google PR值 android.appwidget类剖析 Android NDK之JNI使用例子 RemoteViews - Android Widget开发入门 ASP.NET如何用正则表达式得到网站页面中的所有链接 PHP实现图形验证码案例(1) Android Widget开发实例-电量监控 Android自带Widget - Clock指针钟表源代码分析 C#实现文件批量改名工具 PHP利用Google Chart API生成饼图 PHP操作SQLite数据库 PHP利用DomDocument创建XML文件 ASP.NET如何加密/解密URL网址 如何使用C#读取csv文件 三步骤实现ASP.NET(C#)项目中添加谷歌(Google Map)地图 使用C# ASP.NET以FTP客户端方式下载文件 ASP.NET如何用C#代码检测手机浏览器 使用C#读取上传的Excel文件 新版本SQL Helper类 C#使用iTextsharp生成PDF 在.NET里用iTextSharp库生成PDF文档 用itextsharp将ASP.NET页面导出到PDF中 什么是JQuery-JQuery API jQuery入门指南-JQuery API jQuery的核心部分-JQuery API $(elements)-JQuery API $(expr, context)-JQuery API $(fn) -JQuery API $(html) -JQuery API 踩着阳光,接生拉灯! 踩着阳光,接生拉灯! 请教!如何将链接的下划线去掉! 怎样自已写程序代替printsetupDialog中的设置打印机、纸张大小、纵横向设置? 关于Pchar()GetMem()StrPcopy()-----[在线等待] 入门问题:我想短时间学习Asp.net,看什么书好???? 今天下午GOOGLE的网页图标好像改了,呵呵,终于有点新意了。。。。 请大家就03年企业信息化市场走势发表看法 怎么把日期型的字段转换成字符串? 求救,在线等待。 请问:win2000下怎么读写ASI槽,地址为358、359、35A? ADO 连接EXCEL 错误 !!!!!怎么解决 请问:win2000下怎么读写ASI槽,地址为358、359、35A? 在WIN2000下出现...... 文件拖动问题,高手进来,顺便散分 晕了!!高手们帮帮我啊,这个问题有这么难吗??要死人了,在这样明天可以看报纸了! vc如何使用ado,有简单例子即可! JDBC数据库联接的问题?(急) 怎样把一个textarea的大量文字分成几小块分别存在几个textarea里?? VB生成的EXE文件不在WINDOWS环境下能运行吗? 如何通过程序控制系统中的另一个程序界面 不使用dataset,能不能把DataGrid初始化成这样? 分配的内存是放在heap好还是放在stack上好???? 请大家帮帮忙,关于确定文件是否存在的问题。 高分求两个文件:分别为tlbimp.exe和excel.dll 50分一个 求教flash/存储卡开发 急救!如何再VB中把罗马数字和阿拉伯数字互相转换! dataGrid问题 在线等待 win2k server配了ad和dns后新开了很多端口,它们都是干什么的? 我的cb6怎么了?? 那位大哥能给我一个qq号?1000分酬谢? JBuilder7+Weblogic7+SQLServer2000的一个简单问题! 请问哪里有vfp的电子书? 3com Switch 1100 不能用了,怎么处理 急:怎样用crontab生成sa文件记录每天机器的耗内存情况? usb的通信问题,进者有分! 如何让WIN 2000 Prefession 装上服务器端 键盘delete怎么调用? 用Asp怎么得到用戶的機器名? 《Java与模式》一书作者的专栏 各位长老,如何修改本机的网关并让其立即生效? 关于数据表查询的问题? 创建二叉树及遍历的问题 高手请进! 研究生到底上些什么课,偶想知道,好明确自己的方向,请知道的朋友来谈谈。 如何在ASP.NET中连接PROGRESS数据库? VC中如何调用VB写的 DLL中的函数? 如何在程序背景中添加背景图片? postgreSQL中文问题 那里有informix的书下载 高分求助 MPEG4的视频问题 质壁分离后细胞体积如何变化?如果基本不变,那么腌制萝卜为什么萝卜体积变小? 绝句两个黄鹂鸣翠柳这首诗中两个相对的词语是什么再加上妙处是什么 一个物体在平衡力的作用下,为什么动能一定不变? 冷水机厂,制造出来的冷水机种类适用于多种工业吗? 玻璃融化不好有气泡怎么办? 莲花那_________,就像__________ 造句 什么是冷水机组? 读数时视线要与温度计液柱( )相平谢谢了, 物体在平衡力的作用下,物体的动能一定不变?是变还是不变?为什么? 杜甫《绝句》(两个黄鹂鸣翠柳)的平仄,急需,谢谢各位了. 怎么制作可以飞起来的气球女朋友过生,我想弄点可以飞的气球,一起去放飞.但是怎么让气球飞起来,怎么办! 用 娇娆 菡萏(荷花) 婆娑 喧噪 造句用 娇娆,菡萏(荷花),婆娑,喧噪写一段话 硫酸铁是什么颜色的? 有没有折射率为2.8左右的玻璃啊我普物实验测算出来玻璃折射率有2.8不知道与没有搞错 谁有关于荷花的成语并造句? 我刚做煤质分析,不清楚煤层样,火车煤,地销煤,原煤,都是什么煤? 我的谷歌地球一加载天气就是一把差这是怎么回事啊?我的谷歌地球一加载天气地球上就是很多差这是怎回事啊? 求一道物理题 一个物体在平衡力的作用下( ) A.它的动能一定不变 B.它的重求一道物理题 一个物体在平衡力的作用下( ) A.它的动能一定不变 B.它的重力势能一定不变 C.它的弹性势能一定 硫酸铁是什么颜色的? 有火能够煮饭,有口出力把气呼,两点偏旁回回数,又字见面哈哈笑.(打一个字)什么字? 帕米尔高原在哪? 《伯牙鼓琴》的相关成语 在线谷歌地球是显示当天的吗? 什么的帕米尔高原 伯牙鼓琴引出什么成语?请再说出历史上像伯牙和钟子期一样的知音. 国产“谷歌地球”是否可用? 帕米尔高原在哪里? 伯牙这样善于鼓琴,用积累到的成语夸夸他和他的琴声 夜幕降临.隐隐约约.飞鸟归林.皎洁.轮廓.大好月色.晓行夜宿造句 想知道:新疆维吾尔自治区 帕米尔高原 在哪 人的体细胞膜上有哪些蛋白质,有什么生理特性? 声音的响度与什么有关有三个空 造成碳碳单键,双键,叁键键长区别的原因 你就是传说中的SB吧. 响度与声音()有关 古诗鸟鸣涧的作者是谁?“闲”字用的好在哪里? 怎么分辨音调 为什么车超载时加速度会变小?高中物理不知道别乱讲、车的加速度不是一定的么(ug)?额、、是刹车时、忘了讲了、 怎么写自然的朋友这篇文章? 怎样区分音调和晌度,有什么关系? 月色 流水 风 用着三个词语写一段环境描写 怎样写? 仿照句式,以”荷花”为内容造句,并能体现一定的哲理例句:扫帚,一生都生活在尘埃中,但走过的路却是光明.洁净的.仿写:荷花,__________________. 歌曲的声调是怎么分辨的?急 某同学将氢氧化钠溶液,石灰水和盐酸倒入烧杯,溶液中的溶质组成假设1溶质:Nacl,cacl2.假设2:溶质为Nacl,cacl2,NaoH,ca(oH)2,假设3请补充一个合理假设 大连 新概念英语班求一个暑假英语班,教新概念的,大家都知道哪家开课,并且教的还可以,给我推荐推荐,对了, 土豆 细胞液水势 用丛丛芦苇,阵阵稻香,片片月色,古老石桥造句,至少用上一个修辞 关于飞机的过载知道战斗机要承受很大过载,关于过载的问题我越来越不明白了,0g和1g是什么情况?请问下面几种情况过载是多少飞机平飞,高度速度方向都不变直升机空中悬停飞机以一个理想 为什么保卫细胞钾离子的累计增加,水势降低而保卫细胞中氢离子增多,水势升高呢? 在经济衰退时应该采取什么财政政策 证明氢气中含有盐酸,水蒸气, 煤质指标评价一般用原煤还是浮煤评价? 肉元子如何做嫩怎么做好吃?很喜欢朋辈餐的元子,又嫩又滑,自己家里做始终觉得老老的、粗粗的,口感不好.猪肉元子如何做才好吃呢?请教有经验的网友, 超声波高于多少赫兹,鲸鱼受到影响 细胞发生质壁分离过程中,细胞体积的变化如何是不是 由大变小再变大说质壁分离就包括了质壁分离和质壁复原两个过程吗?还是只是指质壁分离? 蛋白肉怎么做好吃? LM1812能用40K赫兹的超声波报警接收吗?本人现在做一个超声波报警器,发现接收超声波电路很复杂,想用一个专用集成模块解决接收超声波问题.LM1812据说能用于超声波报警,但是适用频率范围貌 植物细胞失水时为什么会皱缩?质壁分离时细胞大小不是不会变化吗? 肉咋做好吃? 荷花像什么 造句 印度一鞭炮厂1日发生火灾 至少6人死澳使馆为美搜集亚太情报 中国是监听目美国务卿将于3日访埃及 穆尔西被罢黜俄男子在法庭引爆手榴弹 导致2人死亡外交部:美方澄清钓鱼岛共同防卫计划的俄男子在法庭引爆手榴弹 导致2人死亡中国驻日使馆表彰见义勇为留学生印将建高达182米世界最大雕像 高约印度古吉拉特邦建世界最大雕像 暗贬尼俄专家称俄罗斯人无法仅凭工资购买一套外交部:望澳方重视对华关系 视中国发律师称斯诺登可在俄境内就德国遭美监听中方对目前阶段销毁叙化武相关决定执行嫦娥三号月球探测器完成总装 正进行飞卜拉希米称日内瓦会议有望于数周内召开外交部:中方将与上合组织各方一道进一俄将向美驻阿富汗军队追加提供30架米俄一法庭发生爆炸致2死2伤公交司机因车速慢被打 打人者自称是警福州破获虚假恐怖信息致航班延误案 1《新快报》社高层调整 社长、总编及副江阴农商行等3公司首发上会足球高尔夫世界杯落幕今年首次成品油调价或继续暂缓难民受邀出席奥巴马国情咨文演说五年内放开成品油定价区政府门口的无证停车场说明了什么开发商无忧会否变成购房者之忧冯仔现身正佳DIY汉堡雀笼别话出轨几率,男女各占两成江山代有才人出 象棋也到换代时京东华南大客户2015年企业采购订单乌尔善确认不导《寻龙诀》续集户口迁入广州,港澳通行证怎么办?高校女教授炒股亏损恶意透支信用卡获刑全市率先完成企业锅炉“油改气”猪猪侠当起公益大使阿里公益启动第三届“年度公益记者”评大金钟路系上“花腰带”魔术师Yif渴望上春晚短期下跌空间有限
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘