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

很多时候我们需要使用到自定义控件 而在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  == A llowType.Number)
16          {
17               // 如果输入是0-9 交由基方法处理 允许输入
18               if  (e.KeyChar  >=   ' 0 '   &&  e.KeyChar  <=   ' 9 ' )
19                  e.Handled  =   false ;
20          }
21           else   if  (_allowType == A llowType.Letter)
22          {
23               // 如果输入是A-Z或a-z 交由基方法处理 允许输入
24               if  (e.KeyChar  >=   ' A '   &&  e.KeyChar  <=   ' z ' )
25                  e.Handled  =   false ;
26          }
27           else   if  (_allowType  == A llowType.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),  0 0 this .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),  0 0 , Width  -   1 , Height  -   1 );
30      }
31       else
32          pevent.Graphics.FillEllipse( new  SolidBrush(BackColor),  0 0 , 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,  1 1 , 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,  1 1 , 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,  3 3 , Width  -   7 , Height  -   7 );
61          focusedDotPen.Dispose();
62      }
63 
64       // *********
65       // 控件外框
66       // **********
67      pevent.Graphics.DrawEllipse(Pens.Black,  0 0 , 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  }

 

 

你可能感兴趣的:(自定义控件)