コンボボックスのオーナードローはあちこちで解説されているので、そちらを参考にしてください。
DOBON.NETさん ComboBoxの項目を自分で描画する
今回参考にさせていただいたのはこちら。C#です。
Out Of Memoryさん オーナードローでデータバインドなコンボボックスのサンプル
DataSourceに設定したデータからDisplayMemberの値を取りだすところで、悩んでました。
たいへん参考になりました。ありがとうございます。
カラーコンボボックスのサンプルです。
Imports System.ComponentModel Public Class ColorComboBox Inherits System.Windows.Forms.ComboBox Private _ColorMember As String Public Property ColorMember() As String Get Return Me._ColorMember End Get Set(ByVal value As String) Me._ColorMember = value End Set End Property Public Sub New() InitializeComponent() 'アイテムの高さが均一の描画 Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed End Sub Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs) '描画領域の取得 Dim rctColor As New RectangleF(e.Bounds.Left, e.Bounds.Top, CSng(e.Bounds.Width * 0.3), e.Bounds.Height) Dim rctText As New RectangleF(rctColor.Right + CSng(e.Bounds.Width * 0.1), e.Bounds.Top, e.Bounds.Width, e.Bounds.Height) Dim rctTextBack As New RectangleF(rctColor.Right, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height) '文字列の描画 If (e.Index <> -1) Then '--表示する文字列の取得 Dim objTxt As Object = Me.Items(e.Index) If (Me.DataSource IsNot Nothing) Then Dim properties As PropertyDescriptorCollection = Me.BindingContext(Me.DataSource).GetItemProperties() Dim prpDisplayMember As PropertyDescriptor = properties(Me.DisplayMember) If (prpDisplayMember IsNot Nothing) Then objTxt = prpDisplayMember.GetValue(Me.Items(e.Index)) End If End If Dim txt As String = System.ComponentModel.TypeDescriptor.GetConverter(objTxt).ConvertToString(objTxt) '--表示する文字列の書式 Dim sf As StringFormat = CType(StringFormat.GenericDefault.Clone, StringFormat) sf.Alignment = StringAlignment.Near sf.LineAlignment = StringAlignment.Center '--文字列領域の前景色と背景色の取得 Dim clrTxtBack As Color Dim clrTxtFore As Color If ((e.State And DrawItemState.Disabled) <> 0) Then clrTxtBack = SystemColors.Window clrTxtFore = SystemColors.GrayText ElseIf (e.State And DrawItemState.Selected) = DrawItemState.Selected Then If (e.State And DrawItemState.ComboBoxEdit) = DrawItemState.ComboBoxEdit Then clrTxtBack = SystemColors.Window clrTxtFore = Me.ForeColor Else clrTxtBack = SystemColors.Highlight clrTxtFore = SystemColors.HighlightText End If Else clrTxtBack = SystemColors.Window clrTxtFore = Me.ForeColor End If '--文字列領域の描画 Using brush As New SolidBrush(clrTxtBack) e.Graphics.FillRectangle(brush, rctTextBack) End Using Using brush As New SolidBrush(clrTxtFore) e.Graphics.DrawString(txt, e.Font, brush, rctText, sf) End Using 'カラーボックスの描画 '--表示するカラーの取得 Dim objClr As Object = Me.Items(e.Index) If (Me.DataSource IsNot Nothing) Then Dim properties As PropertyDescriptorCollection = Me.BindingContext(Me.DataSource).GetItemProperties() Dim prpColorMember As PropertyDescriptor = properties(Me.ColorMember) If (prpColorMember IsNot Nothing) Then objClr = prpColorMember.GetValue(Me.Items(e.Index)) End If End If Dim clr As Color = CType(objClr, System.Drawing.Color) Using backBrush As New SolidBrush(clr) e.Graphics.FillRectangle(backBrush, rctColor) End Using End If ''Forcus枠の描画 'If ((e.State And DrawItemState.Focus) <> 0) Then ' e.DrawFocusRectangle() 'End If End Sub End Class
テストコードです。
フォームにカラーコンボボックスを2つ配置し以下のコードを実行します。
Public Class Form1 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim props As System.Reflection.PropertyInfo() = GetType(Color).GetProperties(System.Reflection.BindingFlags.Public Or System.Reflection.BindingFlags.Static) 'ItemsプロパティにColorオブジェクトを追加 Dim items As New List(Of Object) For Each prop As System.Reflection.PropertyInfo In props If (prop.PropertyType IsNot GetType(Color)) Then Continue For End If Dim color As Color = CType(prop.GetValue(Nothing, Nothing), Color) If (color = color.Transparent) Then Continue For Else items.Add(color) End If Next Me.ColorComboBox1.Items.AddRange(items.ToArray) 'DataSourceにDataTableを指定 Dim dt As New DataTable() dt.Columns.Add("Cd", GetType(Integer)) dt.Columns.Add("Color", GetType(Color)) dt.Columns.Add("Name", GetType(String)) Dim cd As Integer = 1 For Each prop As System.Reflection.PropertyInfo In props If (prop.PropertyType IsNot GetType(Color)) Then Continue For End If Dim color As Color = CType(prop.GetValue(Nothing, Nothing), Color) If (color = color.Transparent) Then Continue For Else dt.Rows.Add(cd, color, color.Name) cd += 1 End If Next Me.ColorComboBox2.ValueMember = "Cd" Me.ColorComboBox2.DisplayMember = "Name" Me.ColorComboBox2.ColorMember = "Color" Me.ColorComboBox2.DataSource = dt End Sub End Class
0 件のコメント:
コメントを投稿