広告

.NETのListViewをちょっとオシャレにカスタマイズ

フリーソフト等で、リストビューのヘッダーが標準のものからカスタマイズされていることがありますよね。

例えば、FenrirFSが該当します。

FenrirFS

このような感じの見た目になるようなStylishListViewというListViewコントロールを作ってみました。

今回は、ヘッダーのカスタマイズの他に、奇数行、偶数行の色分けも実装しました。

左が標準コントロール、右が今回作成したカスタムコントロールです。

標準コントロールStylishListView

実装プロパティ説明

コントロールには、以下のプロパティが実装されています。

項目名 説明
HeaderTopColor ヘッダーの上部色
HeaderBottomColor ヘッダーの下部色
HeaderBorderColor ヘッダーの枠線色
ViewStylishHeader ヘッダーをカスタマイズするか
EvenBackColor 偶数行の背景色
EvenForeColor 偶数行の前景色
OddBackColor 奇数行の背景色
OddForeColor 奇数行の前景色
OddEvenColorCoding 奇数、偶数行を色分けするか

ソースダウンロード

以下からソースファイルをダウンロード出来ます。ソースのライセンスはGPLです。

“StylishListViewサンプルソース” をダウンロード StylishListViewTest.zip – 1625回ダウンロードされました – 46 kB

ダウンロード出来るソリューションについて

このソリューションは、コントロールが実装されている「StylishListView」プロジェクトとコントロールのテスト用プロジェクト「StylishListViewTest」の2つで出来ています。

開発言語はVB.NETで、開発環境はVisual Studio 2005です。

「StylishListView」プロジェクトは、ListViewコントロールを継承したStylishListViewコントロールと、ヘッダー画像を描画するListViewImageクラスの2つで出来ています。

ヘッダーのカスタマイズ方法について

OnDrawColumnHeaderメソッドでヘッダー描画を行います。

まず始めに、e.Graphics.DrawImageで背景画像の描画を行います。

次に、e.Graphics.DrawStringでヘッダーに表示するテキストを描画します。

ちなみに

今回は、ヘッダーには文字のみ描画していますが、画像を表示することも可能なので、ソート用のアイコンを表示したりも出来ます。

通常、リストアイテムには、左端にしかアイコンは表示出来ませんが、OnDrawSubItemメソッドを使うと、リストのサブアイテムにもアイコンや画像を表示することが出来ます。

StylishListViewコントロールのソース

ソースのライセンスはGPLです。

''' <summary>
''' 標準ListViewをちょっとオシャレにカスタマイズしたコントロールです。
''' </summary>
''' <remarks>
''' ライセンス:GNU General Public License (http://www.gnu.org/licenses/gpl.html)
''' 著作者:rider (http://www.lasical.com/)
''' </remarks>
Public Class StylishListView

#Region "変数"
    ''' <summary>
    ''' ヘッダーの上部色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _HeaderTopColor As Color = System.Drawing.ColorTranslator.FromHtml("#DCDCDC")

    ''' <summary>
    ''' ヘッダーの下部色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _HeaderBottomColor As Color = System.Drawing.ColorTranslator.FromHtml("#CDCDCD")

    ''' <summary>
    ''' ヘッダーの枠線色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _HeaderBorderColor As Color = System.Drawing.ColorTranslator.FromHtml("#7F7F7F")

    ''' <summary>
    ''' ヘッダーをカスタマイズするかの値です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _ViewStylishHeader As Boolean = False

    ''' <summary>
    ''' 偶数行の背景色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _EvenBackColor As Color = SystemColors.Window

    ''' <summary>
    ''' 偶数行の前景色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _EvenForeColor As Color = SystemColors.WindowText

    ''' <summary>
    ''' 奇数行の背景色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _OddBackColor As Color = SystemColors.Window

    ''' <summary>
    ''' 奇数行の前景色です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _OddForeColor As Color = SystemColors.WindowText

    ''' <summary>
    ''' 奇数、偶数行を色分けするかの値です。
    ''' </summary>
    ''' <remarks></remarks>
    Private _OddEvenColorCoding As Boolean = False

    Const WM_PAINT As Integer = &HF
#End Region

#Region "プロパティ"
    ''' <summary>
    ''' ヘッダーの上部色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("ヘッダーの上部色を示します。")> _
    <Category("カスタム - ヘッダー")> _
    Public Property HeaderTopColor() As Color
        Get
            Return Me._HeaderTopColor
        End Get
        Set(ByVal value As Color)
            Me._HeaderTopColor = value
        End Set
    End Property

    ''' <summary>
    ''' ヘッダーの下部色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("ヘッダーの下部色を示します。")> _
    <Category("カスタム - ヘッダー")> _
    Public Property HeaderBottomColor() As Color
        Get
            Return Me._HeaderBottomColor
        End Get
        Set(ByVal value As Color)
            Me._HeaderBottomColor = value
        End Set
    End Property

    ''' <summary>
    ''' ヘッダーの枠線色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("ヘッダーの枠線色を示します。")> _
    <Category("カスタム - ヘッダー")> _
    Public Property HeaderBorderColor() As Color
        Get
            Return Me._HeaderBorderColor
        End Get
        Set(ByVal value As Color)
            Me._HeaderBorderColor = value
        End Set
    End Property

    ''' <summary>
    ''' ヘッダーをカスタマイズするかの値を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("ヘッダーをカスタマイズするかの値を示します。")> _
    <Category("カスタム - ヘッダー")> _
    <DefaultValue(GetType(Boolean), "False")> _
    Public Property ViewStylishHeader() As Boolean
        Get
            Return Me._ViewStylishHeader
        End Get
        Set(ByVal value As Boolean)
            Me._ViewStylishHeader = value

            If value Then
                'オーナードローを有効に変更
                Me.OwnerDraw = True
            End If
        End Set
    End Property

    ''' <summary>
    ''' 偶数行の背景色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("偶数行の背景色を示します。")> _
    <Category("カスタム - リスト")> _
    <DefaultValue(GetType(Color), "Window")> _
    Public Property EvenBackColor() As Color
        Get
            Return Me._EvenBackColor
        End Get
        Set(ByVal value As Color)
            Me._EvenBackColor = value
        End Set
    End Property

    ''' <summary>
    ''' 偶数行の前景色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("偶数行の前景色を示します。")> _
    <Category("カスタム - リスト")> _
    <DefaultValue(GetType(Color), "WindowText")> _
    Public Property EvenForeColor() As Color
        Get
            Return Me._EvenForeColor
        End Get
        Set(ByVal value As Color)
            Me._EvenForeColor = value
        End Set
    End Property

    ''' <summary>
    ''' 奇数行の背景色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("奇数行の背景色を示します。")> _
    <Category("カスタム - リスト")> _
    <DefaultValue(GetType(Color), "Window")> _
    Public Property OddBackColor() As Color
        Get
            Return Me._OddBackColor
        End Get
        Set(ByVal value As Color)
            Me._OddBackColor = value
        End Set
    End Property

    ''' <summary>
    ''' 奇数行の前景色を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("奇数行の前景色を示します。")> _
    <Category("カスタム - リスト")> _
    <DefaultValue(GetType(Color), "WindowText")> _
    Public Property OddForeColor() As Color
        Get
            Return Me._OddForeColor
        End Get
        Set(ByVal value As Color)
            Me._OddForeColor = value
        End Set
    End Property

    ''' <summary>
    ''' 奇数、偶数行を色分けするかの値を取得または設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("奇数、偶数行を色分けするかの値を示します。")> _
    <Category("カスタム - リスト")> _
    <DefaultValue(GetType(Boolean), "False")> _
    Public Property OddEvenColorCoding() As Boolean
        Get
            Return Me._OddEvenColorCoding
        End Get
        Set(ByVal value As Boolean)
            Me._OddEvenColorCoding = value
        End Set
    End Property
#End Region

#Region "コンストラクタ"
    ''' <summary>
    ''' StylishListViewのコンストラクタです。
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        ' この呼び出しは、Windows フォーム デザイナで必要です。
        InitializeComponent()

        'リストビューを詳細表示に設定
        Me.View = System.Windows.Forms.View.Details
    End Sub
#End Region

#Region "WndProc"
    ''' <summary>
    ''' WndProcをオーバーライド
    ''' </summary>
    ''' <param name="m"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)

        'メッセージの種類
        Select Case m.Msg
            Case WM_PAINT
                'リストの偶数、奇数の色分けをするか(デザインモードの時も処理しない)
                If DesignMode = False AndAlso Me._OddEvenColorCoding Then
                    Me.OnPaint(New PaintEventArgs(Me.CreateGraphics, Me.Bounds))
                End If
        End Select
    End Sub
#End Region

#Region "イベント"
    ''' <summary>
    ''' ペイントメソッドオーバーライド
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        '偶数行と奇数行の色分け
        For i As Integer = 0 To Me.Items.Count - 1
            If i / 2 <> Int(i / 2) Then
                Me.Items(i).BackColor = Me._EvenBackColor
                Me.Items(i).ForeColor = Me._EvenForeColor
            Else
                Me.Items(i).BackColor = Me._OddBackColor
                Me.Items(i).ForeColor = Me._OddForeColor
            End If
        Next
    End Sub
#End Region

#Region "ヘッダー描画時"
    ''' <summary>
    ''' ヘッダー描画時の処理です。
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnDrawColumnHeader(ByVal e As System.Windows.Forms.DrawListViewColumnHeaderEventArgs)
        MyBase.OnDrawColumnHeader(e)

        'カスタムヘッダーを使うか
        If Me._ViewStylishHeader Then
            '自分で描画
            e.DrawDefault = False
        Else
            '標準描画
            e.DrawDefault = True

            '終了
            Exit Sub
        End If

        Dim TextBrush As System.Drawing.Brush
        Dim HeaderStringFormat As StringFormat

        'ヘッダーテキストのブラシ取得
        TextBrush = New SolidBrush(e.ForeColor)

        'ヘッダーテキストの描画フォーマット取得
        HeaderStringFormat = GetDrawHeaderStringFormat(e.ColumnIndex)

        '背景描画
        e.Graphics.DrawImage(ListViewImage.HeaderBackgroundImage(e.Bounds.Width, e.Bounds.Height - 1, Me._HeaderTopColor, Me._HeaderBottomColor, Me._HeaderBorderColor, e.ColumnIndex), e.Bounds.Left, e.Bounds.Top)

        'テキスト描画
        e.Graphics.DrawString(e.Header.Text, e.Font, TextBrush, e.Bounds, HeaderStringFormat)

        '開放
        TextBrush.Dispose()
    End Sub
#End Region

#Region "アイテム描画時"
    ''' <summary>
    ''' アイテム描画時の処理です。
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawListViewItemEventArgs)
        MyBase.OnDrawItem(e)

        '標準描画
        e.DrawDefault = True
    End Sub
#End Region

#Region "ヘッダーテキストの文字列描画設定取得"
    ''' <summary>
    ''' ヘッダーテキストの文字列描画設定を取得します。
    ''' </summary>
    ''' <param name="ColumnIndex">カラム番号です。</param>
    ''' <remarks></remarks>
    Private Function GetDrawHeaderStringFormat(ByVal ColumnIndex As Integer) As StringFormat
        Dim SubItemStringFormat As New StringFormat

        'テキストの描画位置
        Select Case Me.Columns(ColumnIndex).TextAlign
            Case HorizontalAlignment.Left
                SubItemStringFormat.Alignment = StringAlignment.Near
            Case HorizontalAlignment.Right
                SubItemStringFormat.Alignment = StringAlignment.Far
            Case HorizontalAlignment.Center
                SubItemStringFormat.Alignment = StringAlignment.Center
        End Select
        SubItemStringFormat.LineAlignment = StringAlignment.Center

        '末尾に省略記号を表示する
        SubItemStringFormat.Trimming = StringTrimming.EllipsisCharacter

        '折り返し
        If Me.LabelWrap = False Then
            SubItemStringFormat.FormatFlags = StringFormatFlags.NoWrap
        End If

        'ヘッダーの文字は左寄せ固定
        SubItemStringFormat.Alignment = StringAlignment.Near

        '折り返し
        SubItemStringFormat.FormatFlags = StringFormatFlags.NoWrap

        Return SubItemStringFormat
    End Function
#End Region
End Class

ListViewImageクラスのソース

ソースのライセンスはGPLです。

''' <summary>
''' リストビュー用の画像を取得します。
''' </summary>
''' <remarks>
''' ライセンス:GNU General Public License (http://www.gnu.org/licenses/gpl.html)
''' 著作者:rider (http://www.lasical.com/)
''' </remarks>
Public Class ListViewImage

#Region "ヘッダー用画像"
    ''' <summary>
    ''' リストビューヘッダー用の背景画像を作成します。
    ''' </summary>
    ''' <param name="Width">リストビューヘッダーの横幅です。</param>
    ''' <param name="Height">リストビューヘッダーの高さです。</param>
    ''' <param name="TopColor">上部の色です。</param>
    ''' <param name="BottomColor">下部の色です。</param>
    ''' <param name="BorderColor">枠線色です。</param>
    ''' <param name="ColumnIndex">ヘッダーのカラムインデックスです。</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function HeaderBackgroundImage(ByVal Width As Integer, ByVal Height As Integer, ByVal TopColor As Color, ByVal BottomColor As Color, ByVal BorderColor As Color, ByVal ColumnIndex As Integer) As Image
        Dim HeaderImage As Image
        Dim HeaderGraphics As Graphics
        Dim HeaderBrush As SolidBrush
        Dim SplendorPen As Pen
        Dim BorderPen As Pen

        '引数チェック
        If Width = 0 OrElse Height = 0 Then
            Return Nothing
        End If

        '描画用の画像作成
        HeaderImage = New Bitmap(Width, Height)
        HeaderGraphics = Graphics.FromImage(HeaderImage)

        '上に色を塗る
        HeaderBrush = New SolidBrush(TopColor)
        HeaderGraphics.FillRectangle(HeaderBrush, 0, 0, Width, CInt(Height * 0.45))
        HeaderBrush.Dispose()

        '下に色を塗る
        HeaderBrush = New SolidBrush(BottomColor)
        HeaderGraphics.FillRectangle(HeaderBrush, 0, CInt(Height * 0.45), Width, CInt(Height * 0.55))
        HeaderBrush.Dispose()

        '枠線を引く
        If ColumnIndex = 0 Then
            BorderPen = New Pen(BorderColor)
            HeaderGraphics.DrawRectangle(BorderPen, 0, -1, Width - 1, Height)
            BorderPen.Dispose()
        Else
            BorderPen = New Pen(BorderColor)
            HeaderGraphics.DrawRectangle(BorderPen, -1, -1, Width, Height)
            BorderPen.Dispose()
        End If

        '光彩描画
        SplendorPen = New Pen(Color.FromArgb(64, Color.MintCream), 1)
        HeaderGraphics.DrawRectangle(SplendorPen, 1, 0, Width - 3, Height - 1)
        SplendorPen.Dispose()
        SplendorPen = New Pen(Color.FromArgb(24, Color.MintCream), 1)
        HeaderGraphics.DrawRectangle(SplendorPen, 2, 1, Width - 5, Height - 3)
        SplendorPen.Dispose()

        '開放
        HeaderGraphics.Dispose()

        Return HeaderImage
    End Function
#End Region
End Class

Share on Facebook

コメントは利用できません。

広告

Facebook

カレンダー

2011年1月
« 12月   2月 »
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

最近の投稿

アーカイブ