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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です