TextBox.SelStart为鼠标和键盘提供不同的值

问题描述 投票:0回答:1

我在TextBox上有一个Form。我使用.SelStart中的TextBox属性获取光标位置。当我在TextBox中单击时,它可以按需要运行。然后我使用该位置通过按下打印其标题的同一表格上的按钮在光标位置上插入某些符号。

但是,如果我在TextBox中用键盘键入一些字符,则Selstart返回0.即使我键入了几个字符并且光标明显位于文本的末尾,SelStart仍为0.现在,如果我在其他表单上打印按钮,则新字符总是在TextBox的开头打印,这不是我想要的。即使我用键盘打字,我也希望字幕始终打印在光标位置。

这种行为非常令人费解。有人可以帮忙吗?

Private LastPosition as Long  'declared in form module


Private sub t_LostFocus()     'to obtain last position in `TextBox`
    LastPosition = Me!t.SelStart
End Sub


Private Sub Insert()

Dim Text As String

   If LastPosition = 0 AND IsNull(Me!t.value) Then
      Me!t.Value = " " + Me.ActiveControl.Caption
      LastPosition = LastPosition + Len(Me.ActiveControl.Caption) + 1

   ElseIf LastPosition >=0 AND Not IsNull(Me!t.Value) Then
      Text = Me!t.Value
      Me!t.Value = Left(Text, LastPosition) & " " & Me.ActiveControl.Caption & Mid (Text, LastPosition + 1)
      LastPosition = LastPosition + Len(Me.ActiveControl.Caption)+1

   Else
      Me!t.Value = Me!t.Value + " " + Me.ActiveControl.Caption

   End If

End Sub

Private Sub button1_Click()
   Call Insert
End Sub
vba ms-access access-vba
1个回答
1
投票

首先是关于访问表单上数据输入的一些事实。这些需要单独理解,以正确解释问题中描述的行为,特别是如果一个人试图改变控件的默认行为。

  • TextBox.SelStartSelLengthSelText仅在控件具有焦点时才可用且有效。当TextBox控件再次获得焦点时,默认选择所有文本,以便SelStart = 0和SelLength = Text属性的长度。当使用鼠标并在特定字符位置单击TextBox时,将绕过默认行为,并按预期将光标放在鼠标光标处。
  • TextBox控件具有Text属性和Value属性。 Text属性表示在控件中显示的文本字符串。显示的文本可以与控件表示的基础值不同,尤其是如果Value是非文本数据类型(例如,整数存储为数字,但表示为单独的文本数字)。 Value属性返回VBA变体,该变体本身保存特定数据类型的基础值。 对于绑定控件(即填充了ControlSource属性),Value数据类型将与绑定源列相同。 对于未绑定的控制(即ControlSource为空白),Value数据类型由TextBox.Format属性决定。如果Format为空,则数据类型为文本,并且将有效地匹配Text属性。 TextValue并不总是同步,当控件具有焦点并且正在编辑时尤其如此。当表单用户编辑文本时(即不是代码),Value不会更新,直到控件失去焦点或Shift + Enter保存表单(除非Enter键行为已被更改)。大多数将更新控件的事件还将涉及单击或以其他方式将焦点移动到控件之外,例如保存记录,将焦点更改为另一个控件等。 当控件的Value更新时,显示的文本 - 可通过Text属性访问 - 被解释和/或转换为适当的数据类型,然后保存到Value属性。 (有时通过将'Value'重新格式化为Format属性中指定的表示来继续同步。例如,如果Format = Long Date则:文本输入为“4-12-19” - >更新值:#4/12/19 00:00#→更新文字:“2019年4月12日星期五”。

在我谈到这一点之前的一个重要的最后事实:

  • 更新TextBox.Value属性时 - 即使它也是String数据类型 - 也会刷新Text属性并重置光标位置和文本选择,以便选择整个文本。换句话说,SelStart设置为0,SelLength设置为Text的长度,就像TextBox新接收焦点时观察到的行为(如上面第一点所述)。

最后到了所有这些细节的关键:

  • 当键盘用于改变文本时,这最终会触发更新,但通常直到控件失去焦点。但是当发生这样的更新时,它发生在LostFocus事件之前并且如上所述重置文本选择,因此在LostFocus事件处理程序中,SelStart == 0。
  • 问题实际上不是在键盘和鼠标之间,而是在被修改或未改变的控制文本之间。如果只在文本框中使用箭头键,则光标位置和文本选择将保留在LostFocus事件中,因为尚未发生控件更新。相反,如果使用鼠标来改变文本(例如右键单击粘贴),这也会触发更新,这将重置选择。实际上,如果以任何方式更改文本然后使用箭头键或鼠标单击,仍会发生更新并重置光标位置和文本选择。 如果焦点移动到文本框之外,然后使用鼠标返回,则可能发生了更新,但鼠标随后将设置光标位置。我只提到这一点,要注意可能不知道的杂散点击导致更新,并仍然给出鼠标有独特行为的错觉。
  • 对于踢,按Shift + Enter强制更新但保持对焦于控件,并观察所有文本是否自动选中。

通过在各种事件中放置一些“日志记录”语句来跟踪代码是值得的,这样您就可以观察它们何时发生以及顺序。


Option Explicit
Option Compare Database

Dim LastSelStart As Integer
Dim LastSelLength As Integer
Dim UpdateSelStart As Integer
Dim UpdateSelLength As Integer

Private Sub button1_Click()
    Insert
End Sub

Private Sub button2_Click()
    Insert
End Sub

Private Sub Form_Load()
    LastSelStart = -1
    LastSelLength = 0
    ResetUpdateSelValues
End Sub

Private Sub ResetUpdateSelValues()
    UpdateSelStart = -1
    UpdateSelLength = 0
End Sub

Private Sub t_AfterUpdate()
    On Error Resume Next
    UpdateSelStart = Me.t.SelStart
    UpdateSelLength = Me.t.SelLength
    If Err.Number <> 0 Then
        UpdateSelStart = -1
    End If
End Sub

Private Sub t_GotFocus()
    On Error Resume Next
    If LastSelStart >= 0 Then
        Me.t.SelStart = LastSelStart
        Me.t.SelLength = LastSelLength
    End If
End Sub

Private Sub t_LostFocus()
    LastSelStart = Me.t.SelStart
    LastSelLength = Me.t.SelLength

    If LastSelStart = 0 And UpdateSelStart > 0 Then
        LastSelStart = UpdateSelStart
        LastSelLength = UpdateSelLength
    End If

    ResetUpdateSelValues
End Sub

Private Sub Insert()
    Dim caption As String
    caption = Me.ActiveControl.caption

    If IsNull(Me.t.Value) Then
        Me.t.Value = caption
        LastSelStart = Len(caption)
        LastSelLength = 0
    Else
        Dim Text As String
        Text = Me.t.Value

        If LastSelStart = 0 Then
            '* Don't add extra space at beginning
            Text = caption & Mid(Text, LastSelLength + 1)
            'Text = caption & Text
            LastSelStart = Len(caption)
            LastSelLength = 0
        ElseIf LastSelStart > 0 Then
            Text = Left(Text, LastSelStart) & " " & caption & Mid(Text, LastSelStart + LastSelLength + 1)
            'Text = Left(Text, LastSelStart) & " " & caption & Mid(Text, LastSelStart + 0 + 1)
            LastSelStart = LastSelStart + 1 + Len(caption)
            LastSelLength = 0
        Else
            'If last cursor position is invalid, append characters
            Text = Text & " " & caption
            LastSelStart = Len(Text)
            LastSelLength = 0
        End If

        t.Value = Text
    End If

    Me.t.SetFocus
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.