Skip to content

Instantly share code, notes, and snippets.

@KOZ60
Last active May 24, 2024 00:17
Show Gist options
  • Save KOZ60/f8c24f4e19916e9aa95cdeed711b063c to your computer and use it in GitHub Desktop.
Save KOZ60/f8c24f4e19916e9aa95cdeed711b063c to your computer and use it in GitHub Desktop.
DataGridViewColumnHeaderCell

DataGridView のヘッダ列が他の行と文字の位置が違うので、DataGridViewTextBoxCell を参考にカスタマイズしました。

Public Class FitHeaderCell
	Inherits DataGridViewColumnHeaderCell

	Private Const DATAGRIDVIEWTEXTBOXCELL_ignoreNextMouseClick As Byte = 1
	Private Const DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetLeft As Byte = 3
	Private Const DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetRight As Byte = 4
	Private Const DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft As Byte = 0
	Private Const DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight As Byte = 0
	Private Const DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetTop As Byte = 2
	Private Const DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetBottom As Byte = 1
	Private Const DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping As Byte = 1
	Private Const DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping As Byte = 2
	Private Const DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom As Byte = 1

	Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle,
									cellBounds As Rectangle, rowIndex As Integer,
									dataGridViewElementState As DataGridViewElementStates,
									value As Object, formattedValue As Object, errorText As String,
									cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle,
									paintParts As DataGridViewPaintParts)
		Dim beforeParts = paintParts And (
								DataGridViewPaintParts.Border Or
								DataGridViewPaintParts.Background Or
								DataGridViewPaintParts.ContentBackground Or
								DataGridViewPaintParts.SelectionBackground)
		Dim afterParts = paintParts And DataGridViewPaintParts.ErrorIcon

		MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex,
					 dataGridViewElementState, value, formattedValue,
					 errorText, cellStyle, advancedBorderStyle, beforeParts)

		If paintParts.HasFlag(DataGridViewPaintParts.ContentForeground) Then
			Dim borderWidths As Rectangle = MyBase.BorderWidths(advancedBorderStyle)
			Dim valBounds As Rectangle = cellBounds
			valBounds.Offset(borderWidths.X, borderWidths.Y)
			valBounds.Width -= borderWidths.Right
			valBounds.Height -= borderWidths.Bottom

			If cellStyle.Padding <> Padding.Empty Then
				If DataGridView.RightToLeft = RightToLeft.Yes Then
					valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top)
				Else
					valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top)
				End If
				valBounds.Width -= cellStyle.Padding.Horizontal
				valBounds.Height -= cellStyle.Padding.Vertical
			End If

			Dim verticalTextMarginTop = If(cellStyle.WrapMode = DataGridViewTriState.True, DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping, DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping)
			valBounds.Offset(DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft, verticalTextMarginTop)
			valBounds.Width -= DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft + DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight
			valBounds.Height -= verticalTextMarginTop + DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom
			valBounds.Width -= 1 ' adjust
			If valBounds.Width > 0 AndAlso valBounds.Height > 0 Then
				Dim flags As TextFormatFlags = ComputeTextFormatFlagsForCellStyleAlignment(DataGridView.RightToLeft = RightToLeft.Yes, cellStyle.Alignment, cellStyle.WrapMode)
				If (flags And TextFormatFlags.SingleLine) <> 0 Then
					flags = flags Or TextFormatFlags.EndEllipsis
				End If
				Dim formattedValueStr As String = TryCast(formattedValue, String)
				TextRenderer.DrawText(graphics, formattedValueStr, cellStyle.Font, valBounds, cellStyle.ForeColor, flags)
			End If
		End If

		MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex,
					 dataGridViewElementState, value, formattedValue,
					 errorText, cellStyle, advancedBorderStyle, afterParts)
	End Sub

	Friend Shared Function ComputeTextFormatFlagsForCellStyleAlignment(rightToLeft As Boolean, alignment As DataGridViewContentAlignment, wrapMode As DataGridViewTriState) As TextFormatFlags
		Dim tff As TextFormatFlags
		Select Case alignment
			Case DataGridViewContentAlignment.TopLeft
				tff = TextFormatFlags.Top
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Right
				Else
					tff = tff Or TextFormatFlags.Left
				End If
			Case DataGridViewContentAlignment.TopCenter
				tff = TextFormatFlags.Top Or TextFormatFlags.HorizontalCenter
			Case DataGridViewContentAlignment.TopRight
				tff = TextFormatFlags.Top
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Left
				Else
					tff = tff Or TextFormatFlags.Right
				End If
			Case DataGridViewContentAlignment.MiddleLeft
				tff = TextFormatFlags.VerticalCenter
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Right
				Else
					tff = tff Or TextFormatFlags.Left
				End If
			Case DataGridViewContentAlignment.MiddleCenter
				tff = TextFormatFlags.VerticalCenter Or TextFormatFlags.HorizontalCenter
			Case DataGridViewContentAlignment.MiddleRight
				tff = TextFormatFlags.VerticalCenter
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Left
				Else
					tff = tff Or TextFormatFlags.Right
				End If
			Case DataGridViewContentAlignment.BottomLeft
				tff = TextFormatFlags.Bottom
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Right
				Else
					tff = tff Or TextFormatFlags.Left
				End If
			Case DataGridViewContentAlignment.BottomCenter
				tff = TextFormatFlags.Bottom Or TextFormatFlags.HorizontalCenter
			Case DataGridViewContentAlignment.BottomRight
				tff = TextFormatFlags.Bottom
				If rightToLeft Then
					tff = tff Or TextFormatFlags.Left
				Else
					tff = tff Or TextFormatFlags.Right
				End If
			Case Else
				tff = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter
		End Select
		If wrapMode = DataGridViewTriState.[False] Then
			tff = tff Or TextFormatFlags.SingleLine
		Else
			tff = tff Or TextFormatFlags.WordBreak
		End If
		tff = tff Or TextFormatFlags.NoPrefix
		tff = tff Or TextFormatFlags.PreserveGraphicsClipping
		If rightToLeft Then
			tff = tff Or TextFormatFlags.RightToLeft
		End If
		Return tff
	End Function

End Class

次のように使います。

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        With DataGridView1.Columns(0)
            .HeaderCell = New FitHeaderCell
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomLeft
            .HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomLeft
        End With
        With DataGridView1.Columns(1)
            .HeaderCell = New FitHeaderCell
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomRight
            .HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomRight
        End With
        With DataGridView1.Columns(2)
            .HeaderCell = New FitHeaderCell
            .DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter
            .HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter
        End With
    End Sub
End Class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment