C#.NET中自定义控件3种方式和需要注意的地方

来源:互联网 发布:奶茶店投资成本知乎 编辑:程序博客网 时间:2024/06/05 12:10

很多时候我们需要使用到自定义控件 而在C#中 我们主要以3中方式创建自定义控件,还有些需要注意的地方时常被忽略 比如Click事件,用户控件的Click并不像系统的Button单击

1.继承自.NET类库中已有的控件 如TextBox MenuStrip Pannel

2.继承自Control类

3.继承自UserControl类

 

下面是3个小示例

1.继承自类库中现有的控件

下面自定义一个ExtendTextBox 该控件扩展了一个属性,可以现在文本框只能输入数字,字母或者所有字符

 

复制代码
 1 public class ExtendTextBox : System.Windows.Forms.TextBox
 2 {
 3     private AllowType _allowType = AllowType.All;
 4     public AllowType AllowType
 5     {
 6         get { return _allowType; }
 7         set { _allowType = value; }
 8     }
 9 
10     protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
11     {
12         //设置此属性为true 基方法将不再处理此KeyPress事件
13         e.Handled = true;
14 
15         if (_allowType == AllowType.Number)
16         {
17             //如果输入是0-9 交由基方法处理 允许输入
18             if (e.KeyChar >= '0' && e.KeyChar <= '9')
19                 e.Handled = false;
20         }
21         else if (_allowType == AllowType.Letter)
22         {
23             //如果输入是A-Z或a-z 交由基方法处理 允许输入
24             if (e.KeyChar >= 'A' && e.KeyChar <= 'z')
25                 e.Handled = false;
26         }
27         else if (_allowType == AllowType.All)
28         {
29             e.Handled = false;
30         }
31         base.OnKeyPress(e);
32     }
33 }
34 public enum AllowType
35 {
36     Number,
37     Letter,
38     All
39 }
复制代码

 

 

2.继承自UserControl类 此方法主要用于编写组合控件 UserControl容器可以提供其组成控件的所有功能。可以编写代码指定新的用户控件可公开其子控件的哪些属性

UserControl支持直接将背景色设置为透明 而Control则不支持

 

public class UserControl1 : Usercontrol
{
}

 

3.继承自Control类 Control类提供基本控件功能,但不提供图形界面或任何特定功能 ,必须编写代码指定控件的属性 方法 事件,还必须重写OnPaint和OnPaintBackground方法以创建界面,通常需要使用到GDI+

Control 类实现向用户显示信息的类所需的最基本功能。它处理用户通过键盘和指针设备所进行的输入。它还处理消息路由和安全。虽然它并不实现绘制,但是它定义控件的边界(其位置和大小)。它提供窗口句柄 (hWnd)。

 

下面是一个椭圆按钮简单的例子 但是有几个地方是要引起注意的,关于自定义控件里由基类继承而来的Click事件,包括UserControl和Control Click事件是鼠标单击事件 鼠标左键单击和右键单击都将触发这个事件 如果没有定义双击事件 则双击控件将两次触发Click事件。这里的Click和.Net类库中的Button的Click事件是区别的 传统的Button按钮,鼠标左键单击才会响应 聚焦后按Enter键也会响应。而自定义控件里的Click事件不会响应键盘的Enter 并且鼠标左键或者右键的单击都会触发它 。所以要对其进行一些处理,例子中自定义了一个椭圆按钮 并且它不会对右键单击产生反应

1 public class EllipesButton : System.Windows.Forms.Control

字段和重写OnPaint和OnPaintBackground

 

复制代码
 1 private bool _mouseEntered;
 2 protected override void OnPaint(PaintEventArgs e)
 3 {
 4     //将文本绘制到正中央
 5     SizeF stringSize = e.Graphics.MeasureString(Text, Font);
 6     float startx = (Width - stringSize.Width) / 2;
 7     float starty = (Height - stringSize.Height) / 2;
 8     e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), startx, starty);
 9     base.OnPaint(e);
10 }
11 protected override void OnPaintBackground(PaintEventArgs pevent)
12 {
13     //绘制过程为 控件整体背景色->控件有效区背景色->控件状态表示区域->控件外框
14 
15     //**********
16     //控件整体背景色
17     //**********
18     if (this.Parent != null)
19         pevent.Graphics.FillRectangle(new SolidBrush(Parent.BackColor), 00this.Width, this.Height);
20     //使用高质量平滑模式消除椭圆边缘锯齿
21     pevent.Graphics.SmoothingMode = SmoothingMode.HighQuality;
22 
23     //***********
24     //控件有效区背景色
25     //************** Control.MouseButtons静态成员
26     if (_mouseEntered && (MouseButtons & MouseButtons.Left) == MouseButtons.Left)
27     {
28         Color mouseDownColor = Color.FromArgb(128, BackColor);
29         pevent.Graphics.FillEllipse(new SolidBrush(mouseDownColor), 00, Width - 1, Height - 1);
30     }
31     else
32         pevent.Graphics.FillEllipse(new SolidBrush(BackColor), 00, Width - 1, Height - 1);
33 
34     //***********
35     //控件状态表示区域
36     //************
37     //左键未按下时绘制状态表示区域
38     if ((MouseButtons & MouseButtons.Left) != MouseButtons.Left)
39     {
40         //鼠标进入 绘制橙色边框
41         if (_mouseEntered)
42         {
43             Pen mouseEnterPen = new Pen(Color.Orange, 2);
44             pevent.Graphics.DrawEllipse(mouseEnterPen, 11, Width - 3, Height - 3);
45             mouseEnterPen.Dispose();
46         }
47         //控件获得焦点 但鼠标未进入 绘制蓝色边框
48         else if (Focused)
49         {
50             Pen focusedPen = new Pen(Color.PowderBlue, 2);
51             pevent.Graphics.DrawEllipse(focusedPen, 11, Width - 3, Height - 3);
52             focusedPen.Dispose();
53         }
54     }
55     //如果有焦点,绘制焦点框
56     if (Focused)
57     {
58         Pen focusedDotPen = new Pen(Color.Black);
59         focusedDotPen.DashStyle = DashStyle.Dot;
60         pevent.Graphics.DrawEllipse(focusedDotPen, 33, Width - 7, Height - 7);
61         focusedDotPen.Dispose();
62     }
63 
64     //*********
65     //控件外框
66     //**********
67     pevent.Graphics.DrawEllipse(Pens.Black, 00, Width - 1, Height - 1);
68 
69     //base.OnPaintBackground(pevent);
70 }
复制代码

 

非关键代码

 

复制代码
 1 protected override void OnMouseEnter(EventArgs e)
 2 {
 3     _mouseEntered = true;
 4     this.Refresh();
 5     base.OnMouseEnter(e);
 6 }
 7 protected override void OnMouseLeave(EventArgs e)
 8 {
 9     _mouseEntered = false;
10     this.Refresh();
11     base.OnMouseLeave(e);
12 }
13 protected override void OnGotFocus(EventArgs e)
14 {
15     this.Refresh();
16     base.OnGotFocus(e);
17 }
18 protected override void OnLostFocus(EventArgs e)
19 {
20     this.Refresh();
21     base.OnLostFocus(e);
22 }
复制代码

 

 

需要注意的地方

复制代码
 1 //这里需要判断是左键还是右键按下
 2 protected override void OnMouseDown(MouseEventArgs e)
 3 {
 4     if (e.Button == MouseButtons.Left)
 5     {
 6         this.Focus();
 7         this.Refresh();
 8     }
 9     base.OnMouseDown(e);
10 }
11 protected override void OnMouseUp(MouseEventArgs e)
12 {
13     if (e.Button == MouseButtons.Left)
14         this.Refresh();
15     base.OnMouseUp(e);
16 }
17 //这里将消息对象强制转换为鼠标消息 判断是哪个键单击 只有当左键单击的时候才
18 //执行,Click事件的委托是由OnClick来调用的 所以通过判断消息决定是否触发Click
19 protected override void OnClick(EventArgs e)
20 {
21     MouseEventArgs m = (MouseEventArgs)e;
22     if (m.Button == MouseButtons.Left)
23         base.OnClick(e);
24 }
复制代码

 

原创粉丝点击