ReadOnly 可能な Combobox

# ReadOly 可能なCombobox

Enabled を False にするとグレーアウトしてしまうため、ReadOnly 可能にしました。
いろいろ余計なことしてますが、これで対応しました。

ReadOnlyに不要なコードを削除しました。

```lang:ReadOnlyCombobox.vb
''' <summary>
''' コンボボックス
''' </summary>
''' <remarks>
''' </remarks>
Public Class ComboBox
    Inherits System.Windows.Forms.ComboBox

    Protected _readOnly As Boolean
    Protected _unenabledBackColor As System.Drawing.Color = System.Drawing.SystemColors.Control
    Protected _components As System.ComponentModel.IContainer
    Protected _keyPressHandled As Boolean

    Protected _readOnlyBackColor As System.Drawing.Color = Me.BackColor
    Protected _readOnlyForeColor As System.Drawing.Color = Me.ForeColor
    Protected _notReadOnlyBackColor As System.Drawing.Color = Me.BackColor
    Protected _notReadOnlyForeColor As System.Drawing.Color = Me.ForeColor

    Protected _unenabledForeColor As System.Drawing.Color = Nothing

    ''' <summary>
    ''' EnabledプロパティがFalseのときに表示されるForeColor
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.ComponentModel.Description("EnabledプロパティがFalseの時に表示される文字色です。")>
    Public Property UnenabledForeColor() As System.Drawing.Color
        Get
            Return Me._unenabledForeColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            Me._unenabledForeColor = value
        End Set
    End Property


    <System.ComponentModel.Description("文字列を変更できるかどうかを設定します。")>
    Public Property [ReadOnly] As Boolean
        Get
            Return Me._readOnly
        End Get
        Set(value As Boolean)

            If value = Me._readOnly Then Return

            Me._readOnly = value

            If value Then
                Me.ContextMenu = New System.Windows.Forms.ContextMenu
                Me.BackColor = _readOnlyBackColor
                Me.ForeColor = _readOnlyForeColor
                Me.SetStyle(ControlStyles.UserMouse, True)
            Else
                Me.ContextMenu = Nothing
                Me.BackColor = _notReadOnlyBackColor
                Me.ForeColor = _notReadOnlyForeColor
                Me.SetStyle(ControlStyles.UserMouse, False)
            End If

        End Set
    End Property

    <System.ComponentModel.Description("ReadOnlyプロパティがTrueの時に表示される背景色です。")>
    Public Property ReadOnlyBackColor() As System.Drawing.Color
        Get
            Return Me._readOnlyBackColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            Me._readOnlyBackColor = value
        End Set
    End Property

    <System.ComponentModel.Description("ReadOnlyプロパティがTrueの時に表示される文字色です。")>
    Public Property ReadOnlyForeColor() As System.Drawing.Color
        Get
            Return Me._readOnlyForeColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            Me._readOnlyForeColor = value
        End Set
    End Property

    <System.ComponentModel.Description("ReadOnlyプロパティがFalseの時に表示される背景色です。")>
    Public Property NotReadOnlyBackColor() As System.Drawing.Color
        Get
            Return Me._notReadOnlyBackColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            Me._notReadOnlyBackColor = value
        End Set
    End Property

    <System.ComponentModel.Description("ReadOnlyプロパティがFalseの時に表示される文字色です。")>
    Public Property NotReadOnlyForeColor() As System.Drawing.Color
        Get
            Return Me._notReadOnlyForeColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            Me._notReadOnlyForeColor = value
        End Set
    End Property

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

        InitializeComponent()
        Me._components = New System.ComponentModel.Container
    End Sub

    ''' <summary>
    ''' コンボボックスのキーダウン時処理
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)

        If Not Me.ReadOnly Then
            Return
        End If

        If e.KeyCode = Keys.Delete Then
            e.Handled = True
            Return
        End If

        If e.KeyCode = Keys.Back Then
            Me._keyPressHandled = True
            Return
        End If

        If e.Control Then
            Select Case e.KeyCode
                Case Keys.V, Keys.X
                    Me._keyPressHandled = True
                    Return
            End Select
        End If

        If e.KeyCode = Keys.Up OrElse e.KeyCode = Keys.PageUp OrElse e.KeyCode = Keys.Down OrElse e.KeyCode = Keys.PageDown Then
            e.Handled = True
            Return
        End If

        Me._keyPressHandled = False

    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing Then
            If Not Me._components Is Nothing Then
                Me._components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub



    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)

        If Not Me.ReadOnly Then
            Me._keyPressHandled = False
            Return
        End If

        If Me._keyPressHandled Then
            e.Handled = True
            Me._keyPressHandled = False
            Return
        End If

        If Not Char.IsControl(e.KeyChar) Then
            e.Handled = True
        End If

        Me._keyPressHandled = False


    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
        MyBase.OnTextChanged(e)

        '項目全削除の場合、前回選択していた内容が残る不具合の処置
        If String.IsNullOrEmpty(Me.Text) Then
            If TypeOf Me.DataSource Is DataTable Then
                Dim dt As DataTable = DirectCast(Me.DataSource, DataTable)
                Dim rows As DataRow() = dt.Select(Me.DisplayMember + "=''")

                If 0 < rows.Length Then
                    Me.SelectedValue = rows(0)(Me.ValueMember)
                Else
                    Me.SelectedIndex = -1
                End If
            End If
        End If

    End Sub

    <SecurityPermission(SecurityAction.Demand,
        Flags:=SecurityPermissionFlag.UnmanagedCode)>
    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean

        If ((keyData And Keys.Control) = Keys.Control AndAlso
            (keyData And Keys.KeyCode) = Keys.V) OrElse
            ((keyData And Keys.Shift) = Keys.Shift AndAlso
             (keyData And Keys.KeyCode) = Keys.Insert) Then
            If Me.ReadOnly Then
                Return True
            Else
                Return MyBase.ProcessCmdKey(msg, keyData)
            End If
        Else
            Return MyBase.ProcessCmdKey(msg, keyData)
        End If

    End Function

End Class

```

```lang:ReadOnlyCombobox.Designer.vb
    <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
    Partial Class ComboBox
        Inherits System.Windows.Forms.ComboBox

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

        ' メモ: 以下のプロシージャはコンポーネント デザイナで必要です。
        ' コンポーネント デザイナを使って変更できます。
        ' コード エディタを使って変更しないでください。
        <System.Diagnostics.DebuggerStepThrough()> _
        Private Sub InitializeComponent()
            components = New System.ComponentModel.Container()
        End Sub

    End Class

```