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

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

编辑:说三道四文库 发布时间:2017-02-23 01:27
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就可以了
思科 IBM 微软等巨头联合开发开源SDN项目OpenDaylight 巾帼不让须眉:2012年度云计算领域Top 10女性 中移动全力推进NFC 5月起乘公交可刷手机 支持Android与iOS,Qt 5.1 Alpha全新亮相 Google Play:劣质Android应用已无藏身之地! 360推出信用网站认证开放平台 联合百家协会围剿钓鱼网站 经验分享:百度测试架构师眼中的百度QA(一) 在线旅行服务行业开放API带来的新机遇 专访:悬疑恐怖游戏Year Walk美术及音效设计师 解密:微软都柏林数据中心的神秘“免费冷却”装置 云计算如何影响数字化营销? 榜单:十位帮我们打理数据的存储大佬 OpenStack Grizzly版发布 Comcast、CERN成为新会员 谷歌携Blink来势汹汹 WebKit将成明日黄花? 星巴克与苹果合作 顾客可免费下载付费App 微信回应信令争议 将启动2.5G网络优化计划 凤凰网CTO吴华鹏离职 先后供职长达10年 外媒:开发者每周编码时间仅19.1小时 AppGratis CEO现身说法:应用被苹果儆杀始末 一个Web设计师眼里的云计算 戴尔高管:服务器业务领先惠普五年时间 Hoodie:基于JS与CouchDB的超快速Web开发框架 设计优秀API的五大规则 盘点英特尔IDF2013第一天:技术产品新趋势 英雄组队去打怪!Nimble Quest开发团队访谈 云通讯平台打造本土Twilio 被逼无奈?传微软或明年秋发布iOS和Android版Office 欧洲各国政府将向大众开放公共数据 访联想云存储罗予晋:优化MooseFS,共建生态系统 磊友创始人赵霏:关于HTML5与Flash争执之我见 国际混乱C语言代码大赛优胜作品详解之“A clock in one line” 搞了这么久,java还在入门阶段,太麻烦了!我要放弃? 有条proc 的语句不会写,大家帮一下忙! thanks a lot. 关于sql server中money 字段的问题 我真的很着急,你们大家都不会吗?还没人理我的话,我只好下网看帮助了!! 请问有什么关于数据库开发的好书么? 请问,在FRAME页中点击IE“刷新”按钮后如何只刷新一个frame而不刷新整个页面?? 请教(无为):关于VC与XML 向各位大侠求救!VB6如何直接输出到打印机?(有关POS机) 请问哪里有InstallShield下载啊 在FRAME页中点击IE“刷新”按钮后,如何只刷新一个frame而不刷新整个页面?? 使用VC+ATL生成控件,在VB中设计时属性窗口设置的值保存不住,运行的时候可以保存,是什么问题 怎样在dephi中用ado调用视图 ~~~动态设置数据窗口~~~~~~~~~~~~~~~~~~~~~~~~~~~! 一两狂死郎之天衣有缝:我是琳琳,提问有关音量问题的人。请来一下!! 有关李维的ADO/MTS/COM的问题,求救! vc与xml 请教:vc与xml 如何做象IE里最大化按钮下的转动的“e"字母? help!!!!!!!高分。。关于applet和servlet通信一个问题 JVM INSTR pop ;什么意思?高手帮帮忙! 如何访问子数据窗口中文本控件的text属性。在线等待!!!!!!!!!! 有的程序Dialog控件比Visual C++所提供的要多,不只是如何实现的?是自己做的吗? 我编了一个用MODEM-MODEM拨号对传的程序。但端口检测不正确,不能拨号。 怎么用installshield 实现软件加密? 急!如何将含NULL的string给MEMO字段赋值 请教:为什么我在WinXP上装完了vs.net,却无法启动?点击出现vs的初始画面,然后什么都没了? 请问hresult的错误码的意思,在哪里可以找到? 有关ORACLE的数据链的问题 我是琳琳,刚才提问有关音量问题的人。如果用一个TrackBar控制左右音道如何解决? 如何控制控件的显示层次! 单文档程序中的对话框中要打印和预览,该如何编程 有人能想通这是怎么算出来的吗? 如何设定objfilesys 一两狂死郎之天衣有缝:如果用一个TrackBar控制左右音道如何解决? 华山论剑 If ((p + 5) / 5) Mod 2 = 0 Then ...出错 ADODB.Recordset 错误 '800a0e78' ???????大侠 有没有办法实现AOL的ICQ中的位于桌面左右并排挤掉所有窗口包括桌面?? 在edit1的edit1keydown事件中为何不能向应button1.click事件??? 希望不要看见DBGrid中的一行记录,但不是要删除她, how? 请问windows优化大师这种界面是用什么控件做的?什么地方有下载的? ■■关系同志们的命运啊,希望都参与讨论■■ 请问如何给一个窗口发送WM_LBUTTONDOWN? 谁能介绍几本SQL SEVER的好书呀,小弟感激不尽呀!!! 请问pdf 文件用什么软件才能打开。急急。。。。。 Access数据库加了密码后用ADO直接不能访问了,用ODBC可以,如何解决? 我不明白这两个程序的函数的作用讲解一下!!谢谢!! 怎么往数据库里添加记录》 why can't connect www.boost.org? 哪里有好的email地址搜索哦工具 关于动态字段的ACCESS查询 用什么胶水可以把小金属板粘在木板上?要很牢固 能长时间不会脱落 UV无影胶用什么品牌好呢,UV胶用于什么材质粘接呢?UV无影胶可用于玻璃与玻璃、玻璃与金属的粘接,只要是一面是透光的就可用,因为UV无影胶也叫紫外线固化胶,需要UV灯来固化.——安华商城— 一瓶二氧化碳有多重一般正常使用的二氧化碳气瓶,他的容积是多少? 一个圆柱形水桶的容积事24立方分米,底面积事8平方分米,装了3分之2通水,水面距桶口有( )分米.说出得数和算式哦 乙烯制备乙酸乙酯的过程中不可能遇到的反应类型是为什么. 如何制备乙烯,相关的反应原理以及方程式 互联网给你的生活带来了哪些方便快 乙烯和乙酸生成乙酸乙酯的反应方程式 液态氧,氮,氩,气体氧,氮,氩,二氧化碳,氢,乙炔,混合气有毒吗 一个圆柱体水桶,底面积是8平方分米,高7分米,装5分之3的水,装了多少升的水?一个圆柱体水桶,底面积是8平方分米,高7分米,装5分之3的水,装了多少升的水? PC产品用UV无影胶水粘接如何去掉就没有更好的办法了?应该有对策吧,看来还是我们对产品的了解不够,失误 一立方液氧能气化多少立方气态氧气 一个圆柱体水桶,底面积是8平方分米,高7分米,装5分之3的水,装了多少升的水? 怎么去除无影胶? 有没有哪家公司分析汽车漆涂料好一点的,最近公司想要把汽车漆涂料做一个改进,想要找家公司先分析一下我们现在用的汽车漆涂料怎么样? 一个水桶从里面量,底面积是16平方分米,高是3分米,这个水桶能盛水( )升 一个侧面展开是正方形的圆柱体,如 衣服上沾了UV无影胶水怎么清洗 哪里能做UV涂料配方分析的公司? 计算机网络可以分为? UV胶和无影胶是同义词,请问怎么清理.UV胶粘了之后,想清理掉.如何用类似浸泡的方式清理掉.用什么化学药品?或药水. 金属上能喷UV油漆吗 作文 令人感动的一件事要好,题材新, 怎么软化农机胶我的一种五金品使用了农机胶后,干了,我想把它分开,请问怎么可以把农机胶溶掉或是软化让我可以把五金平分开?最好是什么药水的!丙酮除外, 加热试管中碳酸氢铵:有刺激性气味气体生成,试管上有液滴生成.液滴是怎样产生的? 以积极的态度面对生活是什么意思? 橡胶软化油是否会对塑胶材料有腐蚀作用我现在的问题是,橡胶套上残留的油状物质,软化了产品的塑胶外壳(ABS+PC),想请教是软化油的原因吗?原理是什么? 碳酸氢铵固体在试管中加热,试管口有---说明生成了 做人有什么意义,工作意味着什么 实验室制取乙烯过程中产生的副产物的方程式制取乙烯的过程中产生SO2的方程式 将碳酸氢铵在试管中加热,使放出的气体依次通过盛有过量的过氧化纳 浓硫酸的容器,最后得到的气体是什么啊只有一种气体,是O2么?那铵气呢? 请你谈谈如何理解生活的意义和过一个好的生活 下图是实验室用来验证乙烯与氢气反应产物的装置,请回答下列问题 (1)此装置用来制取乙烯,其中包括下图是实验室用来验证乙烯与氢气反应产物的装置,请回答下列问题 (1)此装置用来制取乙 取少量碳酸氢铵固体装在试管中在酒精灯上加热,观察到的现象___,说明碳酸氢铵受热___,保存碳酸氢铵化肥应_ 节能灯灯胶完全干后用什么溶剂能够泡开?能够有用的答案另加100积分 实验室制取乙稀,问:能说明二氧化碳气体存在现象是? 乙烯制备乙酸乙酯的分步反应为什么 节能灯胶哪个厂家出产 工程队要修一条长200米,宽9米,厚20厘米的水泥路.如果每立方米需要混凝土2吨,那么修完这条水泥路共需要多少吨混凝土? 以乙烯为有机原料合成乙酸乙酯的各步反应方程,并注明反应类型共四个应该~ 提示:学校里哪些地方用了电?电给我们的学习、生活带来了哪些好处?用电时我们应该注意什么?请你有条理地写一篇介绍电在学校的应用的短文. 工程队要修一条长100米,宽8米,厚20厘米的水泥路,如果每立方米需要混凝土2.5顿,那么修完这条水泥路共需要多少吨混凝土? 无影胶水怎么使用好呢? 电给人类带来了什么好处? 修路队修一条宽8米,厚35厘米的水泥路.如果有混凝土280立方米,可以铺多少米长的路 将温将碳酸氢氨加热生成氨气,水,二氧化碳,现有碳酸氢铵1mol加热后恢复原状,求生成气体的体积,质量,密度,及与氢气的相对密度.将温度提高到200度又会怎样? 网络给学习和生活带来什么好处,出现了那些问题? 请问什么可以替代橡胶软化油? 乙烷加热分解生成乙烯和氧气,取乙烷部分分解后的反应混合物1体积,使其充分燃烧生成1.6体积的co2(同温同压),则乙烯的分解率是多少 电对人们有哪些好处 乙烯的实验室制备属于什么反应? 乙烯和乙烷混合气体共amol,与bmol的氧气共存一密闭容器,点燃后充分反应,乙烯和乙烷全部消耗完,乙烯和乙烷全部消耗完,得到CO和CO2的混合气体和45gH2O,试求:1.当a=1时,乙烯和乙烷的物质的量之 想问下哪种胶水粘ABS和橡胶或橡塑效果最理想? 用密度为1.5×10三次方kg/立方米的砖铺一条宽5m的路,砖的厚度是4cm,用载重6000kg的汽车运砖,每车砖最多能铺多长的路? 已知碳酸氢铵固体受热分解成氨气、二氧化碳和水蒸气,则该混合气体的平均相对分子质量为? 粘橡塑海绵用什么胶 C30商品混凝土7天强度是多少?2月26日浇筑砼,想在3月5日,上设备.看强度能不能达到75%-80%. 乙醇生成乙烯反应方程式? 304不锈钢板与橡胶片粘贴用什么胶水才能粘得牢固呢? 混凝土配比,粗砂每立方多重?12个立方的量大概要用多少方砂子和石头?常用强度C25的设计要求. 二氧化碳的单位是用什么来计算的一便写出他的符号
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn