Как выделить содержимое текстового поля после его активации?

у меня есть эта простая пользовательская форма, где у меня есть только TextBox1 и TextBox2. Я ввожу текст в них обоих. Предположим, что фокус находится на (курсор находится в)TextBox2. Когда я нажимаю на TextBox1, Я хочу, чтобы весь текст в этом элементе должен быть выделен (выбран). Таким образом я использую этот код:

Private Sub TextBox1_Enter()
    With TextBox1
        .SetFocus
        .SelStart = 0
        .SelLength = Len(.Text)
    End With
    MsgBox "enter event was fired"
End Sub

есть MsgBox в конце, который загружен, это означает, что событие работает. Однако текст не выделен. Как это исправить?

я использую Enter событие и не хочу использовать MouseDown событие, потому что мне нужен код, чтобы работать, когда TextBox1 активируется программно, поэтому я чувствую Enter событие, чтобы быть лучшим выбором, так как он уволен в обоих случаях! Еще один недостаток MouseDown событие: когда я нажимаю второй раз на TextBox1, Я бы не ожидал, что весь текст будет выделен больше, потому что фокус был установлен на первом щелчке, и он не был изменен после того, как я нажал на тот же элемент управления во второй раз; так что в этом случае Я хотел бы, чтобы курсор действовал нормально (не держать текст помеченным).

обновление
Когда я нажимаю один раз на TextBox1, Я ожидаю получить этот результат: enter image description here
при повторном нажатии подсветка будет удалена, и курсор будет помещен в то место, где он был нажат.

8 ответов


не может быть проще, чем это, я думаю...

Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)
    With TextBox1
        .SelStart = 0
        .SelLength = Len(.Text)
    End With
End Sub

если вы нажмете на текстовое поле или вкладку в него, он будет делать то, что вы хотите. Чтобы отменить выбор текста, используйте клавиши со стрелками.

объяснение

если вы отлаживаете код, вы увидите, что хотя вы сказали .SetFocus фокус не на поле. .SetFocus не работает TextBox1_Enter() и вам нужно сосредоточиться на остальной части кода для работы. И, следовательно, моего альтернатива...

альтернатива

вам также может понравиться эта версия :) это преодолевает ограничение использования мыши в текстовом поле

Dim boolEnter As Boolean

Private Sub TextBox1_Enter()
    boolEnter = True
End Sub

Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)
    If boolEnter = True Then
        With TextBox1
            .SelStart = 0
            .SelLength = Len(.Text)
        End With
        boolEnter = False
    End If
End Sub

Pff, заняло у меня некоторое время. На самом деле ваш код работает, но он выделяет текст до того, как произойдет событие click. Таким образом, щелчок в поле мгновенно переопределяет выбор, созданный кодом. Я использовал отложенный выбор, и он работает, хотя это немного мерзко...

код для текстовых полей:

Private Sub TextBox1_Enter()
  Application.OnTime Now + TimeValue("00:00:01"), "module1.SelectText1"
End Sub

Private Sub TextBox2_Enter()
  Application.OnTime Now, "module1.SelectText2"
End Sub

обратите внимание, что он работает даже с {+TimeValue("00:00:01")} частично, но теоретически это может помешать ему работать время от времени. Хмм, на секунду подумал, просто оставь это. Сомневаюсь, что это когда-нибудь вызовет проблемы.

теперь код в module1:

Sub SelectText1()
  UserForm1.TextBox1.SelStart = 0
  UserForm1.TextBox1.SelLength = Len(UserForm1.TextBox1.Text)
End Sub

Sub SelectText2()
  UserForm1.TextBox2.SelStart = 0
  UserForm1.TextBox2.SelLength = Len(UserForm1.TextBox2.Text)
End Sub

надеюсь, это сработает и для вас. Проблема инерции. :) Ура!


мне не удалось выбрать / выделить текст в событии Enter, поскольку события mousedown и mouseup, наступающие после, несколько сбрасывают выделение.

Я думаю, что самый правильный способ достижения того, что вы хотите это :

' if you want to allow highlight more then once, reset the  variable LastEntered prior to call SelectTboxText:
'       LastEntered = ""
'       SelectTboxText TextBox2


Dim LastEntered As String


' Button to select Textbox1
Private Sub CommandButton1_Click()
    SelectTboxText TextBox1
End Sub

' Button to select Textbox2
Private Sub CommandButton2_Click()
    SelectTboxText TextBox2
End Sub

Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    SelectTboxText TextBox1
End Sub


Private Sub TextBox2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
     SelectTboxText TextBox2
End Sub


Public Sub SelectTboxText(ByRef tBox As MSForms.TextBox)

    If LastEntered <> tBox.Name Then

        LastEntered = tBox.Name

        With tBox
            .SetFocus
            .SelStart = 0
            .SelLength = Len(.Text)
        End With

    End If

End Sub

поэтому каждый раз, когда вы хотите активировать один из текстовых полей программно, вы должны вызвать sub SelectTboxText, что на самом деле не раздражает IMO. Я сделал 2 кнопки для этого в качестве примера.


это несколько улучшение того, что @vacip опубликовал. Преимущество заключается в том, что вам не нужно добавлять отдельный метод в модуль для каждого нового текстового поля.

следующий код в форму:

'===== User Form Code ========

Option Explicit

Private Sub TextBox1_Enter()
    OnTextBoxEnter
End Sub

Private Sub TextBox2_Enter()
   OnTextBoxEnter
End Sub

Private Sub TextBox3_Enter()
   OnTextBoxEnter
End Sub

следующий код в модуле:

'===== Module Code ========

Sub SelectAllText()
    SendKeys "{HOME}+{END}", True
End Sub

Sub OnTextBoxEnter()
   Application.OnTime Now + 0.00001, "SelectAllText", Now + 0.00002
End Sub

Я знаю, что это устарело, но я оставляю это здесь, вдруг это поможет кому-то в моем положении.

чего я хочу, так это:

  • если я нажму на поле в первый раз: выберите весь текст
  • если я нажму на него в следующий раз: поместите курсор туда, где находится мышь, и позвольте мне использовать мышь, чтобы выбрать подстроку

во-первых, важно знать, что "выделить весь текст" - это поведение по умолчанию при закладке в текстовое поле и что "поместить курсор здесь" является поведением по умолчанию при нажатии на текстовое поле, поэтому нам нужно только беспокоиться о том, что делает мышь.

для этого мы можем отслеживать активный элемент управления, но только во время перемещения мыши над нашим текстовым полем (т. е. перед щелчком)

код:

Private m_ActiveControlName As String

Private Sub Text1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    m_ActiveControlName = Me.ActiveControl.Name
End Sub

Private Sub Text1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If m_ActiveControlName <> Me.Text1.Name Then
        Call Text1_Enter   'we don't have to use Text1_Enter for this, any method will do
        Exit Sub           'quit here so that VBA doesn't finish doing its default Click behaviour
    End If
End Sub

Private Sub Text1_Enter()
    With Text1
        .SelStart = 0
        .SelLength = Len(.Text)
    End With
End Sub

использовать

Private Sub TextBox1_Enter()
    With TextBox2
        .ForeColor = vbBlack
        .Font.Bold = False
    End With
    With TextBox1
        .ForeColor = vbRed
        .Font.Bold = True
    End With
End Sub

Private Sub TextBox2_Enter()
    With TextBox1
        .ForeColor = vbBlack
        .Font.Bold = False
    End With
    With TextBox2
        .ForeColor = vbRed
        .Font.Bold = True
    End With
End Sub

поведение, которое вы пытаетесь реализовать, уже встроено в TextBox. При перемещении мыши по левой стороне текстового поля указатель мыши будет указывать вправо. Если щелкнуть, то будет выделен весь текст в поле. Щелчок в другом месте отменит выбор текста.

Я попробую несколько других стратегий, чтобы увидеть, могу ли я заставить это работать в одном суб.


попробуйте тот же код с TextBox1_MouseDown. Это должно сработать.

Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    With TextBox1
        .SetFocus
        .SelStart = 0
        .SelLength = Len(.Text)
    End With
    MsgBox "Text in TextBox1 is selected"
End Sub