Bonjour, j'essaie ce code dans mon formulaire utilisateur pour vérifier si les données saisies dans textbox1 sont un nombre et si ce n'est pas le cas, affichez un msgbox à l'utilisateur et sélectionnez le texte dans textbox1, mais le code ci-dessous ne le fait pas t sélectionnez du texte dans textbox1 lorsque Userform est vBModeless

Private Sub TextBox1_Change()
    If Not IsNumeric(TextBox1) Then
        MsgBox " only number"
        TextBox1.SetFocus
        TextBox1.SelStart = 0
        TextBox1.SelLength = Len(TextBox1.Text)
    End If
End Sub

Est une solution?

4
Avax 20 nov. 2018 à 15:24

3 réponses

Meilleure réponse

Dans ma version d'Excel, une msgbox est toujours vbModal, elle ne peut pas être vbModeless, vous ne pouvez définir que sa propriété de portée modale comme niveau application ou niveau système

  • Au niveau de l'application, il arrête l'application jusqu'à ce qu'elle reçoive une réponse
  • Au niveau du système, il suspend toutes les applications jusqu'à ce que l'utilisateur y réponde

Afin de faire ce que vous avez l'intention de faire; J'ai créé un UserForm sans mode et je l'utilise comme boîte de message

Le code devient

Private Sub TextBox1_Change()

    If Not IsNumeric(TextBox1) Then
        UserForm2.Label1 = "Only Number is Allowed"
        UserForm2.Show

        'At this point TextBox1 has lost focus,
        'to set the focus again you have to setfocus on something else
        'and then again set focus on textbox1 (a way to reinitialize it).
        'I have added a hidden textbox2 and will set focus on it

        TextBox2.Visible = True
        TextBox2.SetFocus
        TextBox2.Visible = False

        TextBox1.SetFocus
        TextBox1.SelStart = 0
        TextBox1.SelLength = Len(TextBox1.Text)

    End If

End Sub

enter image description here

La capture d'écran n'est qu'un test, vous pouvez faire le formatage etc. en fonction de votre application.

6
usmanhaq 26 nov. 2018 à 12:25

La racine du problème n'est pas une sélection, car elle est là et fonctionne comme prévu:

Private Sub TextBox1_Change()
    If Not IsNumeric(TextBox1) Then
        MsgBox " only number"
        TextBox1.SetFocus
        TextBox1.SelStart = 0
        TextBox1.SelLength = Len(TextBox1.Text)
        Debug.Print TextBox1.SelText
    End If
End Sub

Je pense que le problème fondamental ici est que les contrôles MSForms ne sont pas de vraies fenêtres, mais une entité "sans fenêtre" sans poignée de fenêtre (bien sûr, il y a des exceptions comme listbox, tabstrip, multipage), qui peuvent facilement être testées via une méthode cachée :

'Which obviously returns a zero.
Debug.Print TextBox1.[_GethWnd]

D'autre part, il y a le modèle de transmission de messages de Window où chaque contrôle est une fenêtre (d'où Windows OS) avec une poignée de fenêtre appropriée et avec la capacité d'envoyer et de recevoir des messages comme WM_SETFOCUS / WM_KILLFOCUS et d'agir de manière appropriée. Et revenons à MSForms - le UserForm gère en interne toute l'interaction entre le monde extérieur et les contrôles enfants.

Commençons par déclarer la fonction WIN API GetFocus :

Public Declare Function GetFocus Lib "user32.dll" () As Long

Et ajoutons quelques-uns des Debug.Print pour voir ce qui se passe:

Private Sub TextBox1_Change()
    If Not IsNumeric(TextBox1) Then
        Debug.Print "--"
        Debug.Print GetFocus
        MsgBox " only number"
        Debug.Print GetFocus
        TextBox1.SetFocus
        Debug.Print GetFocus
        Debug.Print "--"
        TextBox1.SelStart = 0
        TextBox1.SelLength = Len(TextBox1.Text)
    End If
End Sub

Ce qui donne cette séquence:

--
 <userform hwnd>
 <outer hwnd>
 <outer hwnd>
--

Comme vous pouvez le voir - le SetFocus n'a aucun effet, car le Userform n'a aucune idée que le focus est perdu (il n'y a donc pas non plus d'événement Exit). Pour surmonter ce problème, vous devez explicitement perdre votre focus en transférant le focus vers un autre contrôle enfant ou en changeant la propriété Enabled (ou même Visible):

Private Sub TextBox1_Change()
    If Not IsNumeric(TextBox1) Then
        Debug.Print "--"
        Debug.Print GetFocus
        TextBox1.Enabled = False
        'or use CommandButton1.SetFocus or something
        MsgBox " only number"
        TextBox1.Enabled = True
        Debug.Print GetFocus
        TextBox1.SetFocus
        Debug.Print GetFocus
        Debug.Print "--"
        TextBox1.SelStart = 0
        TextBox1.SelLength = Len(TextBox1.Text)
    End If
End Sub

Ce qui donne une apparence souhaitée et une séquence appropriée:

--
 <userform hwnd>
 <outer hwnd>
 <userform hwnd>
--

En conclusion, la cause est la désynchronisation des états de focalisation interne et externe, qui découle d'un modèle de gestion légèrement différent entre MSForms et WinForms / WinAPI plus un régime non modal de travail, qui mélange les deux, donnant une opportunité de perdre le focus sur quelque chose de non - MSForms.

7
CommonSense 27 nov. 2018 à 11:34

Je vote pour usmanhaq et CommonSense!

Juste quelque chose à ajouter: j'ai essayé d'implémenter des choses similaires sur l'un de mes projets, je finis par éviter de faire apparaître une autre fenêtre. Utilisez simplement une étiquette pour alerter.

Et après avoir mis en œuvre cela, je trouve cela plus convivial!

J'espère que cela t'aides!

Formulaire utilisateur:

Private Sub TextBox1_Change()
If Not IsNumeric(TextBox1.Value) Then
    Label1.Caption = "NUMBER ONLY!"
    UserForm1.TextBox1.SetFocus
    UserForm1.TextBox1.SelStart = FirstNonDigit(TextBox1.Value) - 1
    UserForm1.TextBox1.SelLength = Len(TextBox1.Text)
Else
     Label1.Caption = ""
End If
End Sub

enter image description here

Cette fonction est financée en ligne qui aiderait à mettre en évidence à partir du premier non numéro

Public Function FirstNonDigit(xStr As String) As Long
    Dim xChar As Integer
    Dim xPos As Integer
    Dim I As Integer
    Application.Volatile
    For I = 1 To Len(xStr)
        xChar = Asc(Mid(xStr, I, 1))
        If xChar <= 47 Or _
           xChar >= 58 Then
            xPos = I
            Exit For
        End If
    Next
    FirstNonDigit = xPos
End Function
1
li rachel 1 déc. 2018 à 03:26