DataGridViewのカーソル制御

ええと、VB2010のDataGridViewで矢印キーとかEnterキーとかTabキーでカーソル移動をさせたいなーと思って苦戦したのでメモ。
非表示や入力不可のセルを飛ばして移動します。端のセルの場合は前の行または次の行に移動します。
Shift+TabはTabと逆に移動します。

※Form内に以下を記述して、そのFormのDataGridViewのテキストの列にはmyDataGridViewTextBoxColumnを使用します。


Friend Class myDataGridViewTextBoxColumn
Inherits DataGridViewTextBoxColumn

Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell
Get
Return New myDataGridViewTextBoxCell
End Get
Set(ByVal value As System.Windows.Forms.DataGridViewCell)
MyBase.CellTemplate = value
End Set
End Property

End Class

Friend Class myDataGridViewTextBoxCell
Inherits DataGridViewTextBoxCell

Public Overrides ReadOnly Property EditType() As System.Type
Get
Return GetType(myDataGridViewTextBoxEditingControl)
End Get
End Property

End Class

Friend Class myDataGridViewTextBoxEditingControl
Inherits DataGridViewTextBoxEditingControl

Private Enum MoveTo
None = 0
PrevCell = -1
NextCell = 1
End Enum

Protected Overrides Sub OnPreviewKeyDown(e As PreviewKeyDownEventArgs)

Select Case e.KeyCode
Case Keys.Enter, Keys.Tab
' EnterキーとTabキーをEditingControlWantsInputKey()で拾えるようにする
e.IsInputKey = True

Case Else
Call MyBase.OnPreviewKeyDown(e)

End Select

End Sub

Public Overrides Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean

Select Case keyData
Case Keys.Left, Keys.Right, Keys.Enter, Keys.Tab, (Keys.Shift Or Keys.Tab)
' カーソル移動キーの押下時処理(左右・Enter・Tab)
Dim intMove As MoveTo = MoveTo.None
Dim blnWk As Boolean = False
Select Case keyData
Case Keys.Enter, Keys.Tab
intMove = MoveTo.NextCell

Case (Keys.Shift Or Keys.Tab)
intMove = MoveTo.PrevCell

Case Keys.Left
If Me.SelectionStart = 0 Then blnWk = True
If Me.SelectionLength = Me.Text.Length Then blnWk = True
If blnWk = True Then
intMove = MoveTo.PrevCell
End If

Case Keys.Right
If Me.SelectionStart = Me.Text.Length Then blnWk = True
If Me.SelectionLength = Me.Text.Length Then blnWk = True
If blnWk = True Then
intMove = MoveTo.NextCell
End If
End Select
If intMove <> MoveTo.None Then
Dim grid As DataGridView = Me.EditingControlDataGridView
Call Me.SetFocusNextCell(grid, intMove)
End If
Return True

Case Else
Return MyBase.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey)

End Select

End Function

Private Sub SetFocusNextCell(ByVal grid As DataGridView, ByVal intMove As MoveTo)

With grid
Dim col As Integer = .CurrentCellAddress.X
Dim row As Integer = .CurrentCellAddress.Y
Dim r As Integer = row
Dim c As Integer
Dim blnWk As Boolean
Dim nextRow As Integer = -1
Dim nextCol As Integer = -1
Dim sc As Integer
Dim maxrow As Integer
Dim ccnt As Integer = .ColumnCount
Dim rcnt As Integer = .RowCount
' 直近の有効なセルにカーソルを移動させる
Select Case intMove
Case MoveTo.PrevCell
maxrow = row - 1
If maxrow < 0 Then maxrow = row
For r = row To maxrow Step -1
sc = col - 1
If r < row Then sc = ccnt - 1
For c = sc To 0 Step -1
blnWk = True

' 適当にチェック(VisibleとかReadOnlyとか)

If blnWk = True Then
nextRow = r
nextCol = c
Exit For
End If
Next c
If nextRow >= 0 Then Exit For
Next r

Case MoveTo.NextCell
maxrow = row + 1
If maxrow >= rcnt Then maxrow = row
For r = row To maxrow
sc = col + 1
If r > row Then sc = 0
For c = sc To ccnt - 1
blnWk = True

' 適当にチェック(VisibleとかReadOnlyとか)

If blnWk = True Then
nextRow = r
nextCol = c
Exit For
End If
Next c
If nextRow >= 0 Then Exit For
Next r
End Select
If nextRow >= 0 And nextCol >= 0 Then
.CurrentCell = .Rows(nextRow).Cells(nextCol)
End If
End With
End Sub

End Class

この辺を参考にさしてもらいました。多謝。
http://dobon.net/vb/bbs/log3-42/25144.html
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=41202&forum=7
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=47305&forum=7
http://social.msdn.microsoft.com/Forums/ja/vbexpressja/thread/fc1a0d8d-23d1-4a4e-a88c-f9a1edd81cff
http://social.msdn.microsoft.com/Forums/ja-JP/csharpgeneralja/thread/234162d6-b3a6-4839-80b1-06641216f458