Gewusst wie: Entwickeln eines einfachen Windows Forms-Steuerelements

In diesem Abschnitt werden die wesentlichen Schritte beim Erstellen benutzerdefinierter Windows Forms-Steuerelemente behandelt. In dieser exemplarischen Vorgehensweise wird ein einfaches Steuerelement entwickelt, das die Änderung der Ausrichtung seiner Text-Eigenschaft zulässt. Es dient nicht zum Behandeln oder Auslösen von Ereignissen.

So erstellen Sie ein einfaches benutzerdefiniertes Steuerelement

  1. Definieren Sie eine Klasse, die von System.Windows.Forms.Control abgeleitet wird.

    Public Class FirstControl
       Inherits Control
    
    End Class
    
    public class FirstControl:Control{}
    
  2. Definieren Sie Eigenschaften. (Die Definition von Eigenschaften ist nicht zwingend erforderlich, da ein Steuerelement viele Eigenschaften von der Control-Klasse erbt. Jedoch definieren im Allgemeinen die meisten benutzerdefinierten Steuerelemente zusätzliche Eigenschaften.) Im folgenden Codefragment wird eine Eigenschaft mit dem Namen TextAlignment definiert. Sie wird von FirstControl dazu verwendet, die Anzeige der Text-Eigenschaft zu formatieren, die von Control geerbt wurde. Weitere Informationen über das Definieren von Eigenschaften finden Sie unter Übersicht über Eigenschaften.

    ' 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
    
    // 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;
    

    Wenn Sie eine Eigenschaft festlegen, durch die die visuelle Darstellung eines Steuerelements geändert wird, müssen Sie die Invalidate-Methode aufrufen, um das Steuerelement neu zu zeichnen. Invalidate ist in der Basisklasse Control definiert.

  3. Überschreiben Sie die geschützte, von Control geerbte OnPaint-Methode, um dem Steuerelement Renderinglogik zur Verfügung zu stellen. Wenn Sie OnPaint nicht überschreiben, wird das Steuerelement nicht in die Lage versetzt, sich selbst zu zeichnen. Im folgenden Codefragment zeigt die OnPaint-Methode die von Control geerbte Text-Eigenschaft mit der durch das alignmentValue-Feld festgelegten Ausrichtung an.

    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
    
    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);
    
    } 
    
  4. Stellen Sie Attribute für das Steuerelement bereit. Durch Attribute kann das Steuerelement samt seiner Eigenschaften und Ereignisse zur Entwurfszeit in einem visuellen Designer entsprechend angezeigt werden. Im folgenden Codefragment werden Attribute auf die TextAlignment-Eigenschaft angewendet. Das Category-Attribut (das im Codefragment gezeigt wird) führt in einem Designer wie Visual Studio dazu, dass die Eigenschaft in einer logischen Kategorie angezeigt wird. Das Description-Attribut bewirkt bei Auswahl der TextAlignment-Eigenschaft, dass eine beschreibende Zeichenfolge am unteren Rand des Eigenschaftenfensters angezeigt wird. Weitere Informationen über Attribute finden Sie unter Entwurfszeitattribute für Komponenten.

    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
    
    [
    Category("Alignment"),
    Description("Specifies the alignment of text.")
    ]
    
  5. (Optional) Stellen Sie Ressourcen für das Steuerelement bereit. Sie können dem Steuerelement eine Ressource (z. B. eine Bitmap) zur Verfügung stellen, indem Sie eine Compileroption (/res für C#) zum Verpacken von Ressourcen mit dem Steuerelement verwenden. Zur Laufzeit kann die Ressource mit den Methoden der ResourceManager-Klasse abgerufen werden. Weitere Informationen über das Erstellen und Verwenden von Ressourcen finden Sie unter Ressourcen in Anwendungen.

  6. Kompilieren Sie das Steuerelement, und geben Sie es weiter. Zum Kompilieren und zur Bereitstellung von FirstControl führen Sie folgende Schritte aus:

    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 diese im Anwendungsverzeichnis. Führen Sie dazu den folgenden Befehl im 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
      

      Durch die Compileroption /t:library wird dem Compiler mitgeteilt, dass es sich bei der von Ihnen erstellten Assembly um eine Bibliothek und nicht um eine ausführbare Datei handelt. Durch die Option /out werden Pfad und Name der Assembly festgelegt. Die Option /r stellt den Namen der Assemblys bereit, auf die der Code verweist. In diesem Beispiel erstellen Sie eine private Assembly, die ausschließlich Ihre Anwendung verwenden kann. Daher müssen Sie sie in Ihrem Anwendungsverzeichnis speichern. Weitere Informationen über das Packen und Bereitstellen eines Steuerelements zur Verteilung finden Sie unter Bereitstellen von .NET Framework und Anwendungen.

Im Folgenden wird der Code für FirstControl gezeigt. Das Steuerelement ist im Namespace CustomWinControls eingeschlossen. Ein Namespace stellt eine logische Gruppe verwandter Typen bereit. Sie können ein Steuerelement in einem neuen oder vorhandenen Namespace erstellen. Using-Deklarationen (Imports in Visual Basic) ermöglichen in C# den Zugriff auf Typen über einen Namespace ohne Verwendung des vollständigen Typnamens. Im folgenden Beispiel ermöglicht es die using-Deklaration, dass Code die Control-Klasse aus System.Windows.Forms einfach als Control aufrufen kann, anstatt den vollständig qualifizierten Namen System.Windows.Forms.Control verwenden zu müssen.

Imports System
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
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);

        } 
    }
}

Verwenden des benutzerdefinierten Steuerelements in einem Formular

Im folgenden Beispiel wird ein einfaches Formular gezeigt, das FirstControl verwendet. Es werden drei Instanzen von FirstControl mit unterschiedlichen Werten für die TextAlignment-Eigenschaft erstellt.

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. Führen Sie dazu den folgenden Befehl in dem Verzeichnis aus, 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, in der die Klasse FirstControl enthalten ist. Diese Assembly muss sich im selben Verzeichnis befinden wie die Quelldatei des Formulars, das auf sie zugreift (SimpleForm.cs oder SimpleForms.vb).

  3. Führen Sie SimpleForm.exe mit folgendem Befehl aus.

    SimpleForm
    
Imports System
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 
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());
        }


    }
}

Siehe auch

Konzepte

Ereignisse in Windows Forms-Steuerelementen

Weitere Ressourcen

Eigenschaften von Windows Forms-Steuerelementen