VB.NET カスタムコントロールの作り方
(Visual Studio 2015 版)

投稿日 2016/04/13

[Home] 

概要

Visual Studio 2015 Windows.Forms プロジェクトではユーザコントロールとカスタムコントロールを作ることができます。ユーザコントロールはコンテナの上に既存の標準コントロールを配置して一つの塊として振る舞うようにしたものです。一方、カスタムコントロールは一般的には System.Windows.Forms.Control から派生したコントロールです。ただし、直接この Control クラスから派生させる必要はなく、TextBox や Button といった既存の標準コントロール(Control を継承しているもの) から派生させることもできます。

 

プロジェクトへのカスタムコントロールの追加

Windows.Forms アプリケーションやクラスライブラリプロジェクトにカスタムコントロールを追加するには、ソリューションエクスプローラーでそのプロジェクトを選択して、コンテキストメニューの「追加 / 新しい項目」をクリックします。「新しい項目の追加」ダイアログが開くので「カスタムコントロール」を選んで OK ボタンをクリックします。カスタムコントロールのテンプレートがプロジェクトに追加されます。

最初は下のようなコードになっています。

Public Class CustomButton

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        'カスタム描画コードをここに追加します。
    End Sub

End Class

同じソリューション内にテスト用の Windows.Forms プロジェクトを作成してビルドを行うとツールボックスの一番上にカスタムコントロールのアイコンが追加されているはずです。

 

コントロールのカスタマイズ

テスト用のフォームにこのコントロールを貼り付けて実行しても何も表示されません。何かを表示するためには、OnPaint メソッドに描画用のコードを追加するか、そのカスタムコントロールを Control でなく TextBox などの標準コントロールから派生させる必要があります。普通は、Control からでなく標準コントロールから派生させます。そうでないと、必要なコードが多くなりコーディングが大変になります。


サンプル1 NumericTextBox カスタムコントロール

このサンプルは TextBox から派生させたコントロールで、標準の TextBox に数字のみの入力制限を追加し、フォーカスが移動したとき指定した桁数にゼロフィルを行うものです。外観は変更しないので、OnPaint は変更しません。

キー入力の制限のため、OnKeyPress イベントハンドラでキー入力を調べて数字キーでなければ表示されないようにします。

整数型の NumberOfDigit プロパティを追加して、そこで指定した桁数以上は入力できないようにします。もし、桁数が足りない場合はゼロフィルを行います。この機能は、OnValidating イベントハンドラで行います。

また、マウスボタンが下がった時とフォーカスが当たったとき、テキストを全選択するようにもしています。

派生元が Control のままなので、NumericTextBox.Designer.vb の Inherits 文を下のように変更します。このファイルはメニューからは開けないので、Explorer でプロジェクトフォルダから探して Visual Studio へドラッグ&ドロップします。

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class NumericTextBox
    Inherits System.Windows.Forms.TextBox  ' <== Control から TextBox に変更

    'Control は、コンポーネント一覧に後処理を実行するために、dispose をオーバーライドし ます。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'コントロール デザイナーで必要です。
    Private components As System.ComponentModel.IContainer

    ' メモ: 以下のプロシージャはコンポーネント デザイナーで必要です。
    ' コンポーネント デザイナーを使って変更できます。
    ' コード エディターを使って変更しないでください。
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.TextBox1 = New System.Windows.Forms.TextBox()
        Me.SuspendLayout()
        '
        'TextBox1
        '
        Me.TextBox1.Location = New System.Drawing.Point(0, 0)
        Me.TextBox1.Name = "TextBox1"
        Me.TextBox1.Size = New System.Drawing.Size(100, 19)
        Me.TextBox1.TabIndex = 0
        Me.ResumeLayout(False)

    End Sub

    Friend WithEvents TextBox1 As Windows.Forms.TextBox
End Class

変更してビルドし直して、もう一度テスト用フォームにツールボックスからこのコントロールを入りつけるとテキストボックスとして表示されます。

このコントロールのコードは下のようになります。

Imports System.ComponentModel
Imports System.Windows.Forms

''' <summary>
''' 数字のみ入力可能なテキストボックス
''' </summary>
Public Class NumericTextBox
    ''' <summary>
    ''' 有効桁数
    ''' </summary>
    Public Property NumberOfDigit As Integer = 8

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        ImeMode = ImeMode.Disable
    End Sub

    ''' <summary>
    ''' 描画が必要なとき
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
    End Sub

    ''' <summary>
    ''' キーが押されたとき
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
        MyBase.OnKeyPress(e)

        If e.KeyChar > "9"c OrElse e.KeyChar < "0"c OrElse Text.Length >= NumberOfDigit Then
            If e.KeyChar <> Chr(8) Then  ' BackSpace
                e.Handled = True
            End If
        End If
    End Sub

    ''' <summary>
    ''' 評価が必要なとき(ロストフォーカス)
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnValidating(e As CancelEventArgs)
        MyBase.OnValidating(e)
        MyBase.OnValidating(e)
        ' 空欄なら何もしない
        If String.IsNullOrEmpty(Text) Then
            Return
        End If
        ' 数字以外または桁数が不正ならロストフォーカスしない
        If Not IsNumeric(Text) OrElse Text.Length > NumberOfDigit Then
            e.Cancel = True
        End If
   End Sub

    ''' <summary>
    ''' フォーカスが当たった時
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnEnter(e As EventArgs)
        MyBase.OnEnter(e)
        SelectAll()
    End Sub

    ''' <summary>
    ''' マウスボタンが下がった時
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
        MyBase.OnMouseDown(e)
        SelectAll()
    End Sub
End Class


 

サンプル2 CustomButton カスタムコントロール

このコントロールは Button クラスを継承しており OnPaint イベントハンドラをオーバーライドして外観を変更する例です。下のイメージは、NumericTextBox も含むテストプログラムで、テキストボックスの下の赤い文字で表示されているのが、CustomButton カスタムコントロールです。

このボタンコントロールは OnPaint の他、ボタンが押されたときの背景色を変えるために OnMouseDown, OnMouseUp イベントハンドラもオーバーライドしています。

NumericTextBox カスタムコントロール同様、CustomButton.Designer.vb で Inherits 文を次のように変更しています。

System.Windows.Forms.Button

CustomButton コントロールの全体のコードを下に示します。

Imports System.Drawing
Imports System.Windows.Forms

''' <summary>
''' ボタンの外観を変更
''' </summary>
Public Class CustomButton
    Dim down As Boolean = False
    Dim brush1 As Brush

    ''' <summary>
    ''' 描画が必要なとき
    ''' </summary>
    ''' <param name="e"></param>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        ' MyBase.OnPaint(e)

        Dim g As Graphics = e.Graphics

        If down Then
            brush1 = Brushes.Silver
        Else
            brush1 = Brushes.White
        End If
        g.FillRectangle(brush1, 0, 0, Width - 1, Height - 1)
        g.DrawRectangle(New Pen(Brushes.Black), New Rectangle(New Point(0, 0), Size))
        g.DrawString(Text, New Font("Courier New", 10), Brushes.Red, New PointF(0, 0))   
    End Sub

    ''' <summary>
    ''' マウスボタンが下がった時
    ''' </summary>
    ''' <param name="mevent"></param>
    Protected Overrides Sub OnMouseDown(mevent As MouseEventArgs)
        MyBase.OnMouseDown(mevent)
        down = True
    End Sub

    ''' <summary>
    ''' マウスボタンが上がった時
    ''' </summary>
    ''' <param name="mevent"></param>
    Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
        MyBase.OnMouseUp(mevent)
        down = False
        Invalidate()
        Refresh()
    End Sub
End Class









 

 


 

 開設 2014年12月   著作権 2014-2015 bonk.red  連絡先: こちらからメッセージを送ってください。

 このページの先頭へ..