C#自定义控件编程轻松入门(1) - Go语言中文社区

C#自定义控件编程轻松入门(1)


前 言

话说,许多新手在接触C#的时候都觉得C#使用起来特别容易方便,相对C++来说没有那么多的繁琐,比如C++每次在使用一个函数,都要先在头文件中声明一遍,而C#声明和实现都在一起,立马可以用。而且不会一会要写指针一会儿要写引用,如果是遇到VC那些句柄就把头给搞大。

随着我们学习的深入,我们发现慢慢上手了,找到感觉了,于是就对C#现有的控件开始不那么满足了,提出要是有更丰富功能更强大的控件该多好,这样我们就能实现更加炫更加酷的功能以及界面。
但对于新手来说,写控件听起来貌似很有难度,很高大上,问题就出在两个地方:第一个就是自定义控件必须自己动手实现控件需要的方方方面面(如果只是简单的事件重载估计没有问题,关键的是中间还涉及到委托的使用),第二就是在实现的过程中需要GDI+的绘图,否则控件无法显示。

一、迈出第一步
有了这两个高山横亘在眼前,那么很多新手就基本放弃了,实际写自定义控件还是比较容易的,我只用一句话来概括你就明白了,那就是:编写一个自定义控件不是每个方面都必须实现的,什么都不做也可以。就好像我们定义一个类一样,一个空的类也是可以正常运行的,只不过它没有什么功能和作用。

那么有的人就会说,那一个空的类一个空的控件对于我来说有什么作用呢?我还不如不写!
那你就错了,这个空的控件已经帮助我们迈开了编写控件的第一步,而且最关键的是成功的打破了编写自定义控件的恐惧。它的成功运行(我这里是指不出错的运行),已经明白得告诉你,咱们编写自定义控件完全可以“量力而行”,有多少能力就实现多少功能。

比如,我基本只了解一些简单的C#属性,其余都不了解,那我们也可以编写自己的自定义控件,那我们就写一个背景颜色为蓝色的控件。
现假定我们建立了一个工程,里面有一个From1用来调用测试我们的编写的自定义控件,我们在工程中添加一个继承自Control的类myControl,添加好了直接点击运行,那么一定不会报错,但我们会在工具栏中发现那个什么也没有的控件。
在这里插入图片描述
接下来我们就来实现我们的控件蓝色背景的代码:

 using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

namespace userControlTest
{
    class myControl: Control
    {
        public myControl()
        {
            this.BackColor = Color.Blue;
         }
     }
}

我们拖放一个myControl控件到Form1上看看效果,

在这里插入图片描述
编译运行后我们会发现它和我们用GDI+绘制的一个填充了的矩形没有任何差别。对鼠标以及键盘没有任何响应。这就是我们编写的自定义控件,我们已经取得了伟大的胜利,虽然是一个“丑陋的小板凳”,但它是我们自己亲手做的!

当然,如果你还对事件有所了解,后者至少知道怎么调用和重载,那么我们就继续来实现一个可以相应鼠标事件的控件。我们假设鼠标进入的时候背景色改变为绿色,离开的时候恢复正常即可。我们只要在myControl下重载鼠标的相关事件,代码如下:

  protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);

        this.BackColor = Color.Green;
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        this.BackColor = Color.Blue;
    }

在这里插入图片描述
到这里为止,我们的摸索进展相当顺利,一些都那么自然,那么容易。这个时候,我们回过头来看看我们编写的自定义控件在控件属性框里的表现如何,右键我们的控件,看看它的属性:
在这里插入图片描述
再看看它的事件:
在这里插入图片描述
此时,我们发现,这些属性和事件我们从来没有重载更没有添加啊,怎么都那么齐全完备呢?
所以到这里,我们应该知道,编写自定义事件其实就是在C#为我们提供的模板的基础上进行个性化改装,也就是说,你没有能力改装的地方不去动它就行了,所以编写自定义控件是件很容易的事情。

有了这个理解和认识了,我们的内心是不是更强大了,不再担心自己不能编写自定义控件了吧。当然,要让我们的控件功能更强大一些,更靠近我们的设计目标,摆在眼前的两座高山是一定要征服的!

现在,假定我们有了更高的要求了,我们想通过我们自己编辑的一个控件属性来控制,当我们的鼠标进入到控件中时显示的颜色,而不是我们上面的就只能是绿色,我们通过属性可以设置为任意颜色。代码如下:

[Description("设置鼠标进入时的颜色")]  // 显示在属性设计视图中的描述 
[DefaultValue(typeof(Color), "Blue")] // 给予初始值 
public Color mouseEnterColor { get; set; }



protected override void OnMouseEnter(EventArgs e)
{
    base.OnMouseEnter(e);

    this.BackColor = this.mouseEnterColor; 
}

protected override void OnMouseLeave(EventArgs e)
{
    base.OnMouseLeave(e);
    this.BackColor = Color.Blue;
}

在这里插入图片描述
编译一下以后,我们可以在myControl属性中看到我们刚为控件增加的属性mouseEnterColor了,我们为其设置一个颜色,这里我们设置为粉棕色:
在这里插入图片描述
运行起来,我们发现果然鼠标进入后颜色变成了我们在属性中设置的颜色。当然,我们在代码中也是可以直接访问设置了,这里不赘述。
这里有几点要注意
1、如果我们要为属性增加一个描述,如上述代码那样,就必须增加一个using System.ComponentModel,否则在Description处就会报错。
2、DefaultValueAttribute will NOT automatically set your property.
It is used for display (in bold or not) and for resetting values.
3、我们所为控件增加的属性或者事件只有在编译后拖放到Form上的才具备那些功能和属性,编译前拖放上去的是不具备这些属性和功能的,别以为前面拖放会自动添加新功能,否则你会被这个“坑”彻底埋葬!
4、如果我们要设置属性的默认值,不是在DefaultValue里面或者通过InitializeComponent,而是通过构造函数来直接设置属性的默认值,暂时没有其他方法,建议不要去苦苦追寻他法。
5、我们在对Control内自带的属性进行操作的时候,不需要强制刷新,系统会自动更新。但我们自定义的属性则必须调用refresh强制更新。

我们现在使用的选项是系统自带的Color类型,如果是我们自己定义的类型,要设置属性为下拉框,则进行这样的设置:
private ControlStyle style = ControlStyle.ComboBox;
[Description(“控件样式”), DefaultValue(ControlStyle.ComboBox), Browsable(true)]

我们的自定义控件编写到这里,我们的信心更在充足了,那么我们可以着手对其外观进行改进了,这就需要我们了解GDI+的一些基本知识了,有决心攻克GDI+高山的伙伴们其实也不必害怕,可以参看我博文中的GDI+绘图的入门篇《VS2017中GDI+绘图轻松入门》,我想这些博文可以帮助你轻松攻克难关,这里我们就当做你已经了解了GDI+。

下面我们来重载控件的paint事件,装点一下控件的外观,我们让它呈现一个椭圆形,代码如下:
在构造函数中声明必要的变量

RectangleF btnRec;
        private Font strFont;
        public myControl()
        {
            this.Width = 100;
            this.Height = 60;
            this.OutLineColor = Color.Yellow;
            this.fillColor = Color.YellowGreen;
            this.TextColor = Color.White;
            btnRec = new RectangleF(0, 0, this.Width, this.Height);
            strFont = new Font("宋体", 9F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(134)));
        }

重载OnPaint事件,在其中绘制椭圆(并绘制控件标题文字)

protected override void OnPaint(PaintEventArgs pe)
    {

        base.OnPaint(pe);

        Graphics graphics = pe.Graphics;
        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        graphics.DrawEllipse(new Pen(this.OutLineColor), btnRec);
        graphics.FillEllipse(new SolidBrush(fillColor), btnRec);
        SolidBrush b = new SolidBrush(TextColor);
        graphics.DrawString(this.Text, strFont, b, new Rectangle(20, this.Height/2-4, this.Width, this.Height));
        graphics.Dispose();
    }

最后,依然在鼠标OnMouseEnter和OnMouseLeave中加入改变椭圆填充颜色的语句:

protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);

         this.fillColor=Color.Red;
       
        this.Refresh();
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        this.fillColor= Color.YellowGreen;
        this.Refresh();
    }

我们看到,拖放到Form中显示出如下图的效果,运行起来鼠标进入则变为红色:
在这里插入图片描述
运行效果:
在这里插入图片描述
到这里,我们已经取得了很大的进展,一路来,你已经是过关斩将了。下一步,我们将为我们的自定义控件添加自定义的事件,那将更加接近我们的设计目标了。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/haigear/article/details/85337491
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 22:45:01
  • 阅读 ( 861 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢