ユーザーがチェックされたコンボボックスのチェックボックスをオンまたはオフにしたときに、ドロップダウンリストが閉じないようにしたいと思います。
Microsoft コードをコピーして、チェック付きコンボボックスを作成しました。そのままでは動かないので、カスタマイズしました。
これが私のコードです:
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Public Class CheckedCombobox
Inherits ComboBox
Public Event ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs)
<Browsable(False)> _
Public Overloads ReadOnly Property Items() As ComboBox.ObjectCollection
Get
Return MyBase.Items
End Get
End Property
Private WithEvents _ItemCollection As New ObservableCollection(Of String)
Public Property ItemCollection As ObservableCollection(Of String)
Get
Return _ItemCollection
End Get
Set(value As ObservableCollection(Of String))
_ItemCollection = value
End Set
End Property
Private _ItemDictionary As New Dictionary(Of String, Boolean)
Public ReadOnly Property ItemDictionary As Dictionary(Of String, Boolean)
Get
Return _ItemDictionary
End Get
End Property
Public ReadOnly Property CheckedItemCollection As List(Of String)
Get
Return New List(Of String)(From item In ItemDictionary Where item.Value = True Select item.Key)
End Get
End Property
Public ReadOnly Property UnCheckedItemCollection As List(Of String)
Get
Return New List(Of String)(From item In ItemDictionary Where item.Value = False Select item.Key)
End Get
End Property
Public Sub setCheckState(ByVal key As String, ByVal checkstate As Boolean)
_ItemDictionary(key) = checkstate
End Sub
Public Function getCheckState(ByVal key As String)
Return (_ItemDictionary(key))
End Function
Public Sub New()
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawVariable
End Sub
Protected Overrides Sub OnCreateControl()
MyBase.OnCreateControl()
For Each item In ItemCollection
_ItemDictionary.Add(item, False)
Next
End Sub
Private Sub ItemsChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Handles _ItemCollection.CollectionChanged
Select Case e.Action
Case Specialized.NotifyCollectionChangedAction.Add
If e.NewStartingIndex = ItemDictionary.Count Then
_ItemDictionary.Add(e.NewItems(0), False)
MyBase.Items.Add(e.NewItems(0))
End If
Case Specialized.NotifyCollectionChangedAction.Remove
_ItemDictionary.Remove(MyBase.Items(e.OldStartingIndex))
MyBase.Items.RemoveAt(e.OldStartingIndex)
Case Specialized.NotifyCollectionChangedAction.Move
Dim _item As Object = MyBase.Items(e.OldStartingIndex)
MyBase.Items.RemoveAt(e.OldStartingIndex)
MyBase.Items.Insert(e.NewStartingIndex, _item)
Case Specialized.NotifyCollectionChangedAction.Replace
Throw New Exception("Not implemented yet!")
Case Specialized.NotifyCollectionChangedAction.Reset
Dim _checkeditems As New List(Of String)(CheckedItemCollection)
MyBase.Items.Clear()
MyBase.Items.AddRange(_ItemCollection.ToArray)
_ItemDictionary.Clear()
For Each item In _ItemCollection
_ItemDictionary.Add(item, _checkeditems.Contains(item))
Next
End Select
Me.Invalidate()
End Sub
Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
e.DrawBackground()
Dim p As Point = e.Bounds.Location
If e.Index >= 0 Then
p.Offset(1, 1)
If getCheckState(MyBase.Items(e.Index)) Then
CheckBoxRenderer.DrawCheckBox(e.Graphics, p, VisualStyles.CheckBoxState.CheckedNormal)
Else
CheckBoxRenderer.DrawCheckBox(e.Graphics, p, VisualStyles.CheckBoxState.UncheckedNormal)
End If
p.Offset(12, 0)
e.Graphics.DrawString(MyBase.GetItemText(Me.Items(e.Index)), e.Font, New SolidBrush(e.ForeColor), p.X, p.Y)
End If
If e.State = DrawItemState.Selected Then
e.DrawFocusRectangle()
End If
MyBase.OnDrawItem(e)
End Sub
Private Sub checkedChanged(ByVal index As Integer)
Dim checked As Boolean = _ItemDictionary(MyBase.Items.Item(index))
If checked Then
_ItemDictionary(MyBase.Items.Item(index)) = False
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Unchecked, CheckState.Checked))
Else
_ItemDictionary(MyBase.Items.Item(index)) = True
RaiseEvent ItemCheck(Me, New ItemCheckEventArgs(index, CheckState.Checked, CheckState.Unchecked))
End If
Me.Invalidate()
End Sub
Private n As nWindow = Nothing
Private Const WM_CTLCOLORLISTBOX As Integer = &H134
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If m.Msg = WM_CTLCOLORLISTBOX Then
If n Is Nothing Then
n = New nWindow(Me)
n.AssignHandle(m.LParam)
AddHandler n.checkedChanged, AddressOf checkedChanged
End If
End If
End Sub
Private Sub CheckedCombobox_Click(sender As Object, e As System.EventArgs) Handles Me.SelectedIndexChanged
Debugger.Break()
End Sub
End Class
Public Class nWindow
Inherits NativeWindow
Private Const WM_LBUTTONDOWN As Integer = &H201
Private _combobox As CheckedCombobox
Public Event checkedChanged(ByVal index As Integer)
Public Sub New(ByVal cb As CheckedCombobox)
_combobox = cb
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_LBUTTONDOWN Then
Dim itemHeight As Integer = _combobox.ItemHeight
If New Point(m.LParam.ToInt32).Y \ itemHeight <= _combobox.Items.Count - 1 And New Point(m.LParam.ToInt32).Y \ itemHeight >= 0 Then
If New Point(m.LParam.ToInt32).X >= 1 And New Point(m.LParam.ToInt32).X <= 11 Then
RaiseEvent checkedChanged(_combobox.SelectedIndex)
End If
End If
End If
MyBase.WndProc(m)
End Sub
End Class