方法: シンプルな Windows フォーム コントロールを開発する

ここでは、カスタム Windows フォーム コントロールの主な作成手順を紹介します。 このチュートリアルで作成したシンプルなコントロールを使用して、Text プロパティの配置を変更できます。 イベントを発生させたり処理したりすることはありません。

シンプルなカスタム コントロールを作成するには

  1. System.Windows.Forms.Control から派生するクラスを定義します。

    Public Class FirstControl
       Inherits Control
    
    End Class
    
    public class FirstControl:Control {}
    
  2. プロパティを定義します (コントロールは Control クラスから多数のプロパティを継承するため、プロパティの定義は必須ではありませんが、通常、ほとんどのカスタム コントロールによって追加プロパティが定義されます)。次のコード フラグメントでは、TextAlignment という名前のプロパティが定義されます。それは、FirstControlControl から継承した Text プロパティの表示形式を設定するときに使用されます。 プロパティの定義の詳細については、「プロパティの概要」を参照してください。

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

    コントロールのビジュアル表示を変更するプロパティを設定するには、Invalidate メソッドを呼び出して、コントロールを再描画する必要があります。 Invalidate は、基底クラス Control に定義されます。

  3. Control から継承された、保護された OnPaint メソッドをオーバーライドして、コントロールにレンダリング ロジックを提供します。 OnPaint をオーバーライドしないと、コントロールは自身を描画できません。 次のコード フラグメントでは、OnPaint メソッドによって、Control から継承された Text プロパティを、alignmentValue フィールドによって指定された配置を使用して表示します。

    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. コントロールの属性を指定します。 ビジュアル デザイナーでは、デザイン時に属性を使用することで、コントロール、コントロールのプロパティ、およびイベントを適切に表示します。 次のコード フラグメントでは、属性が TextAlignment プロパティに適用されます。 Visual Studio などのデザイナーでは、(コード フラグメントに示されている) Category 属性によって、プロパティが論理カテゴリの下に表示されます。 Description 属性を指定すると、TextAlignment プロパティが選択されたときに、説明的な文字列が [プロパティ] ウィンドウの下部に表示されます。 属性の詳細については、「コンポーネントのデザイン時属性」を参照してください。

    [
    Category("Alignment"),
    Description("Specifies the alignment of text.")
    ]
    
    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
    
  5. (省略可能) コントロールに対してリソースを指定します。 コントロールに対してビットマップなどのリソースを指定するには、コンパイラ オプション (C# の場合は /res) を使用して、リソースをコントロールと共にパッケージ化します。 実行時に、ResourceManager クラスのメソッドを使用してリソースを取得できます。 リソースの作成と使用の詳細については、「デスクトップ アプリケーションのリソース」を参照してください。

  6. コンパイルしてコントロールを配置します。 FirstControl, をコンパイルして配置するには、次の手順を実行します。

    1. 次のサンプル コードをソース ファイル (FirstControl.cs、FirstControl.vb など) に保存します。

    2. ソース コードをコンパイルして、アセンブリを生成し、アプリケーションのディレクトリに保存します。 それには、ソース ファイルが格納されているディレクトリで次のコマンドを実行します。

      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
      

      /t:library コンパイラ オプションは、作成しているアセンブリが (実行可能ファイルではなく) ライブラリであることをコンパイラに伝えます。 /out オプションでは、アセンブリの名前とパスを指定します。 /r オプションでは、コードが参照するアセンブリの名前を指定します。 この例では、ご自身のアプリケーションのみが使用できるプライベート アセンブリを作成します。 このため、アセンブリはご自身のアプリケーションのディレクトリに保存する必要があります。 配布用コントロールのパッケージ化と配置の詳細については、配置に関するページをご覧ください。

次のサンプルは、FirstControl のコードを示しています。 このコントロールは、CustomWinControls 名前空間に囲まれています。 名前空間では、関連する型を論理的にグループ化できます。 コントロールは、新しい名前空間または既存の名前空間に作成できます。 C# では、using 宣言 (Visual Basic の場合は Imports) を使用すると、名前空間から型へアクセスするときに、型の完全修飾名を使用する必要はありません。 次の例では、using 宣言によって、コードが単純に Control として System.Windows.Forms から Control クラスにアクセスできます。その際、完全修飾名 System.Windows.Forms.Control を使用する必要はありません。

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

フォームでのカスタム コントロールの使用

FirstControl を使用するシンプルなフォームの例を次に示します。 この例では、FirstControl のインスタンスを 3 つ作成します。それぞれのインスタンスで、TextAlignment プロパティに異なる値が設定されます。

このサンプルをコンパイルして実行するには

  1. このサンプルをコンパイルして実行するには、次に示すサンプルのコードをソース ファイル (SimpleForm.cs または SimpleForms.vb) に保存します。

  2. ソース ファイルが格納されているディレクトリから次のコマンドを実行して、ソース コードを実行可能アセンブリにコンパイルします。

    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 は、FirstControl クラスが含まれているアセンブリです。 フォームがアセンブリにアクセスできるように、そのアセンブリはソース ファイル (SimpleForm.cs または SimpleForms.vb) と同じディレクトリに格納されている必要があります。

  3. 次のコマンドで SimpleForm.exe を実行します。

    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 

関連項目