以编程方式扫描表单上的控件。
注意那些有 TabStop=True 的。
将它们放入按 TabIndex 排序的列表中。
清除所有控件的 TabStop=True 属性。
打开表单的 KeyPreview 选项。
捕获表单的 _KeyDown 事件。
如果键是 Tab 键,则通过控制列表单步查找下一个或上一个并设置焦点。
如果焦点位于网格上,您可以选择向前或向后移动选定的行/列。
我在石器时代写了这门课。可耻的丑陋代码,但它有效。
具有多个控件和网格的表单:
Private WithEvents TabStop As cTabStop
Private Sub Form_Load()
Me.MSFlexGrid1.Rows = 3
Me.MSFlexGrid1.Cols = 3
Me.MSFlexGrid1.FixedRows = 0
Me.MSFlexGrid1.FixedCols = 0
Set TabStop = New cTabStop
TabStop.Setup Me
End Sub
Private Sub TabStop_TabPressed(ByVal Shift As Integer, Cancel As Integer)
If Me.ActiveControl.Name = Me.MSFlexGrid1.Name Then
If Shift = 0 Then
If Me.MSFlexGrid1.Col < Me.MSFlexGrid1.Cols - 1 Then
Me.MSFlexGrid1.Col = Me.MSFlexGrid1.Col + 1
Cancel = 1
ElseIf Me.MSFlexGrid1.Row < Me.MSFlexGrid1.Rows - 1 Then
Me.MSFlexGrid1.Col = 0
Me.MSFlexGrid1.Row = Me.MSFlexGrid1.Row + 1
Cancel = 1
End If
Else
If Me.MSFlexGrid1.Col > 0 Then
Me.MSFlexGrid1.Col = Me.MSFlexGrid1.Col - 1
Cancel = 1
ElseIf Me.MSFlexGrid1.Row > 0 Then
Me.MSFlexGrid1.Col = Me.MSFlexGrid1.Cols - 1
Me.MSFlexGrid1.Row = Me.MSFlexGrid1.Row - 1
Cancel = 1
End If
End If
End If
End Sub
班级:
Option Explicit
' ------------------------------------------------------------------------------
' This class ATTEMPTS to manage Tab Keypress events
' The specific advantage is the ability capture and cancel a Tab Keypress
'
' This is a horribly inelegant way to get the job done
'
' Bug:
' If a control should be next to receive focus, but is sitting on a control
' which is hidden, the tab order will not be able to proceed past that control.
' i.e. Command1 on Frame1 where Frame1.Visible = False
' ------------------------------------------------------------------------------
Private Type typeControl
Control As Control
TabIndex As Long
End Type
Private Type typeSettings
Controls() As typeControl
ControlCount As Long
End Type
Public Event TabPressed(ByVal Shift As Integer, ByRef Cancel As Integer)
Private Settings As typeSettings
Private WithEvents Form As Form
Public Sub Setup(Form_ As Form)
Call FunctionTagger("cTabStop", "Setup")
On Error GoTo E
Dim Control As Control
' Get the Form and enable its KeyPreview ability
Set Form = Form_
Form.KeyPreview = True
' Get the Tab-Able controls from the form
Settings.ControlCount = 0
ReDim Settings.Controls(0 To 0)
For Each Control In Form.Controls
Call AddControl(Control)
Next Control
Exit Sub
E:
Debug.Print " " & Err.Description
End Sub
Public Sub Clear()
Call FunctionTagger("cTabStop", "Clear")
Set Form = Nothing
Settings.ControlCount = 0
ReDim Settings.Controls(0 To 0)
End Sub
Private Sub AddControl(ByRef Control As Control)
Call FunctionTagger("cTabStop", "AddControl")
On Error GoTo E
Dim TabIndex As Long
Dim TabStop As Boolean
Dim Visible As Boolean
Dim Enabled As Boolean
' Only accept controls with these four properties
TabStop = Control.TabStop
TabIndex = Control.TabIndex
Visible = Control.Visible
Enabled = Control.Enabled
' Diable the control's TabStop property
Control.TabStop = False
' Add the control to our list
Settings.ControlCount = Settings.ControlCount + 1
ReDim Preserve Settings.Controls(0 To Settings.ControlCount - 1)
Set Settings.Controls(Settings.ControlCount - 1).Control = Control
Settings.Controls(Settings.ControlCount - 1).TabIndex = TabIndex
Exit Sub
E:
End Sub
Private Sub Class_Initialize()
Call FunctionTagger("cTabStop", "Class_Initialize")
Clear
End Sub
Private Sub Class_Terminate()
Call FunctionTagger("cTabStop", "Class_Terminate")
Clear
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Call FunctionTagger("cTabStop", "Form_KeyDown")
Dim Cancel As Integer
If KeyCode = 9 Then
KeyCode = 0
RaiseEvent TabPressed(Shift, Cancel)
Debug.Print " Tab Pressed"
If Cancel <> 0 Then ' Tab Keypress Cancelled...
KeyCode = 0
ElseIf Shift = 0 Then ' Tab Pressed...
TabRight
ElseIf Shift = 1 Then ' Shift-Tab Pressed...
TabLeft
End If
End If
End Sub
Public Sub TabLeft()
Call FunctionTagger("cTabStop", "TabLeft")
On Error GoTo E
Dim CurTabIndex As Long
Dim NextControl As Long
Dim NextTabIndex As Long
Dim c As Long
' Get the Tab Index of the currently active control
If Not Form.ActiveControl Is Nothing Then ' 2012-09-25 - Jaron
CurTabIndex = Form.ActiveControl.TabIndex
End If
' Find the control with the next smallest Tab Index
NextControl = -1
NextTabIndex = -1
For c = 0 To Settings.ControlCount - 1
' With Settings.Controls(c) ' 2007-05-07
If Settings.Controls(c).TabIndex >= NextTabIndex And Settings.Controls(c).TabIndex < CurTabIndex Then
If Settings.Controls(c).Control.Visible And Settings.Controls(c).Control.Enabled Then
NextControl = c
NextTabIndex = Settings.Controls(c).TabIndex
End If
End If
' End With
Next c
' Set focus to the next control
If NextControl >= 0 Then
' With Settings.Controls(NextControl).Control ' 2007-05-07
'Debug.Print " Set Focus to " & Settings.Controls(NextControl).Control.Name
SetFocusSafe Settings.Controls(NextControl).Control ' 2007-06-05
DoEvents
' End With
End If
Exit Sub
E:
Debug.Print " " & Err.Description
End Sub
Public Sub TabRight()
Call FunctionTagger("cTabStop", "TabRight")
On Error GoTo E
Dim CurTabIndex As Long
Dim NextControl As Long
Dim NextTabIndex As Long
Dim c As Long
' Get the Tab Index of the currently active control
If Not Form.ActiveControl Is Nothing Then ' 2012-09-25 - Jaron
CurTabIndex = Form.ActiveControl.TabIndex
End If
' Find the control with the next largest Tab Index
NextControl = -1
NextTabIndex = 999999999
For c = 0 To Settings.ControlCount - 1
' With Settings.Controls(c) ' 2007-05-07
If Settings.Controls(c).TabIndex <= NextTabIndex And Settings.Controls(c).TabIndex > CurTabIndex Then
If Settings.Controls(c).Control.Visible And Settings.Controls(c).Control.Enabled Then
NextControl = c
NextTabIndex = Settings.Controls(c).TabIndex
End If
End If
' End With
Next c
' Set focus to the next control
If NextControl >= 0 Then
' With Settings.Controls(NextControl).Control ' 2007-05-07
'Debug.Print " Set Focus to " & Settings.Controls(NextControl).Control.Name
SetFocusSafe Settings.Controls(NextControl).Control ' 2007-06-05
DoEvents
' End With
End If
Exit Sub
E:
Debug.Print " " & Err.Description
End Sub
' ------------------------------------------------------------------------------
Private Sub SetFocusSafe(ByRef Control As Control)
On Error GoTo E
Control.SetFocus
Exit Sub
E:
End Sub
Private Sub FunctionTagger(ByVal sModule As String, ByVal sFunction As String)
Debug.Print " " & Time$ & " " & sModule & "." & sFunction
End Sub
' ------------------------------------------------------------------------------
' ------------------------------------------------------------------------------