Vorgehensweise: Entwickeln eines einfachen Windows Forms-Steuerelements

Dieser Abschnitt führt Sie durch die wichtigsten Schritte zum Erstellen von benutzerdefinierten Windows Forms-Steuerelementen. Das einfache Steuerelement, das in dieser exemplarischen Vorgehensweise entwickelt wird, ermöglicht die Änderung der Ausrichtung der Eigenschaft Text. Es löst keine Ereignisse aus oder behandelt sie.

So erstellen Sie ein einfaches benutzerdefiniertes Steuerelement

  1. Definieren Sie eine Klasse, die sich von System.Windows.Forms.Control ableitet.

    Public Class FirstControl
       Inherits Control
    
    End Class
    
    public class FirstControl:Control {}
    
  2. Definieren Sie Eigenschaften. (Sie müssen keine Eigenschaften definieren, da ein Steuerelement viele Eigenschaften von der Klasse Control erbt. Die meisten benutzerdefinierten Steuerelemente definieren allerdings zusätzliche Eigenschaften.) Das folgende Codefragment definiert eine Eigenschaft namens TextAlignment, die von FirstControl verwendet wird, um die Anzeige der von Control geerbten Text-Eigenschaft zu formatieren. Weitere Informationen zum Definieren von Eigenschaften finden Sie in der Übersicht über Eigenschaften.

    // ContentAlignment is an enumeration defined in the System.Drawing
    // namespace that specifies the alignment of content on a drawing
    // surface.
    private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
    
    ' ContentAlignment is an enumeration defined in the System.Drawing
    ' namespace that specifies the alignment of content on a drawing 
    ' surface.
    Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft
    
    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
       
       Get
          Return alignmentValue
       End Get
       Set
          alignmentValue = value
          
          ' The Invalidate method invokes the OnPaint method described 
          ' in step 3.
          Invalidate()
       End Set
    End Property
    

    Wenn Sie eine Eigenschaft festlegen, die die grafische Darstellung des Steuerelements ändert, müssen Sie die Methode Invalidate aufrufen, um das Steuerelement neu zu zeichnen. Invalidate ist in der Basisklasse Control definiert.

  3. Überschreiben Sie die von Control geerbte OnPaint-Methode, um die Renderinglogik für das Steuerelement anzugeben. Wenn Sie OnPaint nicht überschreiben, kann das Steuerelement nicht sich selbst zeichnen. Im folgenden Codefragment zeigt die OnPaint-Methode die von Control geerbte Text-Eigenschaft mit der über das Feld alignmentValue angegebenen Ausrichtung an.

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        StringFormat style = new StringFormat();
        style.Alignment = StringAlignment.Near;
        switch (alignmentValue)
        {
            case ContentAlignment.MiddleLeft:
                style.Alignment = StringAlignment.Near;
                break;
            case ContentAlignment.MiddleRight:
                style.Alignment = StringAlignment.Far;
                break;
            case ContentAlignment.MiddleCenter:
                style.Alignment = StringAlignment.Center;
                break;
        }
    
        // Call the DrawString method of the System.Drawing class to write
        // text. Text and ClientRectangle are properties inherited from
        // Control.
        e.Graphics.DrawString(
            Text,
            Font,
            new SolidBrush(ForeColor),
            ClientRectangle, style);
    }
    
    Protected Overrides Sub OnPaint(e As PaintEventArgs)
    
       MyBase.OnPaint(e)
       Dim style As New StringFormat()
       style.Alignment = StringAlignment.Near
       Select Case alignmentValue
          Case ContentAlignment.MiddleLeft
             style.Alignment = StringAlignment.Near
          Case ContentAlignment.MiddleRight
             style.Alignment = StringAlignment.Far
          Case ContentAlignment.MiddleCenter
             style.Alignment = StringAlignment.Center
       End Select
       
       ' Call the DrawString method of the System.Drawing class to write   
       ' text. Text and ClientRectangle are properties inherited from
       ' Control.
       e.Graphics.DrawString( _
           me.Text, _
           me.Font, _
           New SolidBrush(ForeColor), _
           RectangleF.op_Implicit(ClientRectangle), _
           style)
    
    End Sub
    
  4. Stellen Sie Attribute für das Steuerelement bereit. Attribute ermöglichen es einem visuellen Designer, Ihr Steuerelement und dessen Eigenschaften und Ereignisse entsprechend zur Entwurfszeit anzuzeigen. Das folgende Codefragment wendet die Attribute auf die Eigenschaft TextAlignment an. In einem Designer wie Visual Studio bewirkt das Attribut Category (siehe Codefragment), dass die Eigenschaft unter einer logischen Kategorie angezeigt wird. Das Attribut Description bewirkt, dass eine beschreibende Zeichenfolge am unteren Rand des Fensters Eigenschaften angezeigt wird, wenn die TextAlignment-Eigenschaft ausgewählt wird. Weitere Informationen zu Attributen finden Sie unter Entwurfszeitattribute für Komponenten.

    [
    Category("Alignment"),
    Description("Specifies the alignment of text.")
    ]
    
    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
    
  5. (optional) Stellen Sie Ressourcen für Ihr Steuerelement zur Verfügung. Sie können eine Ressource, z.B. eine Bitmap für das Steuerelement mit einer Compileroption bereitstellen (/res für C#), um Ressourcen mit dem Steuerelement zu verpacken. Zur Laufzeit kann die Ressource mithilfe der Methoden der ResourceManager-Klasse abgerufen werden. Weitere Informationen zum Erstellen und Verwenden von Ressourcen finden Sie unter Ressourcen in Desktop-Apps.

  6. Kompilieren Sie das Steuerelement, und stellen Sie es bereit. Führen Sie die folgenden Schritte aus, um FirstControl, zu kompilieren und bereitzustellen:

    1. Speichern Sie den Code im folgenden Beispiel als Quelldatei (z.B. als „FirstControl.cs“ oder „FirstControl.vb“).

    2. Kompilieren Sie den Quellcode in eine Assembly, und speichern Sie sie im Verzeichnis der Anwendung. Führen Sie hierfür den folgenden Befehl in dem Verzeichnis aus, das die Quelldatei enthält.

      vbc -t:library -out:[path to your application's directory]/CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll FirstControl.vb
      
      csc -t:library -out:[path to your application's directory]/CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll FirstControl.cs
      

      Die Compileroption /t:library benachrichtigt den Compiler, dass es sich bei der erstellten Assembly um eine Bibliothek handelt (nicht um eine ausführbare Assembly). Die Option /out gibt den Pfad und den Namen der Assembly an. Die Option /r gibt den Namen der Assembly an, auf die durch Ihren Code verwiesen wird. In diesem Beispiel erstellen Sie eine private Assembly, die ausschließlich von Ihren Anwendungen verwendet werden kann. Daher müssen Sie sie im Verzeichnis der Anwendung speichern. Weitere Informationen über das Packen und Bereitstellen eines Steuerelements für die Verteilung finden Sie unter Bereitstellung.

Das folgende Beispiel zeigt den Code für FirstControl. Das Steuerelement ist im Namespace CustomWinControls enthalten. Ein Namespace bietet eine logische Gruppierung von verwandten Typen. Sie können das Steuerelement in einem neuen oder vorhandenen Namespace erstellen. In C# ermöglicht die Deklaration using (Imports in Visual Basic), dass auf Typen von einem Namespace zugegriffen wird, ohne dass der vollqualifizierte Name des Typs verwendet wird. Im folgenden Beispiel ermöglicht die using-Deklaration den einfachen Codezugriff auf die Control-Klasse von System.Windows.Forms über Control, anstatt den vollqualifizierten Namen System.Windows.Forms.Control verwenden zu müssen.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace CustomWinControls
{
    public class FirstControl : Control
    {

        public FirstControl()
        {
        }

        // ContentAlignment is an enumeration defined in the System.Drawing
        // namespace that specifies the alignment of content on a drawing
        // surface.
        private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;

        [
        Category("Alignment"),
        Description("Specifies the alignment of text.")
        ]
        public ContentAlignment TextAlignment
        {

            get
            {
                return alignmentValue;
            }
            set
            {
                alignmentValue = value;

                // The Invalidate method invokes the OnPaint method described
                // in step 3.
                Invalidate();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            StringFormat style = new StringFormat();
            style.Alignment = StringAlignment.Near;
            switch (alignmentValue)
            {
                case ContentAlignment.MiddleLeft:
                    style.Alignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleRight:
                    style.Alignment = StringAlignment.Far;
                    break;
                case ContentAlignment.MiddleCenter:
                    style.Alignment = StringAlignment.Center;
                    break;
            }

            // Call the DrawString method of the System.Drawing class to write
            // text. Text and ClientRectangle are properties inherited from
            // Control.
            e.Graphics.DrawString(
                Text,
                Font,
                new SolidBrush(ForeColor),
                ClientRectangle, style);
        }
    }
}
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms


Public Class FirstControl
   Inherits Control

   Public Sub New()
   End Sub 
   
   
   ' ContentAlignment is an enumeration defined in the System.Drawing
   ' namespace that specifies the alignment of content on a drawing 
   ' surface.
   Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft
   
   <Category("Alignment"), Description("Specifies the alignment of text.")> _
   Public Property TextAlignment() As ContentAlignment
      
      Get
         Return alignmentValue
      End Get
      Set
         alignmentValue = value
         
         ' The Invalidate method invokes the OnPaint method described 
         ' in step 3.
         Invalidate()
      End Set
   End Property
   
   
   Protected Overrides Sub OnPaint(e As PaintEventArgs)

      MyBase.OnPaint(e)
      Dim style As New StringFormat()
      style.Alignment = StringAlignment.Near
      Select Case alignmentValue
         Case ContentAlignment.MiddleLeft
            style.Alignment = StringAlignment.Near
         Case ContentAlignment.MiddleRight
            style.Alignment = StringAlignment.Far
         Case ContentAlignment.MiddleCenter
            style.Alignment = StringAlignment.Center
      End Select
      
      ' Call the DrawString method of the System.Drawing class to write   
      ' text. Text and ClientRectangle are properties inherited from
      ' Control.
      e.Graphics.DrawString( _
          me.Text, _
          me.Font, _
          New SolidBrush(ForeColor), _
          RectangleF.op_Implicit(ClientRectangle), _
          style)

   End Sub

End Class

Verwenden des benutzerdefinierten Steuerelements in einem Formular

Im folgenden Beispiel wird ein einfaches Formular dargestellt, dass FirstControl verwendet. Es erstellt drei Instanzen von FirstControl, jede mit einem anderen Wert für die Eigenschaft TextAlignment.

So kompilieren Sie dieses Beispiel und führen es aus

  1. Speichern Sie den Code im folgenden Beispiel als Quelldatei („SimpleForm.cs“ oder „SimpleForms.vb“).

  2. Kompilieren Sie den Quellcode in eine ausführbare Assembly, indem Sie den folgenden Befehl im Verzeichnis ausführen, das die Quelldatei enthält.

    vbc -r:CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll SimpleForm.vb
    
    csc -r:CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll SimpleForm.cs
    

    „CustomWinControls.dll“ ist die Assembly mit der Klasse FirstControl. Diese Assembly muss sich im gleichen Verzeichnis befinden wie die Quelldatei für das Formular, das auf sie zugreift („SimpleForm.cs“ oder „SimpleForms.vb“).

  3. Führen Sie „SimpleForm.exe“ mit dem folgenden Befehl aus.

    SimpleForm
    
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace CustomWinControls
{

    public class SimpleForm : System.Windows.Forms.Form
    {
        private FirstControl firstControl1;

        private System.ComponentModel.Container components = null;

        public SimpleForm()
        {
            InitializeComponent();
        }

        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        private void InitializeComponent()
        {
            this.firstControl1 = new FirstControl();
            this.SuspendLayout();

            //
            // firstControl1
            //
            this.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark;
            this.firstControl1.Location = new System.Drawing.Point(96, 104);
            this.firstControl1.Name = "firstControl1";
            this.firstControl1.Size = new System.Drawing.Size(75, 16);
            this.firstControl1.TabIndex = 0;
            this.firstControl1.Text = "Hello World";
            this.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

            //
            // SimpleForm
            //
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.firstControl1);
            this.Name = "SimpleForm";
            this.Text = "SimpleForm";
            this.ResumeLayout(false);
        }

        [STAThread]
        static void Main()
        {
            Application.Run(new SimpleForm());
        }
    }
}
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms




Public Class SimpleForm
   Inherits System.Windows.Forms.Form

   Private firstControl1 As FirstControl
   
   Private components As System.ComponentModel.Container = Nothing
   
   
   Public Sub New()
      InitializeComponent()
   End Sub 
   
   

   
   
   Private Sub InitializeComponent()
      Me.firstControl1 = New FirstControl()
      Me.SuspendLayout()
      
      ' 
      ' firstControl1
      ' 
      Me.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark
      Me.firstControl1.Location = New System.Drawing.Point(96, 104)
      Me.firstControl1.Name = "firstControl1"
      Me.firstControl1.Size = New System.Drawing.Size(75, 16)
      Me.firstControl1.TabIndex = 0
      Me.firstControl1.Text = "Hello World"
      Me.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter
      
      ' 
      ' SimpleForm
      ' 
      Me.ClientSize = New System.Drawing.Size(292, 266)
      Me.Controls.Add(firstControl1)
      Me.Name = "SimpleForm"
      Me.Text = "SimpleForm"
      Me.ResumeLayout(False)
   End Sub 
    
   
   <STAThread()>  _
   Shared Sub Main()
      Application.Run(New SimpleForm())
   End Sub 
End Class 

Weitere Informationen