DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

ListBoxの項目を自分で描画する

つまり、リストボックスをオーナードローする方法です。なお、CheckedListBoxではオーナードローはできません。

まず、オーナードローするリストボックスのDrawModeプロパティをDrawMode.OwnerDrawFixedまたはDrawMode.OwnerDrawVariableにします。OwnerDrawFixedの場合、項目の高さを個別に変更することができません(つまり、すべての項目が同じ高さとなります)。OwnerDrawVariableを指定した時は、MeasureItemイベントハンドラで項目の高さを個別に指定できます。MeasureItemイベントが発生するのは、DrawModeプロパティがOwnerDrawVariableに指定されている時のみです。

項目の描画はDrawItemイベントハンドラで行います。e.Graphicsで得られるGraphicsオブジェクトに対して具体的な描画を行います。

次に具体的な例を示します。この例では、リストボックスListBox1をオーナードローにより、赤、青、緑の順番で項目を描画するようにしています。

VB.NET
コードを隠すコードを選択
'Form1のLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    '同じサイズでオーナードローする
    'MeasureItemは発生しない
    'DrawMode.OwnerDrawVariableを指定した時は、
    'MeasureItemで項目の高さを指定する
    ListBox1.DrawMode = DrawMode.OwnerDrawFixed
    'ListBox1に項目を追加する
    Dim i As Integer
    For i = 0 To 9
        ListBox1.Items.Add((i.ToString() + "番目の項目"))
    Next i
End Sub

'DrawItemイベントハンドラ
'項目を描画する
Private Sub ListBox1_DrawItem1(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DrawItemEventArgs) _
        Handles ListBox1.DrawItem
    '背景を描画する
    '項目が選択されている時は強調表示される
    e.DrawBackground()

    'ListBoxが空のときにListBoxが選択されるとe.Indexが-1になる
    If e.Index > -1 Then
        '文字を描画する色の選択
        Dim b As Brush = Nothing
        If (e.State And DrawItemState.Selected) <> DrawItemState.Selected Then
            '選択されていない時
            Select Case e.Index Mod 3
                Case 0
                    b = New SolidBrush(Color.Red)
                Case 1
                    b = New SolidBrush(Color.Blue)
                Case 2
                    b = New SolidBrush(Color.Green)
            End Select
        Else
            '選択されている時はそのままの前景色を使う
            b = New SolidBrush(e.ForeColor)
        End If
        '描画する文字列の取得
        Dim txt As String = CType(sender, ListBox).Items(e.Index).ToString()
        '文字列の描画
        e.Graphics.DrawString(txt, e.Font, b, e.Bounds.X, e.Bounds.Y)
        '後始末
        b.Dispose()
    End If

    'フォーカスを示す四角形を描画
    e.DrawFocusRectangle()
End Sub
C#
コードを隠すコードを選択
//Form1のLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //同じサイズでオーナードローする
    //MeasureItemは発生しない
    //DrawMode.OwnerDrawVariableを指定した時は、
    //MeasureItemで項目の高さを指定する
    ListBox1.DrawMode = DrawMode.OwnerDrawFixed;
    //ListBox1に項目を追加する
    for (int i = 0; i < 10; i++)
        ListBox1.Items.Add(i.ToString() + "番目の項目");
}

//DrawItemイベントハンドラ
//項目を描画する
private void ListBox1_DrawItem(object sender, 
    System.Windows.Forms.DrawItemEventArgs e)
{
    //背景を描画する
    //項目が選択されている時は強調表示される
    e.DrawBackground();

    //ListBoxが空のときにListBoxが選択されるとe.Indexが-1になる
    if (e.Index > -1)
    {
        //文字を描画する色の選択
        Brush b = null;
        if ((e.State & DrawItemState.Selected) != DrawItemState.Selected)
        {
            //選択されていない時
            switch (e.Index % 3)
            {
                case 0:
                    b = new SolidBrush(Color.Red);
                    break;
                case 1:
                    b = new SolidBrush(Color.Blue);
                    break;
                case 2:
                    b = new SolidBrush(Color.Green);
                    break;
            }
        }
        else
        {
            //選択されている時はそのままの前景色を使う
            b = new SolidBrush(e.ForeColor);
        }
        //描画する文字列の取得
        string txt = ((ListBox)sender).Items[e.Index].ToString();
        //文字列の描画
        e.Graphics.DrawString(txt, e.Font, b, e.Bounds);
        //後始末
        b.Dispose();
    }

    //フォーカスを示す四角形を描画
    e.DrawFocusRectangle();
}
  • 履歴:
  • 2009/12/3 ListBoxが空のときにエラーが出る不具合を修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。