很多时候我们需要使用到自定义控件 而在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), 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 }
1.首先在usercontrol后台添加如下代码:
public partial class UXUserControl: UserControl
{
//添加事件代理
public event EventHandler UXEvent;
//在需要响应的事件中添加
private void btn_MouseClick(object sender, MouseEventArgs e)
{
if (UXEvent!= null)
{
UXEvent(this, e);
//Or use :
//UXEvent(this, new EventArgs());
}
}
}
2.在窗体或页面添加一个用户控件,在Page_Load或Form_Load事件中添加:
private void Form1_Load(object sender, EventArgs e)
{
(UXUserControl)UC.UXEvent+= new EventHandler(uxEvent);
}
private void uxEvent(object sender, EventArgs e)
{
//do something(including send message to other user controls)
}