ぐ~たら ぷろぐらまー にっき

最近すぐ忘れるけー。

DataGridViewでEnterキーが押された時に横のセルに移動したい

ちょっと苦手なDataGridViewのメモ

CellEnterイベントとかでEnterキーの時はTabキーを送るようにしていたんだけど
ReadOnlyのセルはとばしたかったり、最終行がReadOnlyだったらとか
制御が面倒になってきて、結局DataGridViewを継承したカスタムコントロールを作るのが一番手っ取り早かったので。

あちこち参考にさせていただき、今はこれに落ち着きました。
今回のバグはこれで何とかなりそう~。たぶん

*******

Enterキーでフォーカス横移動
ReadOnly=Trueのセルは飛ばす
最終列がReadOnlyの場合は次の行へ移動
最終行だった場合は最初の行に戻る

********

'///////////////////
' DataGridView
'///////////////////

''' <summary>
''' DataGridView
''' Enterキーが押された時に、Tabキーが押されたのと同じ動作をする
''' (現在のセルを隣のセルに移動する)
''' ReadOnlyのセルはとばす
''' </summary>
Public Class DataGridViewEx
    Inherits DataGridView

    Protected Overrides Function ProcessDialogKey(ByVal keyData As Keys) As Boolean

        If (keyData And Keys.KeyCode) = Keys.Tab OrElse (keyData And Keys.KeyCode) = Keys.Enter Then

            '現在のセルの次の列
            Dim col As Integer = Me.CurrentCell.ColumnIndex + 1

            While col < Me.Columns.Count

                If Not Me.Rows(Me.CurrentCell.RowIndex).Cells(col).ReadOnly And Me.Rows(Me.CurrentCell.RowIndex).Cells(col).Visible Then
                    Exit While
                End If
                col = col + 1
            End While

            If col < Me.Columns.Count Then
                Me.CurrentCell = Me.Rows(Me.CurrentCell.RowIndex).Cells(col)

            Else
                '行
                Dim row As Integer = Me.CurrentCell.RowIndex + 1
                Dim Flg As Boolean = False '無限ループ防止フラグ

                If row = Me.Rows.Count Then
                    '最終行の場合は最初の行に戻す
                    row = 0
                    Flg = True
                End If

                While row < Me.Rows.Count
                    For col = 0 To Me.Columns.Count - 1
                        If Not Me.Rows(row).Cells(col).ReadOnly And Me.Rows(row).Cells(col).Visible Then
                            Exit While
                        End If
                    Next

                    If row = Me.Rows.Count - 1 And Flg = False Then
                        '1回だけ最初の行に戻す
                        row = 0
                        Flg = True
                    Else
                        row = row + 1
                    End If
                End While


                If col < Me.Columns.Count Then
                    Me.CurrentCell = Me.Rows(row).Cells(col)
                End If

            End If

            Return True

        End If

        Return MyBase.ProcessDialogKey(keyData)
    End Function

    Protected Overrides Function ProcessDataGridViewKey(ByVal e As KeyEventArgs) As Boolean

        If e.KeyData = Keys.Tab OrElse e.KeyData = Keys.Enter Then

            Dim col As Integer = Me.CurrentCell.ColumnIndex + 1

            While col < Me.Columns.Count
                If Not Me.Rows(Me.CurrentCell.RowIndex).Cells(col).ReadOnly And Me.Rows(Me.CurrentCell.RowIndex).Cells(col).Visible Then
                    Exit While
                End If
                col = col + 1
            End While

            If col < Me.Columns.Count Then

                Me.CurrentCell = Me.Rows(Me.CurrentCell.RowIndex).Cells(col)
            Else

                '行
                Dim row As Integer = Me.CurrentCell.RowIndex + 1
                Dim Flg As Boolean = False '無限ループ防止フラグ

                If row = Me.Rows.Count Then
                    '最終行の場合は最初の行に戻す
                    row = 0
                    Flg = True
                End If

                While row < Me.Rows.Count

                    For col = 0 To Me.Columns.Count - 1
                        If Not Me.Rows(row).Cells(col).ReadOnly And Me.Rows(row).Cells(col).Visible Then
                            Exit While
                        End If
                    Next

                    If row = Me.Rows.Count - 1 And Flg = False Then
                        '1回だけ最初の行に戻す
                        row = 0
                        Flg = True
                    Else
                        row = row + 1
                    End If
                End While


                If col < Me.Columns.Count Then
                    Me.CurrentCell = Me.Rows(row).Cells(col)
                End If
            End If
            Return True

        End If

        Return MyBase.ProcessDataGridViewKey(e)
    End Function

End Class