2013年8月4日日曜日

【VB.NET ・C#】DataGridViewの列ヘッダーの複数行表示するカスタムコントロール①

DataGridViewを継承して列ヘッダーの複数行表示をするカスタムコントロールをつくります。

先ずは列ヘッダーのセルの結合のための定義をコレクションエディターで表示するためにHeaderCellクラスをプロジェクトに追加します。ヘッダーセル定義は以下の項目にします。
項目意味
Column
Row
ColumnSpan結合する列数
RowSpan結合する行数
BackgroundColorセルの背景色
ForeColorセルの文字色
SortVisible結合したセル内にソートされた列がある場合のソート方向の表示の有無
Textセルに関連付けられたテキスト
TextAlign結合されたセル内のテキストの位置

VB.NET
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing

'Public Class HeaderCellColection
'    Inherits System.Collections.Generic.List(Of HeaderCell)
'End Class

''' <summary>
''' ヘッダーセル定義
''' </summary>
''' <remarks></remarks>
Public Class HeaderCell

    Private _row As Integer
    ''' <summary>
    ''' 行
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル位置")> _
    <Description("行")>
    Public Property Row As Integer
        Get
            Return _row
        End Get
        Set(ByVal value As Integer)
            _row = value
        End Set
    End Property

    Private _column As Integer
    ''' <summary>
    ''' 列
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル位置")> _
    <Description("列")>
    Public Property Column As Integer
        Get
            Return _column
        End Get
        Set(ByVal value As Integer)
            _column = value
        End Set
    End Property

    Private _rowSpan As Integer = 1
    ''' <summary>
    ''' 結合する行数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル結合")> _
    <Description("行数")>
    Public Property RowSpan As Integer
        Get
            Return _rowSpan
        End Get
        Set(ByVal value As Integer)
            _rowSpan = value
        End Set
    End Property

    Private _columnSpan As Integer = 1
    ''' <summary>
    ''' 結合する列数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル結合")> _
    <Description("列数")>
    Public Property ColumnSpan As Integer
        Get
            Return _columnSpan
        End Get
        Set(ByVal value As Integer)
            _columnSpan = value
        End Set
    End Property

    Private _backgroundColor As System.Drawing.Color = Color.Empty
    ''' <summary>
    ''' セルの背景色
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セルの背景色")>
    Public Property BackgroundColor As System.Drawing.Color
        Get
            Return _backgroundColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            _backgroundColor = value
        End Set
    End Property

    Private _foreColor As System.Drawing.Color = Color.Empty
    ''' <summary>
    ''' テキストの文字色
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("テキストの文字色")>
    Public Property ForeColor As System.Drawing.Color
        Get
            Return _foreColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            _foreColor = value
        End Set
    End Property


    Private _text As String
    ''' <summary>
    ''' セルに関連付けられたテキスト
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セルに関連付けられたテキストです")>
    Public Property Text As String
        Get
            Return _text
        End Get
        Set(ByVal value As String)
            _text = value
        End Set
    End Property

    Private _textAlign As DataGridViewContentAlignment
    ''' <summary>
    ''' 結合されたセル内でのテキストの位置
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("結合されたセル内のテキストの位置を決定します")>
    Public Property TextAlign As DataGridViewContentAlignment
        Get
            Return _textAlign
        End Get
        Set(ByVal value As DataGridViewContentAlignment)
            _textAlign = value
        End Set
    End Property

    Private _wrapMode As DataGridViewTriState = DataGridViewTriState.NotSet
    ''' <summary>
    ''' セルに含まれるテキスト形式の内容が 1 行に収まらないほど長い場合に、次の行に折り返されるか、
    ''' 切り捨てられるかを示す値を取得または設定する
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セル内のテキストが一行に収まらない場合にテキストを折り返す")>
    Public Property WrapMode As DataGridViewTriState
        Get
            Return _wrapMode
        End Get
        Set(ByVal value As DataGridViewTriState)
            _wrapMode = value
        End Set
    End Property

    Private _sortVisible As Boolean
    ''' <summary>
    ''' 結合されている列に並び替えがある場合に並び替えの方向を表示する
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("結合されている列に並び替えがある場合に並び替えの方向を表示する")>
    Public Property SortVisible As Boolean
        Get
            Return _sortVisible
        End Get
        Set(ByVal value As Boolean)
            _sortVisible = value
        End Set
    End Property
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace ClassLibrary1
{
    class HeaderCell

    {
        private int _row;
        /// 
        /// 行
        /// 
        /// 
        /// 
        /// 
        [Category("セル位置")]
        [Description("行")]
        public int Row
        {
            get { return _row; }
            set { _row = value; }
        }

        private int _column;
        /// 
        /// 列
        /// 
        /// 
        /// 
        /// 
        [Category("セル位置")]
        [Description("列")]
        public int Column
        {
            get { return _column; }
            set { _column = value; }
        }

        private int _rowSpan = 1;
        /// 
        /// 結合する行数
        /// 
        /// 
        /// 
        /// 
        [Category("セル結合")]
        [Description("行数")]
        public int RowSpan
        {
            get { return _rowSpan; }
            set { _rowSpan = value; }
        }

        private int _columnSpan = 1;
        /// 
        /// 結合する列数
        /// 
        /// 
        /// 
        /// 
        [Category("セル結合")]
        [Description("列数")]
        public int ColumnSpan
        {
            get { return _columnSpan; }
            set { _columnSpan = value; }
        }

        private System.Drawing.Color _backgroundColor = Color.Empty;
        /// 
        /// セルの背景色
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セルの背景色")]
        public System.Drawing.Color BackgroundColor
        {
            get { return _backgroundColor; }
            set { _backgroundColor = value; }
        }

        private System.Drawing.Color _foreColor = Color.Empty;
        /// 
        /// テキストの文字色
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("テキストの文字色")]
        public System.Drawing.Color ForeColor
        {
            get { return _foreColor; }
            set { _foreColor = value; }
        }


        private string _text;
        /// 
        /// セルに関連付けられたテキスト
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セルに関連付けられたテキストです")]
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        private DataGridViewContentAlignment _textAlign;
        /// 
        /// 結合されたセル内でのテキストの位置
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("結合されたセル内のテキストの位置を決定します")]
        public DataGridViewContentAlignment TextAlign
        {
            get { return _textAlign; }
            set { _textAlign = value; }
        }

        private DataGridViewTriState _wrapMode = DataGridViewTriState.NotSet;
        /// 
        /// セルに含まれるテキスト形式の内容が 1 行に収まらないほど長い場合に、次の行に折り返されるか、
        /// 切り捨てられるかを示す値を取得または設定する
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セル内のテキストが一行に収まらない場合にテキストを折り返す")]
        public DataGridViewTriState WrapMode
        {
            get { return _wrapMode; }
            set { _wrapMode = value; }
        }

        private bool _sortVisible;
        /// 
        /// 結合されている列に並び替えがある場合に並び替えの方向を表示する
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("結合されている列に並び替えがある場合に並び替えの方向を表示する")]
        public bool SortVisible
        {
            get { return _sortVisible; }
            set { _sortVisible = value; }
        }
    }
}

次にDataGridViewの継承クラスを作成します。

クラスに以下ののプロパティを追加。
プロパティ意味
ColumnHeaderBorderStyle列ヘッダーセルの境界線の線種
ColumnHeaderRowCount列ヘッダーの行数
ColumnHeaderRowHeight列ヘッダーの行の高さ
HeaderCells列ヘッダーのセル定義

次にOnPaintイベントにヘッダセルの描画処理とセルの結合の描画処理を記述します。

スクロール時、コントロールのサイズ変更時および列の幅が変更された時に直前の描画が
残るのを防ぐために描画領域の無効化をしています。
VB.NET
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing
'Imports MyLibrary.HeaderCell


Public Class CustomHeaderDataGridView
    Inherits System.Windows.Forms.DataGridView

    Private _item As New MyCollection(Me)

    ''' <summary>
    ''' 列ヘッダに表示するCellを設定します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示するCellを設定します")>
    Public ReadOnly Property HeaderCells() As MyCollection
        Get
            Return _item
        End Get
    End Property

    Friend Sub OnCollectionChanged()
        Me.Invalidate()
    End Sub



    ''' <summary>
    ''' コレクションの設定
    ''' </summary>
    ''' <remarks></remarks>
    Public Class MyCollection
        Inherits System.Collections.ObjectModel.Collection(Of HeaderCell)

        Private _parent As CustomHeaderDataGridView

        Friend Sub New(ByVal parent As CustomHeaderDataGridView)
            _parent = parent
        End Sub

        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As HeaderCell)
            MyBase.InsertItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub RemoveItem(ByVal index As Integer)
            MyBase.RemoveItem(index)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As HeaderCell)
            MyBase.SetItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

    End Class


    Private _columnHeaderRowCount As Integer = 1
    ''' <summary>
    ''' 列ヘッダーの行数を設定します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示する行を設定します")>
    Public Property ColumnHeaderRowCount As Integer
        Get
            Return _columnHeaderRowCount
        End Get
        Set(ByVal value As Integer)



            _columnHeaderRowCount = value

            If value = 0 Then
                _columnHeaderRowCount = 1
            End If

            MyBase.ColumnHeadersHeight = value * ColumnHeaderRowHeight + 2
            MyBase.Refresh()
        End Set
    End Property

    Private _columnHeaderRowHeight As Integer = 17
    ''' <summary>
    ''' 列ヘッダに表示する行の高さ
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示する行の高さを設定します")>
    Public Property ColumnHeaderRowHeight As Integer
        Get
            Return _columnHeaderRowHeight
        End Get
        Set(ByVal value As Integer)
            _columnHeaderRowHeight = value

            MyBase.ColumnHeadersHeight = value * ColumnHeaderRowCount + 2
            MyBase.Refresh()
        End Set
    End Property

    ''' <summary>
    ''' 列ヘッダーの境界線の種類
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum HeaderCellBorderStyle
        SingleLine = 0
        DoubleLine = 1
    End Enum

    Private _columnHeaderBorderStyle As HeaderCellBorderStyle = HeaderCellBorderStyle.SingleLine
    ''' <summary>
    ''' 列ヘッダーの線種
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに線種を設定します")>
    Public Property ColumnHeaderBorderStyle As HeaderCellBorderStyle
        Get
            Return _columnHeaderBorderStyle
        End Get
        Set(ByVal value As HeaderCellBorderStyle)
            _columnHeaderBorderStyle = value
            MyBase.Refresh()
        End Set
    End Property

    <System.Diagnostics.DebuggerNonUserCode()> _
    Public Sub New()
        MyBase.New()

        'この呼び出しは、コンポーネント デザイナーで必要です。
        InitializeComponent()

        MyBase.DoubleBuffered = True

    End Sub

    'Component は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

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

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

    

    ''' <summary>
    ''' 再描画をするとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Try

            
            '---------------------------------------------------------------------------------------------------------
            'ヘッダーセルの描画
            '---------------------------------------------------------------------------------------------------------

            'ヘッダーの行の高さの取得
            Dim rowHeight As Integer = MyBase.ColumnHeadersHeight

            If Me.ColumnHeaderRowCount > 0 Then
                rowHeight = MyBase.ColumnHeadersHeight / Me.ColumnHeaderRowCount
            End If

            '線の太さ
            Dim lineWidth As Integer = 1

            For i = 0 To ColumnCount - 1

                For j = 0 To Me.ColumnHeaderRowCount - 1

                    'グッリドの線
                    Dim gridPen As New Pen(MyBase.GridColor)

                    '背景色
                    Dim backBrash As New SolidBrush(MyBase.ColumnHeadersDefaultCellStyle.BackColor)

                    'くぼみ線
                    Dim whiteBrash As New SolidBrush(Color.White)

                    Try
                        '列ヘッダーの描画領域
                        Dim rect As Rectangle = MyBase.GetCellDisplayRectangle(i, -1, True)

                        '列ヘッダーの描画領域の底部の座標を保存
                        Dim btm As Integer = rect.Bottom

                        'セルの描画領域のY座標
                        Select Case MyBase.BorderStyle
                            Case Windows.Forms.BorderStyle.None
                                rect.Y = rowHeight * j
                            Case Windows.Forms.BorderStyle.FixedSingle
                                rect.Y = rowHeight * j + lineWidth
                            Case Windows.Forms.BorderStyle.Fixed3D
                                rect.Y = rowHeight * j + (lineWidth * 2)
                        End Select

                        'セルの描画領域のX座標
                        rect.X -= lineWidth

                        'セルの描画領域の高さ
                        rect.Height = rowHeight

                        '最下行の場合高さを調整
                        If j = Me.ColumnHeaderRowCount - 1 Then
                            rect.Height = btm - rect.Y - lineWidth
                        End If

                        'セルを囲む線の描画
                        e.Graphics.DrawRectangle(gridPen, rect)


                        'セルの背景色の領域
                        rect.Y += lineWidth
                        rect.X += lineWidth
                        rect.Height -= lineWidth
                        rect.Width -= lineWidth

                        '背景色の描画
                        If ColumnHeaderBorderStyle <> HeaderCellBorderStyle.DoubleLine Then
                            'Single線の場合
                            e.Graphics.FillRectangle(backBrash, rect)
                        Else
                            'くぼみ線の場合
                            'rect.Width -= lineWidth
                            e.Graphics.FillRectangle(whiteBrash, rect)
                            rect.Y += lineWidth
                            rect.X += lineWidth
                            rect.Height -= lineWidth
                            rect.Width -= lineWidth

                            e.Graphics.FillRectangle(backBrash, rect)
                        End If

                        '見出しを最下列に表示
                        If j = Me.ColumnHeaderRowCount - 1 Then
                            Dim text As String = MyBase.Columns(i).HeaderText

                            If MyBase.SortedColumn IsNot Nothing AndAlso MyBase.SortedColumn Is Me.Columns(i) Then
                                If MyBase.SortOrder = Windows.Forms.SortOrder.Ascending Then
 text = text & "  ▼"
                                ElseIf MyBase.SortOrder = Windows.Forms.SortOrder.Descending Then
 text = text & "  ▲"
                                End If
                            End If

                            Dim formatFlg As TextFormatFlags = GetTextFormatFlags(MyBase.ColumnHeadersDefaultCellStyle.Alignment, _
MyBase.ColumnHeadersDefaultCellStyle.WrapMode)

                            TextRenderer.DrawText(e.Graphics, text, MyBase.ColumnHeadersDefaultCellStyle.Font, _
rect, MyBase.ColumnHeadersDefaultCellStyle.ForeColor, _
formatFlg)
                        End If

                    Finally
                        'リソースの解放
                        gridPen.Dispose()
                        backBrash.Dispose()
                        whiteBrash.Dispose()
                    End Try
                Next
            Next


            '---------------------------------------------------------------------------------------------------------
            'ヘッダーのセル結合
            '---------------------------------------------------------------------------------------------------------
            'ヘッダーセル定義の処理
            For i = 0 To Me.HeaderCells.Count - 1

                'セルの結合の開始行がヘッダーの行数より大きい場合は除外
                If HeaderCells(i).Row > Me.ColumnHeaderRowCount - 1 Then
                    Continue For
                End If

                'セルの結合の開始列の列インデックスが列数より大きい場合は除外
                If HeaderCells(i).Column > MyBase.ColumnCount - 1 Then
                    Continue For
                End If

                '描画領域の設定
                Dim rect As Rectangle = Nothing

                '結合する列中のソート状態
                Dim sortText As String = String.Empty

                '結合するセルの各列の幅を取得し描画領域の幅を決める、ソートされている列の場合Textに表示するソート方向の設定
                For j = Me.HeaderCells(i).Column To Me.HeaderCells(i).Column + Me.HeaderCells(i).ColumnSpan - 1

                    '列が画面に表示されていない場合は処理しない
                    If MyBase.Columns(j).Displayed = False Then
                        Continue For
                    End If

                    '列ヘッダーの領域の幅
                    If rect = Nothing Then
                        '結合するセルの開始列の場合
                        rect = MyBase.GetCellDisplayRectangle(j, -1, True)
                    Else
                        '結合するセルの2列目以降の場合
                        rect.Width += MyBase.GetCellDisplayRectangle(j, -1, True).Width
                    End If


                    'ソート列の場合
                    If HeaderCells(i).SortVisible = True AndAlso MyBase.SortedColumn IsNot Nothing AndAlso MyBase.SortedColumn Is MyBase.Columns(j) Then
                        If MyBase.SortOrder = Windows.Forms.SortOrder.Ascending Then
                            sortText = "  ▼"
                        ElseIf MyBase.SortOrder = Windows.Forms.SortOrder.Descending Then
                            sortText = "  ▲"
                        End If
                    End If

                Next

                '結合するセルが画面中に無い場合
                If rect = Nothing Then
                    Continue For
                End If

                '結合する行がヘッダー行数より大きい場合
                Dim rowSapn As Integer = Me.HeaderCells(i).RowSpan
                If rowSapn > ColumnHeaderRowCount Then
                    rowSapn = ColumnHeaderRowCount
                End If

                '列ヘッダーの描画領域の底部の座標を保存
                Dim btm As Integer = rect.Bottom

                '結合するセルの描画領域のY座標
                Select Case MyBase.BorderStyle
                    Case Windows.Forms.BorderStyle.None
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row)
                    Case Windows.Forms.BorderStyle.FixedSingle
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row) + lineWidth
                    Case Windows.Forms.BorderStyle.Fixed3D
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row) + (lineWidth * 2)
                End Select

                '結合するセルの描画領域のX座標
                rect.X -= lineWidth

                '結合するセルの描画領域の高さ
                rect.Height = rowHeight * rowSapn

                '最下行の場合は描画領域の高さを調整する
                If Me.HeaderCells(i).Row + rowSapn = Me.ColumnHeaderRowCount Then
                    rect.Height = btm - rect.Y - lineWidth
                End If

                'グッリドの線
                Dim gridPen As New Pen(MyBase.GridColor)

                '背景色の取得
                Dim backgroundColor As System.Drawing.Color = MyBase.ColumnHeadersDefaultCellStyle.BackColor
                'セルの背景色が設定されている場合
                If Not Me.HeaderCells(i).BackgroundColor = Color.Empty Then
                    backgroundColor = Me.HeaderCells(i).BackgroundColor
                End If

                '背景色
                Dim backBrash As New SolidBrush(backgroundColor)

                'くぼみ線
                Dim whiteBrash As New SolidBrush(Color.White)

                Try

                    '枠線の描画
                    e.Graphics.DrawRectangle(gridPen, rect)


                    '結合セルの背景色の描画領域の設定
                    rect.Y += lineWidth
                    rect.X += lineWidth
                    rect.Height -= lineWidth
                    rect.Width -= lineWidth


                    '背景色の描画
                    If ColumnHeaderBorderStyle = HeaderCellBorderStyle.SingleLine Then
                        'Singleの場合
                        e.Graphics.FillRectangle(backBrash, rect)
                    Else
                        'くぼみ線の場合
                        e.Graphics.FillRectangle(whiteBrash, rect)
                        rect.Y += lineWidth
                        rect.X += lineWidth
                        rect.Height -= lineWidth
                        rect.Width -= lineWidth

                        e.Graphics.FillRectangle(backBrash, rect)
                    End If


                    'テキストの描画
                    Dim foreColor As System.Drawing.Color = MyBase.ColumnHeadersDefaultCellStyle.ForeColor
                    If Not Me.HeaderCells(i).ForeColor = Color.Empty Then
                        foreColor = Me.HeaderCells(i).ForeColor
                    End If

                    Dim formatFlg As TextFormatFlags = GetTextFormatFlags(Me.HeaderCells(i).TextAlign, Me.HeaderCells(i).WrapMode)

                    TextRenderer.DrawText(e.Graphics, Me.HeaderCells(i).Text & sortText, MyBase.ColumnHeadersDefaultCellStyle.Font, _
rect, foreColor, formatFlg)

                Finally
                    'リソースの解放
                    gridPen.Dispose()
                    backBrash.Dispose()
                    whiteBrash.Dispose()
                End Try
            Next

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' 指定のスタイルから描写するテキストのスタイルを取得する
    ''' </summary>
    ''' <param name="alignment">テキストのスタイル</param>
    ''' <param name="wrapMode">折り返</param>
    ''' <remarks>描写するテキストのスタイル</remarks>
    Private Function GetTextFormatFlags(ByVal alignment As DataGridViewContentAlignment,
ByVal wrapMode As DataGridViewTriState) As TextFormatFlags
        Try
            ''文字の描画
            Dim formatFlg As TextFormatFlags = TextFormatFlags.Right Or TextFormatFlags.VerticalCenter Or TextFormatFlags.EndEllipsis

            '表示位置
            Select Case alignment
                Case DataGridViewContentAlignment.BottomCenter
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.BottomLeft
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.BottomRight
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleCenter
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleLeft
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleRight
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopCenter
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopLeft
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopRight
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
            End Select


            '折り返し
            Select Case wrapMode
                Case DataGridViewTriState.False
                Case DataGridViewTriState.NotSet
                Case DataGridViewTriState.True
                    formatFlg = formatFlg Or TextFormatFlags.WordBreak
            End Select

            Return formatFlg

        Catch ex As Exception
            Throw
        End Try
    End Function

    ''' <summary>
    ''' セルを結合する対象の列の描画領域の無効化
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InvalidateUnitColumns()
        Try

            Dim hRect As Rectangle = MyBase.DisplayRectangle
            hRect.Height = MyBase.ColumnHeadersHeight + 1
            MyBase.Invalidate(hRect)

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' スクロールが実行されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnScroll(ByVal e As System.Windows.Forms.ScrollEventArgs)
        MyBase.OnScroll(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' サイズが変更されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnSizeChanged(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try

    End Sub

    ''' <summary>
    ''' 列の幅が変更されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnColumnWidthChanged(ByVal e As System.Windows.Forms.DataGridViewColumnEventArgs)
        MyBase.OnColumnWidthChanged(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' 行の境界線がダブルクリックされた時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnRowDividerDoubleClick(ByVal e As System.Windows.Forms.DataGridViewRowDividerDoubleClickEventArgs)
        MyBase.OnRowDividerDoubleClick(e)

        Try
            '行ヘッダーの境界線がダブルクリックされたへっだーの高さを整える
            If e.RowIndex = -1 Then
                MyBase.ColumnHeadersHeight = Me.ColumnHeaderRowCount * Me.ColumnHeaderRowHeight + 2
            End If
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' マウスのボタンが押された時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDown(e)

        Try
            '列幅、行高を調整するドラグ線を見えるようにするためにダブルバッファを解除する
            MyBase.DoubleBuffered = False
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' マウスのボタンが離された時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseUp(e)

        Try
            'OnMouseDownイベントで解除されたダブルバッファを適用する
            MyBase.DoubleBuffered = True
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;


namespace ClassLibrary1
{
    class CustomHeaderDataGridView : System.Windows.Forms.DataGridView
    {
        private MyCollection _item = null;

        /// 
        /// 列ヘッダに表示するCellを設定します
        /// 
        /// 
        /// 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示するCellを設定します")]
        public MyCollection HeaderCells
        {
            get { return _item; }
        }

        internal void OnCollectionChanged()
        {
            this.Invalidate();
        }

        /// 
        /// コレクションの設定
        /// 
        /// 
        public class MyCollection : System.Collections.ObjectModel.Collection<HeaderCell>
        {

            private CustomHeaderDataGridView _parent;

            internal MyCollection(CustomHeaderDataGridView parent)
            {
                _parent = parent;
            }

            protected override void ClearItems()
            {
                base.ClearItems();
                _parent.OnCollectionChanged();
            }

            protected override void InsertItem(int index, HeaderCell item)
            {
                base.InsertItem(index, item);
                _parent.OnCollectionChanged();
            }

            protected override void RemoveItem(int index)
            {
                base.RemoveItem(index);
                _parent.OnCollectionChanged();
            }

            protected override void SetItem(int index, HeaderCell item)
            {
                base.SetItem(index, item);
                _parent.OnCollectionChanged();
            }

        }

        private int _columnHeaderRowCount = 1;
        /// 
        /// 列ヘッダーの行数を設定します
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示する行を設定します")]
        public int ColumnHeaderRowCount
        {
            get { return _columnHeaderRowCount; }
            set
            {
                _columnHeaderRowCount = value;

                if (value == 0)
                {
                    _columnHeaderRowCount = 1;
                }

                base.ColumnHeadersHeight = value * ColumnHeaderRowHeight + 2;
                base.Refresh();
            }
        }

        private int _columnHeaderRowHeight = 17;
        // 
        /// 列ヘッダに表示する行の高さ
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示する行の高さを設定します")]
        public int ColumnHeaderRowHeight
        {
            get { return _columnHeaderRowHeight; }
            set
            {
                _columnHeaderRowHeight = value;

                base.ColumnHeadersHeight = value * ColumnHeaderRowCount + 2;
                base.Refresh();
            }
        }

        /// 
        /// 列ヘッダーの境界線の種類
        /// 
        /// 
        public enum HeaderCellBorderStyle
        {
            SingleLine = 0,
            DoubleLine = 1
        }

        private HeaderCellBorderStyle _columnHeaderBorderStyle = HeaderCellBorderStyle.SingleLine;
        /// 
        /// 列ヘッダーの線種
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに線種を設定します")]
        public HeaderCellBorderStyle ColumnHeaderBorderStyle
        {
            get { return _columnHeaderBorderStyle; }
            set
            {
                _columnHeaderBorderStyle = value;
                base.Refresh();
            }
        }

        [System.Diagnostics.DebuggerNonUserCode()]
        public CustomHeaderDataGridView()
            : base()
        {
            //この呼び出しは、コンポーネント デザイナーで必要です。
            InitializeComponent();

            this._item = new MyCollection(this);
            base.DoubleBuffered = true;

        }


        //Component は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
        [System.Diagnostics.DebuggerNonUserCode()]
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing && components != null)
                {
                    components.Dispose();
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }

        //コンポーネント デザイナーで必要です。
        private System.ComponentModel.IContainer components;

        //メモ: 以下のプロシージャはコンポーネント デザイナーで必要です。
        //コンポーネント デザイナーを使って変更できます。
        //コード エディターを使って変更しないでください。
        [System.Diagnostics.DebuggerStepThrough()]
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }





        /// 再描画をするとき
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            try
            {


                //---------------------------------------------------------------------------------------------------------
                //ヘッダーセルの描画
                //---------------------------------------------------------------------------------------------------------

                //ヘッダーの行の高さの取得
                int rowHeight = base.ColumnHeadersHeight;

                if (this.ColumnHeaderRowCount > 0)
                {
                    rowHeight = base.ColumnHeadersHeight / this.ColumnHeaderRowCount;
                }

                //線の太さ
                int lineWidth = 1;

                for (int i = 0; i <= ColumnCount - 1; i++)
                {

                    for (int j = 0; j <= this.ColumnHeaderRowCount - 1; j++)
                    {

                        //グッリドの線
                        Pen gridPen = new Pen(base.GridColor);

                        //背景色
                        SolidBrush backBrash = new SolidBrush(base.ColumnHeadersDefaultCellStyle.BackColor);

                        //くぼみ線
                        SolidBrush whiteBrash = new SolidBrush(Color.White);

                        try
                        {
                            //列ヘッダーの描画領域
                            Rectangle rect = base.GetCellDisplayRectangle(i, -1, true);

                            //列ヘッダーの描画領域の底部の座標を保存
                            int btm = rect.Bottom;

                            //セルの描画領域のY座標
                            switch (base.BorderStyle)
                            {
                                case BorderStyle.None:
 rect.Y = rowHeight * j;
 break;
                                case BorderStyle.FixedSingle:
 rect.Y = rowHeight * j + lineWidth;
 break;
                                case BorderStyle.Fixed3D:
 rect.Y = rowHeight * j + (lineWidth * 2);
 break;
                            }

                            //セルの描画領域のX座標
                            rect.X -= lineWidth;

                            //セルの描画領域の高さ
                            rect.Height = rowHeight;

                            //最下行の場合高さを調整
                            if (j == this.ColumnHeaderRowCount - 1)
                            {
                                rect.Height = btm - rect.Y - lineWidth;
                            }

                            //セルを囲む線の描画
                            e.Graphics.DrawRectangle(gridPen, rect);


                            //セルの背景色の領域
                            rect.Y += lineWidth;
                            rect.X += lineWidth;
                            rect.Height -= lineWidth;
                            rect.Width -= lineWidth;

                            //背景色の描画
                            if (ColumnHeaderBorderStyle != HeaderCellBorderStyle.DoubleLine)
                            {
                                //Single線の場合
                                e.Graphics.FillRectangle(backBrash, rect);
                            }
                            else
                            {
                                //くぼみ線の場合
                                //rect.Width -= lineWidth
                                e.Graphics.FillRectangle(whiteBrash, rect);
                                rect.Y += lineWidth;
                                rect.X += lineWidth;
                                rect.Height -= lineWidth;
                                rect.Width -= lineWidth;

                                e.Graphics.FillRectangle(backBrash, rect);
                            }

                            //見出しを最下列に表示
                            if (j == this.ColumnHeaderRowCount - 1)
                            {
                                string text = base.Columns[i].HeaderText;

                                if (base.SortedColumn != null && object.ReferenceEquals(base.SortedColumn, this.Columns[i]))
                                {
 if (base.SortOrder == SortOrder.Ascending)
 {
text = text + " ▼";
 }
 else if (base.SortOrder == SortOrder.Descending)
 {
text = text + " ▲";
 }
                                }

                                TextFormatFlags formatFlg = GetTextFormatFlags(base.ColumnHeadersDefaultCellStyle.Alignment, base.ColumnHeadersDefaultCellStyle.WrapMode);

                                TextRenderer.DrawText(e.Graphics, text, base.ColumnHeadersDefaultCellStyle.Font, rect, base.ColumnHeadersDefaultCellStyle.ForeColor, formatFlg);
                            }

                        }
                        finally
                        {
                            //リソースの解放
                            gridPen.Dispose();
                            backBrash.Dispose();
                            whiteBrash.Dispose();
                        }
                    }
                }

                //---------------------------------------------------------------------------------------------------------
                //ヘッダーのセル結合
                //---------------------------------------------------------------------------------------------------------
                //ヘッダーセル定義の処理
                for (int i = 0; i <= this.HeaderCells.Count - 1; i++)
                {

                    //セルの結合の開始行がヘッダーの行数より大きい場合は除外
                    if (HeaderCells[i].Row > this.ColumnHeaderRowCount - 1)
                    {
                        continue;
                    }

                    //セルの結合の開始列の列インデックスが列数より大きい場合は除外
                    if (HeaderCells[i].Column > base.ColumnCount - 1)
                    {
                        continue;
                    }

                    //描画領域の設定
                    Rectangle rect = Rectangle.Empty;

                    //結合する列中のソート状態
                    string sortText = string.Empty;

                    //結合するセルの各列の幅を取得し描画領域の幅を決める、ソートされている列の場合Textに表示するソート方向の設定
                    for (int j = this.HeaderCells[i].Column; j <= this.HeaderCells[i].Column + this.HeaderCells[i].ColumnSpan - 1; j++)
                    {

                        //列が画面に表示されていない場合は処理しない
                        if (base.Columns[j].Displayed == false)
                        {
                            continue;
                        }

                        //列ヘッダーの領域の幅
                        if (rect.IsEmpty)
                        {
                            //結合するセルの開始列の場合
                            rect = base.GetCellDisplayRectangle(j, -1, true);
                        }
                        else
                        {
                            //結合するセルの2列目以降の場合
                            rect.Width += base.GetCellDisplayRectangle(j, -1, true).Width;
                        }


                        //ソート列の場合
                        if (HeaderCells[i].SortVisible == true && base.SortedColumn != null && object.ReferenceEquals(base.SortedColumn, base.Columns[j]))
                        {
                            if (base.SortOrder == SortOrder.Ascending)
                            {
                                sortText = " ▼";
                            }
                            else if (base.SortOrder == SortOrder.Descending)
                            {
                                sortText = " ▲";
                            }
                        }

                    }

                    //結合するセルが画面中に無い場合
                    if (rect == null)
                    {
                        continue;
                    }

                    //結合する行がヘッダー行数より大きい場合
                    int rowSapn = this.HeaderCells[i].RowSpan;
                    if (rowSapn > ColumnHeaderRowCount)
                    {
                        rowSapn = ColumnHeaderRowCount;
                    }

                    //列ヘッダーの描画領域の底部の座標を保存
                    int btm = rect.Bottom;

                    //結合するセルの描画領域のY座標
                    switch (base.BorderStyle)
                    {
                        case BorderStyle.None:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row);
                            break;
                        case BorderStyle.FixedSingle:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row) + lineWidth;
                            break;
                        case BorderStyle.Fixed3D:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row) + (lineWidth * 2);
                            break;
                    }

                    //結合するセルの描画領域のX座標
                    rect.X -= lineWidth;

                    //結合するセルの描画領域の高さ
                    rect.Height = rowHeight * rowSapn;

                    //最下行の場合は描画領域の高さを調整する
                    if (this.HeaderCells[i].Row + rowSapn == this.ColumnHeaderRowCount)
                    {
                        rect.Height = btm - rect.Y - lineWidth;
                    }

                    //グッリドの線
                    Pen gridPen = new Pen(base.GridColor);

                    //背景色の取得
                    System.Drawing.Color backgroundColor = base.ColumnHeadersDefaultCellStyle.BackColor;
                    //セルの背景色が設定されている場合
                    if (!(this.HeaderCells[i].BackgroundColor == Color.Empty))
                    {
                        backgroundColor = this.HeaderCells[i].BackgroundColor;
                    }

                    //背景色
                    SolidBrush backBrash = new SolidBrush(backgroundColor);

                    //くぼみ線
                    SolidBrush whiteBrash = new SolidBrush(Color.White);

                    try
                    {

                        //枠線の描画
                        e.Graphics.DrawRectangle(gridPen, rect);


                        //結合セルの背景色の描画領域の設定
                        rect.Y += lineWidth;
                        rect.X += lineWidth;
                        rect.Height -= lineWidth;
                        rect.Width -= lineWidth;


                        //背景色の描画
                        if (ColumnHeaderBorderStyle == HeaderCellBorderStyle.SingleLine)
                        {
                            //Singleの場合
                            e.Graphics.FillRectangle(backBrash, rect);
                        }
                        else
                        {
                            //くぼみ線の場合
                            e.Graphics.FillRectangle(whiteBrash, rect);
                            rect.Y += lineWidth;
                            rect.X += lineWidth;
                            rect.Height -= lineWidth;
                            rect.Width -= lineWidth;

                            e.Graphics.FillRectangle(backBrash, rect);
                        }


                        //テキストの描画
                        System.Drawing.Color foreColor = base.ColumnHeadersDefaultCellStyle.ForeColor;
                        if (!(this.HeaderCells[i].ForeColor == Color.Empty))
                        {
                            foreColor = this.HeaderCells[i].ForeColor;
                        }

                        TextFormatFlags formatFlg = GetTextFormatFlags(this.HeaderCells[i].TextAlign, this.HeaderCells[i].WrapMode);

                        TextRenderer.DrawText(e.Graphics, this.HeaderCells[i].Text + sortText, base.ColumnHeadersDefaultCellStyle.Font, rect, foreColor, formatFlg);

                    }
                    finally
                    {
                        //リソースの解放
                        gridPen.Dispose();
                        backBrash.Dispose();
                        whiteBrash.Dispose();
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }


        /// <summary>
        /// 指定のスタイルから描写するテキストのスタイルを取得する
        /// </summary>
        /// <param name="alignment">テキストのスタイル</param>
        /// <param name="wrapMode">折り返</param>
        /// <remarks>描写するテキストのスタイル</remarks>
        private TextFormatFlags GetTextFormatFlags(DataGridViewContentAlignment alignment, DataGridViewTriState wrapMode)
        {
            try
            {
                //'文字の描画
                TextFormatFlags formatFlg = TextFormatFlags.Right | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis;

                //表示位置
                switch (alignment)
                {
                    case DataGridViewContentAlignment.BottomCenter:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.BottomLeft:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.BottomRight:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleCenter:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleLeft:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleRight:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopCenter:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopLeft:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopRight:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                }


                //折り返し
                switch (wrapMode)
                {
                    case DataGridViewTriState.False:
                        break;
                    case DataGridViewTriState.NotSet:
                        break;
                    case DataGridViewTriState.True:
                        formatFlg = formatFlg | TextFormatFlags.WordBreak;
                        break;
                }

                return formatFlg;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// セルを結合する対象の列の描画領域の無効化
        /// </summary>
        /// <remarks></remarks>
        private void InvalidateUnitColumns()
        {
            try
            {

                Rectangle hRect = base.DisplayRectangle;
                hRect.Height = base.ColumnHeadersHeight + 1;
                base.Invalidate(hRect);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// スクロールが実行されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnScroll(System.Windows.Forms.ScrollEventArgs e)
        {
            base.OnScroll(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// サイズが変更されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnSizeChanged(System.EventArgs e)
        {
            base.OnSizeChanged(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

        /// <summary>
        /// 列の幅が変更されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnColumnWidthChanged(System.Windows.Forms.DataGridViewColumnEventArgs e)
        {
            base.OnColumnWidthChanged(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 行の境界線がダブルクリックされた時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnRowDividerDoubleClick(System.Windows.Forms.DataGridViewRowDividerDoubleClickEventArgs e)
        {
            base.OnRowDividerDoubleClick(e);

            try
            {
                //行ヘッダーの境界線がダブルクリックされたへっだーの高さを整える
                if (e.RowIndex == -1)
                {
                    base.ColumnHeadersHeight = this.ColumnHeaderRowCount * this.ColumnHeaderRowHeight + 2;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// マウスのボタンが押された時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            base.OnMouseDown(e);

            try
            {
                //列幅、行高を調整するドラグ線を見えるようにするためにダブルバッファを解除する
                base.DoubleBuffered = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// マウスのボタンが離された時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            base.OnMouseUp(e);

            try
            {
                //OnMouseDownイベントで解除されたダブルバッファを適用する
                base.DoubleBuffered = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}

1 件のコメント:

  1. Hi, i have a question mind can send me the project file for me to Download? i really like to have the columns group header i try the code but i keep getting error can paste the download link here so anyone need this can download.
    Thank you.

    返信削除