前言

以前看别人的控件好看只有羡慕的份;以前觉得控件重绘是个很复杂的东西;以前知道MSDN很全面很专业却一直没有好好用起来;

作为初级程序猿,不能原地踏步,来吧,让我们一起把 TreeView 美化一下,每天进步一点点! 

要点

1、WinForm自定义控件

2、重绘

3、MSDN使用

基础准备:利用MSDN查找我们需要的资料

1、进入MSDN技术资料库:http://msdn.microsoft.com/library

2、在右上角搜索栏里输入 TreeView

3、找到TreeView类(System.Windows.Forms)这一条【应该是搜索结果里的第二条】,里面详尽的介绍了这个类

这里直接附上地址:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.treeview(v=vs.110).aspx

4、TreeView的方法、属性、事件等可以大概浏览下,知道有这个东西就行,继续往下看,我发现了我们需要的东西:

来吧,给你的Winform列表控件画个妆

这里的意思是我们可以完全自定义TreeView的外观有2个要点:

  一个是将DrawMode属性设置为TreeViewDrawMode.Normal以外的值;

  一个是在DrawNode事件里我们可以进行对控件的皮肤修改

5、那DrawNode事件怎么用呢?截图中我们看到末尾的 DrawNode 字样是个超级链接,果断点进去一看究竟,于是发现了如下描述:

来吧,给你的Winform列表控件画个妆

6、这段文字很详尽的介绍了DrawNode事件,我们可以总结出3个要点:

  a、TreeView提供2种自定义模式,分别是OwnerDrawText和OwnerDrawAll。

          OwnerDrawText:允许我们自定义节点的字体样式

          OwnerDrawAll:允许我们自定义节点的所有元素样式,包括字体、背景、图标等

  b、TreeNode有2个区域的概念:分别是【点击测试区域】和【整行区域】(整行区域这个名字自己取的,大家只要知道什么意思就行),来张图更容易理解

           来吧,给你的Winform列表控件画个妆可能区域的范围图中不是很精确,但是我们能够大概的知道 【整行区域】 是这个节点这一行所有的面积,而 【点击测试区域】    是这个节点所有表现元素(图标+字体)所占的面积,从名字上我们也大概可以猜到这个【点击测试区域】跟用户鼠标点击的位置和对应的表现行为(单击选中,双击展开等)有关。

  c、在DrawNode事件中,参数 DrawTreeNodeEventArgs.Bounds 我们可以获取到节点的【整行区域】,而 DrawTreeNodeEventArgs.Node.Bounds 我们可以获取到节点的【点击测试区域】

7、我们MSDN网页继续向下看,发现还有一段代码示例如下:

  ps:示例什么的最好了,又直接又快捷,你懂的。而且MSDN里面的代码考虑都能周全,copy下来直接放到新建的程序里稍作调整就可以直接运行看到效果,然后我们可以逐行慢慢分析理解

using System;
using System.Drawing;
using System.Windows.Forms;

public class TreeViewOwnerDraw : Form
{
    private TreeView myTreeView;

    // Create a Font object for the node tags.
    Font tagFont = new Font("Helvetica", 8, FontStyle.Bold);

    public TreeViewOwnerDraw()
    {
        // Create and initialize the TreeView control.
        myTreeView = new TreeView();
        myTreeView.Dock = DockStyle.Fill;
        myTreeView.BackColor = Color.Tan;
        myTreeView.CheckBoxes = true;

        // Add nodes to the TreeView control.
        TreeNode node;
        for (int x = 1; x < 4; ++x)
        {
            // Add a root node to the TreeView control.
            node = myTreeView.Nodes.Add(String.Format("Task {0}", x));
            for (int y = 1; y < 4; ++y)
            {
                // Add a child node to the root node.
                node.Nodes.Add(String.Format("Subtask {0}", y));
            }
        }
        myTreeView.ExpandAll();

        // Add tags containing alert messages to a few nodes 
        // and set the node background color to highlight them.
        myTreeView.Nodes[1].Nodes[0].Tag = "urgent!";
        myTreeView.Nodes[1].Nodes[0].BackColor = Color.Yellow;
        myTreeView.SelectedNode = myTreeView.Nodes[1].Nodes[0];
        myTreeView.Nodes[2].Nodes[1].Tag = "urgent!";
        myTreeView.Nodes[2].Nodes[1].BackColor = Color.Yellow;

        // Configure the TreeView control for owner-draw and add
        // a handler for the DrawNode event.
        myTreeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
        myTreeView.DrawNode += 
            new DrawTreeNodeEventHandler(myTreeView_DrawNode);

        // Add a handler for the MouseDown event so that a node can be 
        // selected by clicking the tag text as well as the node text.
        myTreeView.MouseDown += new MouseEventHandler(myTreeView_MouseDown);

        // Initialize the form and add the TreeView control to it.
        this.ClientSize = new Size(292, 273);
        this.Controls.Add(myTreeView);
    }

    // Clean up any resources being used.        
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            tagFont.Dispose();
        }
        base.Dispose(disposing);
    }

    [STAThreadAttribute()]
    static void Main() 
    {
        Application.Run(new TreeViewOwnerDraw());
    }

    // Draws a node.
    private void myTreeView_DrawNode(
        object sender, DrawTreeNodeEventArgs e)
    {
        // Draw the background and node text for a selected node.
        if ((e.State & TreeNodeStates.Selected) != 0)
        {
            // Draw the background of the selected node. The NodeBounds
            // method makes the highlight rectangle large enough to
            // include the text of a node tag, if one is present.
            e.Graphics.FillRectangle(Brushes.Green, NodeBounds(e.Node));

            // Retrieve the node font. If the node font has not been set,
            // use the TreeView font.
            Font nodeFont = e.Node.NodeFont;
            if (nodeFont == null) nodeFont = ((TreeView)sender).Font;

            // Draw the node text.
            e.Graphics.DrawString(e.Node.Text, nodeFont, Brushes.White,
                Rectangle.Inflate(e.Bounds, 2, 0));
        }

        // Use the default background and node text.
        else 
        {
            e.DrawDefault = true;
        }

        // If a node tag is present, draw its string representation 
        // to the right of the label text.
        if (e.Node.Tag != null)
        {
            e.Graphics.DrawString(e.Node.Tag.ToString(), tagFont,
                Brushes.Yellow, e.Bounds.Right + 2, e.Bounds.Top);
        }

        // If the node has focus, draw the focus rectangle large, making
        // it large enough to include the text of the node tag, if present.
        if ((e.State & TreeNodeStates.Focused) != 0)
        {
            using (Pen focusPen = new Pen(Color.Black))
            {
                focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
                Rectangle focusBounds = NodeBounds(e.Node);
                focusBounds.Size = new Size(focusBounds.Width - 1, 
                focusBounds.Height - 1);
                e.Graphics.DrawRectangle(focusPen, focusBounds);
            }
        }
    }

    // Selects a node that is clicked on its label or tag text.
    private void myTreeView_MouseDown(object sender, MouseEventArgs e)
    {
        TreeNode clickedNode = myTreeView.GetNodeAt(e.X, e.Y);
        if (NodeBounds(clickedNode).Contains(e.X, e.Y))
        {
            myTreeView.SelectedNode = clickedNode;
        }
    }

    // Returns the bounds of the specified node, including the region 
    // occupied by the node label and any node tag displayed.
    private Rectangle NodeBounds(TreeNode node)
    {
        // Set the return value to the normal node bounds.
        Rectangle bounds = node.Bounds;
        if (node.Tag != null)
        {
            // Retrieve a Graphics object from the TreeView handle
            // and use it to calculate the display width of the tag.
            Graphics g = myTreeView.CreateGraphics(); 
            int tagWidth = (int)g.MeasureString
                (node.Tag.ToString(), tagFont).Width + 6;

            // Adjust the node bounds using the calculated value.
            bounds.Offset(tagWidth/2, 0);
            bounds = Rectangle.Inflate(bounds, tagWidth/2, 0);
            g.Dispose();
         }

        return bounds;

    }

}
View Code

相关文章:

  • 2021-07-28
  • 2021-12-02
  • 2021-12-27
  • 2022-12-23
  • 2021-08-08
  • 2022-12-23
  • 2021-09-01
猜你喜欢
  • 2021-09-08
  • 2022-12-23
  • 2021-05-21
  • 2022-12-23
  • 2021-05-20
  • 2021-11-01
  • 2022-12-23
相关资源
相似解决方案