zoukankan      html  css  js  c++  java
  • TreeView的自定义绘制图标处理

          Treeview是一个很常用的Winform控件,它提供了结合复选框和图标的展示方式,而且有上下级节点的缩进,在开发中很方便实用。通常在使用中,通过指定一个图标列表控件(ImageList),把要填充的所有节点图标都放到该控件中,把Treeview的ImageList属性指向它,然后在程序中根据节点数据来指定对应的图标序号(或者名称),可以方便地实现图标的动态切换。但有时,节点的图标不是固定的,可能是程序中动态生成的,比如常见的颜色设置和GIS图例等功能,需要实时刷新节点的颜色和图案,显然,并不能把所有的节点图片预先存储在ImageList中,该怎么办呢?幸好,Treeview控件为我们提供了自定义绘制的接口。

      下面结合着以前写的一个图例控件,说明一下自定义绘制时的用法和要点,在此做个抛砖引玉。

      首先,要实现自定义绘制,需要设置Treeview.DrawMode属性,来指明绘制模式:

      Treeview.DrawMode = TreeViewDrawMode.OwnerDrawText;  //自定义绘制节点的文本和图标

      或

      Treeview.DrawMode = TreeViewDrawMode.OwnerDrawAll;  //自定义绘制节点的全部(包括节点虚线和复选框,以及节点展开和收缩时的+-号)

      在通常情况下,我们只需要绘制图标和文本就行,虚线和复选框由系统绘制,以下示例即采用TreeViewDrawMode.OwnerDrawText模式。

      其次,设置了绘制模式之后,需要实现节点绘制事件Treeview.DrawNode,该事件仅当 DrawMode 属性设置为 OwnerDrawAll 或 OwnerDrawText 的 TreeViewDrawMode 值时,才引发。另外,该事件是在绘制每一个节点时都触发,并非针对所有节点。

      该事件的声明为:public delegate void DrawTreeNodeEventHandler (Object sender,DrawTreeNodeEventArgs e),其中参数DrawTreeNodeEventArgs中包含了当前要绘制的节点对象,以及该节点的范围坐标等信息。

      在实现该方法时,主要负责处理两个事情:绘制图标和绘制文本,绘制的方法依靠参数DrawTreeNodeEventArgs中的Graphics对象句柄。示例代码如下:

    1 /// <summary>
    2 /// 自己绘制节点图标和文字
    3 /// </summary>
    4 /// <param name="sender"></param>
    5 /// <param name="e"></param>
    6   void legendTree_DrawNode(object sender, DrawTreeNodeEventArgs e)
    7 {
    8 Rectangle nodeRect = e.Node.Bounds; //节点区域
    9  
    10 Point drawPt = new Point(nodeRect.Location.X - 18, nodeRect.Location.Y); //绘制图标的起始位置
    11   Size imgSize = new Size(12, 12); //图片大小
    12 Rectangle imgRect = new Rectangle(drawPt, imgSize);
    13
    14 //--------绘制图片: 判断节点类型,并根据各节点的类型绘制不同的图片--------------------
    15 if (e.Node is DirectoryNode)
    16 {
    17 this.LegendIcon.Draw(e.Graphics, drawPt, 0);
    18 }
    19 else if (e.Node is LayerNode)
    20 {
    21 ....
    22 }
    23 else if (e.Node is ThemeNode)
    24 {
    25 ....
    26 }
    27 else
    28 {
    29
    30 }
    31
    32 //-----------------------绘制文本 -------------------------------
    33 Font nodeFont = e.Node.NodeFont;
    34 if (nodeFont == null)
    35 nodeFont = ((TreeView)sender).Font;
    36 Brush textBrush = SystemBrushes.WindowText;
    37 if (mapView.MapObject.ReadOnly)
    38 textBrush = SystemBrushes.GrayText; //如果不可编辑,则将字体颜色置灰
    39 //反色突出显示
    40 if ((e.State & TreeNodeStates.Focused) != 0)
    41 textBrush = SystemBrushes.Window;
    42 //不限定文本区域,以免大字体时长文本被截取----edited by: Vivi 2009/11/19
    43 e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, Rectangle.Inflate(nodeRect, 2, 0));
    44 }

    在绘制过程中,一定要注意控制图标的起点位置,以及图标填充的范围大小,另外,如果有些固定的图标可以放到ImageList中或者是本地图片文件中,也可以通过图片操作的相关类进行绘制,从而获得更大的操作灵活性。

    绘制后的效果如下:

    注意:在绘制过程中,要注意的一个问题是性能和效率问题,由于实时绘制和频繁调用,在大数据量时应该尽量避免,如果在绘制中使用e.Graphics.GetHdc(),则一定要记得在使用之后调用e.Graphics.ReleaseHdc()。

  • 相关阅读:
    剑指offer51-正则表达式匹配
    剑指offer50-构建乘积数组
    剑指offer49-数组中的重复
    PHP系列笔记——Zend_Controller工作流程
    多态与重载
    读取文件数据的大概流程
    基于HTTP协议下载文件的实现
    C++中的面向对象笔记
    firebreath注册接口
    python读取excelxlsx,写入excel
  • 原文地址:https://www.cnblogs.com/qingteng1983/p/Treeview.html
Copyright © 2011-2022 走看看