创建控件
本主题演示如何创建 Windows 窗体控件。它包括创建控件的基础知识。另外,本主题还包括向控件添加绘画逻辑、公开属性和事件、使用控件授权以及向控件添加设计时行为。本主题中包括以下主题方面:介绍 
入门 
添加属性、事件和元数据 
向“属性”窗口添加自定义编辑器 
扩展程序提供程序 
用户控件 
为控件授权 
注意:在 Microsoft .NET 框架 SDK 文档中的控件创建部分更详细地介绍了本主题中所涉及的内容。有两种类型的控件: 自定义控件:通过调用 Paint 事件中的 Graphics 对象来显示 UI 的控件。自定义控件通常从 Control 派生。Chart 控件是自定义控件的一个示例。对创建自定义控件提供有限的设计时支持。 
用户或复合控件:由其他控件组成的控件。用户控件从 UserControl 派生。使用 TextBox 控件显示客户地址的控件是用户控件的一个示例。对使用 Visual Studio .NET Windows 窗体设计器创建用户控件提供完全设计时支持。 
本主题中的大部分示例演示生成自定义控件。但是,有关公开属性和事件、定义设计时行为和授权的部分适用于自定义控件和用户控件。 入门
编写简单控件
下面的示例创建一个简单控件,该控件通过处理 Paint 事件显示其 Text 属性的值。为了创建此控件和处理事件,必须创建一个从 Control 继承的类,并创建一个重写 OnPaint 方法的方法。
public class HelloWorldControl : Control {    protected override void OnPaint(PaintEventArgs e) {        RectangleF rect = new RectangleF(ClientRectangle.X,
                                         ClientRectangle.Y,
                                         ClientRectangle.Width,
                                         ClientRectangle.Height);        //Paint the Text property on the control
        e.Graphics.DrawString(this.Text, Font, new SolidBrush(ForeColor), rect);    }}
public class HelloWorldControl: Inherits Control    Overrides Protected Sub OnPaint(e As PaintEventArgs)        Dim rect As RectangleF = new RectangleF(ClientRectangle.X,
                                                 ClientRectangle.Y,
                                                 ClientRectangle.Width,
                                                 ClientRectangle.Height)        'Paint the Text property on the control
        e.Graphics.DrawString(Me.Text, Font, new SolidBrush(ForeColor), rect)    End SubEnd Class 
C#  VB    查看并运行此示例。   
C# Hello World 控件 [运行示例] | [查看源代码]  
检查控件的设计时行为
可以在 Visual Studio .NET Windows 窗体设计器中测试控件的设计时行为:启动 Visual Studio .NET Windows 窗体设计器。 
通过从“文件”菜单单击“新建 VB”或“新建 C#”添加新窗体。 
单击“编辑”菜单上的“添加库”。 
选择包含要使用的控件的 DLL。
该控件出现在工具箱的底部。 
选择该控件并将其添加到窗体中。
将看到该控件出现在窗体上。 
如果从上一个示例添加控件,您将注意到即使如此简单的控件都具有一整套属性和广泛的设计时行为。此默认行为是从 Control 类继承的。 
注意:对于要在 Windows 窗体设计器中显示的控件,它必须具有不采用参数的公共构造函数。添加属性、事件和元数据
现在已经创建了一个简单的控件,可以向其添加属性、事件和元数据信息。下面的示例: 添加一个名为 DrawMode 的属性,该属性用于确定控件如何绘画。 
添加一个事件,该事件在 DrawMode 属性被更改时引发。 
向该控件添加元数据以描述其设计时行为。 
在设计时重写从 Control 继承的属性以隐藏该属性。 
添加属性
首先创建一个名为 DrawingMode 的简单枚举。
public enum DrawingMode {
    Happy = 0,
    Sad = 1,
    Angry = 2
}
Public Enum DrawingModeStyle
    Happy = 0
    Sad = 1
    Angry = 2
End Enum 
C#  VB    接着,向该控件添加 DrawingMode 属性。下面的代码将此属性添加到前面创建的控件中。
//DrawingMode - controls how the control paintspublic DrawingModeStyle DrawingMode {    get {
        return myDrawingMode;
    }    set {
        myDrawingMode=value;        //Set BackColor and ForeColor based on DrawingMode
        SetColors();        //Raise property changed event for DrawingMode
        RaisePropertyChangedEvent("DrawingMode");
    }}
'DrawingMode - controls how the control paintsPublic Property DrawingMode As DrawingModeStyle    Get
        Return myDrawingMode
    End Get    Set
        myDrawingMode=value        'Set BackColor and ForeColor based on DrawingMode
        SetColors        ' Raise property changed event for DrawingMode
        RaisePropertyChangedEvent("DrawingMode")
    End SetEnd Property 
C#  VB    注意:属性 Set 代码包括对 RaisePropertyChangedEvent 方法的调用。此方法引发一个属性更改通知事件。引发属性更改通知事件很重要,因为 Windows 窗体设计器侦听此事件。设计器侦听此事件以便可跟踪属性是何时更改的。在该代码的后面部分,控件利用此事件。对 SetColors 方法的调用只是根据 DrawingMode 的值设置控件的 BackColor 和 ForeColor。向控件添加下面的代码。
private void SetColors() {    switch (drawingMode) {       case DrawingMode.Happy:
           base.BackColor = Color.Yellow;
           base.ForeColor = Color.Green;
           break;       case DrawingMode.Sad:
           base.BackColor = Color.LightSlateGray;
           base.ForeColor = Color.White;
           break;      case DrawingMode.Angry:
          base.BackColor = Color.Red;
          base.ForeColor = Color.Teal;
          break;       default:
           base.BackColor = Color.Black;
           base.ForeColor = Color.White;   }}
Private Sub SetColors()    Select Case myDrawingMode       Case DrawingModeStyle.Happy
           MyBase.BackColor = Color.Yellow
           MyBase.ForeColor = Color.Green
       Case DrawingModeStyle.Sad
           MyBase.BackColor = Color.LightSlateGray
           MyBase.ForeColor = Color.White
      Case DrawingModeStyle.Angry
          MyBase.BackColor = Color.Red
          MyBase.ForeColor = Color.Teal
      Case Else
           MyBase.BackColor = Color.Black
           MyBase.ForeColor = Color.White   End SelectEnd Sub 
C#  VB    现在您可以在控件绘制其内容时使用此信息。向控件类添加此代码,以重写 Control 的 OnPaint 方法。
protected override void OnPaint(PaintEventArgs e) {    e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle);    Size textSize = (Size) e.Graphics.MeasureString(Text, Font);    float xPos = (ClientRectangle.Width/2) - (textSize.Width/2);
    float yPos = (ClientRectangle.Height/2) - (textSize.Height/2);    e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), xPos, yPos);}
Overrides Protected Sub OnPaint(e As PaintEventArgs)    e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle)    Dim textSize As SizeF = e.Graphics.MeasureString(Me.Text, Font)    Dim xPos As Single = CSng((ClientRectangle.Width/2) - (textSize.Width/2))
    Dim yPos As Single = CSng((ClientRectangle.Height/2) - (textSize.Height/2))    e.Graphics.DrawString(Me.Text, Font,new SolidBrush(ForeColor),xPos, yPos)End Sub 
C#  VB    注意:为了使控件在调整大小后自动重新绘制,请在创建该控件时设置 ResizeRedraw 样式位。
public SimpleControl() :base() {    drawingMode = DrawingMode.Happy;
    SetColors();
    SetStyle(ControlStyles.ResizeRedraw, true);
}
Public Sub New()
    MyBase.New
    myDrawingMode = DrawingModeStyle.Happy
    SetColors
    SetStyle(ControlStyles.ResizeRedraw, True)
End Sub

解决方案 »

  1.   

    添加事件
    在这一步中,添加一个 DrawingMode 属性更改时引发的简单事件。已经有一个引发的事件 PropertyChange 事件,那么为什么必须添加您自己的事件呢?默认情况下,不向控件使用者公开 PropertyChange 事件,它是由框架结构使用的隐藏事件。通常,要做的第一件事是为事件声明 EventHandler 和 EventArgs 类。因为此示例事件非常简单,所以可以使用标准 EventHandler 和 EventArgs 类。声明 EventHandler 和 EventArgs 类后,需要声明该事件并添加引发它的方法。用于引发该事件的方法通常称为 On<事件名>。此方法是受保护的,因为只有从该控件进行派生的开发人员需要直接引发该事件。 
    public class SimpleControl : Control {    private DrawingMode drawingMode ;
        private EventHandler onDrawingModeChanged;
        ....    //DrawingModeChanged Event
        //In C#, Event declarations are very similar to property declarations
        public event EventHandler DrawingModeChanged {
            get {
                return onDrawingModeChanged;
            }
            set {
                onDrawingModeChanged = value;
            }
        }    protected virtual void OnDrawingModeChanged(EventArgs e) {
            Invalidate();
            if (onDrawingModeChanged != null) onDrawingModeChanged.Invoke(this, e);
        }
        ....
    }
    Public Class SimpleControl: Inherits Control    Private myDrawingMode As DrawingModeStyle
        ....    'Declare the DrawingModeChanged Event
        Public Event DrawingModeChanged(sender As Object, ev As EventArgs)    Overridable Protected Sub OnDrawingModeChanged(e As EventArgs)
            Invalidate
            RaiseEvent DrawingModeChanged(Me, e)
        End Sub    ....End Class 
    C#  VB    添加事件后,需要引发它。可以转到 DrawingMode 属性 Set 语句,然后添加对 OnDrawingModeChanged 的调用。但是,因为此方法已经引发一个属性更改通知事件,所以只需侦听要引发的事件,而不必添加事件处理方法。可重写 OnPropertyChanged 方法。
    ....
    //Override OnPropertyChanged to raise the DrawingModeChanged event
    protected override void OnPropertyChanged(PropertyChangedEventArgs e) {
        base.OnPropertyChanged(e);
        string d = e.PropertyName;    if (d.Equals("DrawingMode")) {
            OnDrawingModeChanged(EventArgs.Empty);
        }}
    ....
    ' Override OnPropertyChanged to raise the DrawingModeChanged event
    Overrides Protected Sub OnPropertyChanged(e As PropertyChangedEventArgs)
        MyBase.OnPropertyChanged(e)
        Dim d As string = e.PropertyName    If (d.Equals("DrawingMode")) Then
            OnDrawingModeChanged(EventArgs.Empty)
        End IfEnd Sub 
    C#  VB    每次更改属性时,控件都将重绘并引发 DrawingModeChanged 事件。 使用控件
    既然已经编写了控件并向其添加了一些行为,可以将其编译为 DLL 并在应用程序中使用它了。可以像使用任何其他 Windows 窗体控件一样使用该新控件。下面的示例演示如何在应用程序中使用该控件。
    ....//Create the control and set its properties
    simpleControl1 = new SimpleControl();
    simpleControl1.Size = new System.Drawing.Size(304, 328);
    simpleControl1.TabIndex = 0;
    simpleControl1.Anchor = System.Windows.Forms.AnchorStyles.All;
    simpleControl1.Text = "Windows Forms Mood Control";//Add an event handling method for the DrawingModeChanged event
    simpleControl1.DrawingModeChanged += new System.EventHandler(simpleControl1_DrawingModeChanged);....private void simpleControl1_DrawingModeChanged(object sender, System.EventArgs e) {
        MessageBox.Show("DrawingMode changed");
    }
    ....' Create the control and set its properties
    simpleControl1 = New SimpleControl()
    simpleControl1.Size = new System.Drawing.Size(304, 328)
    simpleControl1.TabIndex = 0
    simpleControl1.Anchor = System.Windows.Forms.AnchorStyles.All
    simpleControl1.Text = "Windows Forms Mood Control"' Add an event handling method for the DrawingModeChanged event
    AddHandler simpleControl1.DrawingModeChanged, AddressOf simpleControl1_DrawingModeChanged....Private Sub simpleControl1_DrawingModeChanged(sender As object, e As System.EventArgs)
        MessageBox.Show("DrawingMode changed")
    End Sub 
    C#  VB    为控件添加设计时信息
    既然拥有了一个工作控件,您可以在窗体设计器中使用可提高其可用性的运行时信息扩充该控件。使用元数据将设计时信息记录在该控件的二进制数据上。使用来自 System.ComponentModel 命名空间的一系列特性类定义此元数据。例如,控件的默认事件是 DrawingModeChanged 事件。当用户双击该控件时,您希望窗体设计器为该默认事件添加事件处理方法。您必须使用 DefaultEvent 类特性注册该默认事件。同样,可以使用 DefaultProperty 类特性定义控件上的默认属性。此特性确定默认情况下给予“属性”窗口中哪个属性焦点。类特性作为类声明的一部分声明。下面的示例演示类特性。
    [
    DefaultProperty("DrawingMode"),
    DefaultEvent("DrawingModeChanged"),
    ]
    public class SimpleControl : Control {
        ...
    }
    Public Class _
        <DefaultProperty("DrawingMode"), DefaultEvent("DrawingModeChanged")> _
        SimpleControl
            Inherits Control
        ...
    End Class 
    C#  VB    下一步是为 DrawingMode 属性添加更多设计时信息。
    [
        Category("Appearance"),
        Description("Controls how the control paints"),
        DefaultValue(DrawingMode.Happy),
        Bindable(true),
    ]
    public DrawingMode DrawingMode {    get {
        return drawingMode;
      }    set {
            drawingMode=value;        //Set BackColor and ForeColor based on DrawingMode
            SetColors();        //Raise property changed event for DrawingMode
            RaisePropertyChangedEvent("DrawingMode");    }}
    'DrawingMode - controls how the control paints
    Public Property _
    <Category("Appearance"), _
     Description("Controls how the control paints"), _
     DefaultValue(DrawingModeStyle.Happy), _
     Bindable(true)> _
    DrawingMode As DrawingModeStyle    Get
            return myDrawingMode
        End Get    Set
            myDrawingMode=value        'Set BackColor and ForeColor based on DrawingMode
            SetColors        'Raise property changed event for DrawingMode
            RaisePropertyChangedEvent("DrawingMode")    End SetEnd Property
      

  2.   

    http://chs.gotdotnet.com/QuickStart/aspplus/default.aspx?url=%2fquickstart%2fwinforms%2fdoc%2fWinFormsCreatingControls.aspx
      

  3.   

    不贴了,自己看爸:Phttp://chs.gotdotnet.com/quickstart/winforms/
      

  4.   

    如何生成和使用自定义控件
    http://www.csdn.net/develop/read_article.asp?id=15568
      

  5.   

    上面的写得它长太麻烦了。我来写个简单的。:
    public class UserControl : Button
    {
        public UserControl()
        {
            label = new Label();
            label.Height = this.Height;
            label.Color = Color.Blue;
         }
        public Label label ;
    }
    然后你就可以使用UserControl控件了。