2017年9月5日火曜日

DataGridViewの選択行を枠で表示する方法

大阪本社 M・Tです。

久々の開発ブログ投稿です。

最近、必要に駆られてVB.NetでDataGridViewの選択行を
枠で表示するということをしましたので紹介します。

通常、DataGridViewでは選択行は色が反転して表示されます。
こんな感じです。













それを以下のようになるようにします。













まあ座標計算して線を描画するだけなんですが
こういうサンプルはWebで探しても意外と少ないので
残しておこうかなと思いました。

イベントはCellPaintingとRowPostPaintです。

'CellPaintingイベント
Private Sub DataGridView1_CellPainting(sender As System.Object,
                                       e As DataGridViewCellPaintingEventArgs) _
Handles DataGridView1.CellPainting

    Dim dgv As DataGridView = CType(sender, DataGridView)

    '行選択時の背景色と前景色を変えない
    If e.RowIndex >= 0 Then
        dgv.Rows(e.RowIndex).DefaultCellStyle.SelectionBackColor
          = e.CellStyle.BackColor

        dgv.Rows(e.RowIndex).DefaultCellStyle.SelectionForeColor
          = e.CellStyle.ForeColor
    End If

End Sub

'RowPostPaintイベント
Private Sub DataGridView1_RowPostPaint(sender As System.Object,
                                       e As DataGridViewRowPostPaintEventArgs)_
Handles DataGridView1.RowPostPaint

    Dim dgv As DataGridView = CType(sender, DataGridView)

    If e.RowIndex = dgv.CurrentRow.Index Then
        '太さ2の黒い線
        Dim linePen As New Pen(Color.Black, 2)

        '座標計算

        '開始X 行ヘッダ表示の場合、行ヘッダ分右にずらす
        Dim startX As Integer = IIf(dgv.RowHeadersVisible,
                                                dgv.RowHeadersWidth,
                                                0)

        '開始Y 行のTOPより1ピクセル下
        '(1ピクセル下にしておかないと選択行を移動したとき
        ' 前に選択していた行の線の描画がきれいに消えない)
        Dim startY As Integer = e.RowBounds.Top + 1

        '終了X
        '開始X+表示される全列の幅-スクロールしないと見えない列の幅
        Dim endX As Integer = startX + _
        dgv.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - _
          dgv.HorizontalScrollingOffset

        '線を引く 上
        e.Graphics.DrawLine(linePen,
                                      startX,
                                      startY,
                                      endX,
                                      startY)


        '線を引く 左
        e.Graphics.DrawLine(linePen,
                                       startX,
                                       startY,
                                       startX,
                                       startY + e.RowBounds.Height - 1)

        '線を引く 右
        e.Graphics.DrawLine(linePen,
                                       endX,
                                       startY,
                                       endX,
                                       startY + e.RowBounds.Height - 1)

        '下罫線を引くため開始Yを再計算
        '(1ピクセル上にしておかないと選択行を移動したとき
        '  前に選択していた行の線の描画がきれいに消えない)
        startY = e.RowBounds.Top + e.RowBounds.Height - 1

        '線を引く 下
        e.Graphics.DrawLine(linePen,
                                      startX,
                                      startY,
                                      endX,
                                      startY)

    End If


End Sub


本日は以上です。ではまた。