Classe de TextBox et événements Exit et Enter

pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 23 mars 2016 à 15:30 - Dernière réponse :  Nono
- 3 mars 2018 à 19:22
Bonjour,

Suite à cette discussion, et, plus particulièrement, ce code d'ucfoutu, je me suis dit qu'il serait agréable de créer un objet personnalisé "TextBox_Date".
Souhaitant donc créer une classe de textbox, et afin de contrôler leur saisie, j'ai bien évidemment songé utiliser les événement KeyDown et Exit des TextBox comme le fait ucfoutu dans son code.
Or l'événement Exit, comme plusieurs autres, n'est pas disponible dans une classe.
Après quelques recherches infructueuses à ce sujet, je suis tombé (plutôt par hasard d'ailleurs) sur la solution à ce problème Source.
Je me dis deux choses :
1- Comme c'est une méthode pas trop connue, il faudrait (sans doute) en faire un Snippet pour la faire connaître,
2- Pour en faire un Snippet, il faudrait la tester dans tous les cas et dans tous ses "retranchements".

C'est là ou je ne me sens pas de le faire seul.

Voici, pour commencer, mon fichier de travail

J'ai déjà identifié quelques soucis liés notamment à "l'encapsulation" de textbox dans un Frame ou un Multipage.
C'est solutionné, dans le fichier joint, par l'ajout de ces types de contrôles dans la classe.
Mais quelque chose d'autre a pu m'échapper, ou la méthode de "contournement" utilisée n'est peut être pas la meilleure.
C'est le but de mon sujet...

Pour celles et ceux qui ne souhaitent pas télécharger le fichier, je vais, dans une réponse, donner les codes et la manière de les intégrer à un fichier.

Merci d'avance de vos contributions
Afficher la suite 

Votre réponse

14 réponses

pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - Modifié par pijaku le 23/03/2016 à 15:54
0
Merci
Bon, les codes.

L'UserForm (UserForm1):
> dessiner un UserForm avec plusieurs contrôles
> notamment, au minimum 11 TextBox (de TextBox1 à TextBox11 etc)
==> répartir ces textbox au sein de l'userform et dans des contrôles "containers" (Multipage, Frame, etc) (perso j'ay ai mis un MultiPage (MultiPage1) et un Frmae (Frame1) (cf code))
> dessiner également, dans l'userform, une ListBox (ListBox1) (assez grande)

Le code de l'UserForm :
Option Explicit

    Private mesTxtB(1 To 7) As cTextBox_Date

    Private Sub UserForm_Initialize()
    Dim i As Integer
    Dim List_TextBoxDate

        List_TextBoxDate = Array("TextBox2", "TextBox5", "TextBox7", "TextBox9", "TextBox11")
        For i = 1 To 5
            Set mesTxtB(i) = New cTextBox_Date
            mesTxtB(i).Item = Me.Controls(List_TextBoxDate(i - 1))
            mesTxtB(i).Index = i
        Next i
        Set mesTxtB(6) = New cTextBox_Date
        mesTxtB(6).Item = Me.Controls("MultiPage1")
        mesTxtB(6).Index = 6
        Set mesTxtB(7) = New cTextBox_Date
        mesTxtB(7).Item = Me.Controls("Frame1")
        mesTxtB(7).Index = 7
        
        TextBox1.SetFocus
    End Sub

    Private Sub UserForm_Terminate()
    Dim i As Integer
        For i = 1 To 7
            mesTxtB(i).Clear
        Next i
        Erase mesTxtB
    End Sub


Pour la classe, c'est un peu plus complexe...
Tout d'abord, insérez un module de classe, nommez le cTextBox_Date

Collez y ce code :
Option Explicit
'Source : http://www.h3.dion.ne.jp/~sakatsu/Breakthrough_P-Ctrl_Arrays_Eng_ref.htm#C2CP

    Private Type GUID
         Data1 As Long
         Data2 As Integer
         Data3 As Integer
         Data4(0 To 7) As Byte
    End Type
     
    #If VBA7 And Win64 Then
         Private Declare PtrSafe Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" _
                 (ByVal punk As stdole.IUnknown, _
                 ByRef riidEvent As GUID, _
                 ByVal fConnect As Long, _
                 ByVal punkTarget As stdole.IUnknown, _
                 ByRef pdwCookie As Long, _
                 Optional ByVal ppcpOut As LongPtr) As Long
    #Else
        Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" _
                 (ByVal punk As stdole.IUnknown, _
                 ByRef riidEvent As GUID, _
                 ByVal fConnect As Long, _
                 ByVal punkTarget As stdole.IUnknown, _
                 ByRef pdwCookie As Long, _
                 Optional ByVal ppcpOut As Long) As Long
    #End If
     
    Private Cookie As Long
    Private MyCtrl As Object
    Private MyIndex As Integer
     
    Private Sub ConnectEvent(ByVal Connect As Boolean)
    Dim IID_IDispatch As GUID
     
        With IID_IDispatch
            .Data1 = &H20400
            .Data4(0) = &HC0
            .Data4(7) = &H46
        End With
        ConnectToConnectionPoint Me, IID_IDispatch, Connect, MyCtrl, Cookie, 0&
    End Sub
     
    Public Property Let Index(NewIndex As Integer)
        MyIndex = NewIndex
    End Property
     
    Public Property Let Item(NewCtrl As Object)
        Set MyCtrl = NewCtrl
        Call ConnectEvent(True)
    End Property
     
    Public Sub Clear()
        If Cookie <> 0 Then Call ConnectEvent(False)
        Set MyCtrl = Nothing
    End Sub
     
    Public Sub Entrer()
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Enter]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Enter] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub Sortie(ByVal Cancel As MsForms.ReturnBoolean)
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Exit]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Exit] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub AvantUpdate(ByVal Cancel As MsForms.ReturnBoolean)
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [BeforeUpdate]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [BeforeUpdate] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub ApresUpdate()
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [AfterUpdate]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [AfterUpdate] Value=" & MyCtrl.Value
    End Sub


Exportez ce module de classe, puis éditez le à l'aide du Bloc notes (par exemple).
Changez les 4 Public Sub Entrer, Sortie, AvantUpdate et ApresUpdate par celles-ci (ajout des Attribute):
    Public Sub Entrer()
 Attribute Entrer.VB_UserMemId = -2147384830
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Enter]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Enter] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub Sortie(ByVal Cancel As MsForms.ReturnBoolean)
 Attribute Sortie.VB_UserMemId = -2147384829
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Exit]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [Exit] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub AvantUpdate(ByVal Cancel As MsForms.ReturnBoolean)
 Attribute AvantUpdate.VB_UserMemId = -2147384831
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [BeforeUpdate]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [BeforeUpdate] Value=" & MyCtrl.Value
    End Sub
     
    Public Sub ApresUpdate()
 Attribute ApresUpdate.VB_UserMemId = -2147384832
        If TypeOf MyCtrl Is MsForms.Frame Or TypeOf MyCtrl Is MsForms.MultiPage Then UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [AfterUpdate]": Exit Sub
        UserForm1.ListBox1.AddItem MyCtrl.Name & "(" & MyIndex & ") [AfterUpdate] Value=" & MyCtrl.Value
    End Sub


Puis importez ce module de classe dans votre classeur (en ayant pris soin de supprimer l'ancien devenu obsolète).

Voilà, votre classeur de test est prêt!
Avant, j'arrivais jamais à finir mes phrases... mais maintenant je
Commenter la réponse de pijaku
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 11 avril 2018 Dernière intervention - Modifié par ucfoutu le 23/03/2016 à 21:07
0
Merci
Bonjour, Franck,
Ne t'embarque pas dans un tel labyrinthe. Tu vas t'y perdre inutilement.
Laisse les instructions/contrôle de sortie s'effectuer là où elles sont importantes (dans l'évènement exit de la textbox concernée, là où elle est - le Userform-).
Le fait d'avoir constitué une collection des textboxes subordonnées à des évènements définis dans une classe n'inhibe en rien le(s) évènement(s) non gérés par la classe concernée.
Tu vois bien que c'est également le cas sans classe aucune : les contrôles à la sortie y sont distincts de ceux à la saisie.
A vouloir faire autrement, tu vas te mettre au sein d'une véritable usine à gaz dans laquelle il te faudra :
- soit gérer (lourd lourd) à l'aide de Ontime
- soit gérer à l'aide d'un "rappel" (addressof) constant (et ralentisseur)
- soit gérer la totalité des autres contrôles du userform dans une classe également ...

EDIT : il faut que tu comprennes (pour comprendre les mots qui précèdent) que l'évènement exit n'est pas en vérité le constat direct de sortie d'une textbox, mais celui, très indirect, de la dation du focus à un autre objet. Il a beau être ""présenté" comme un évènement de la textbox, il n'est en réalité que celui d'un autre contrôle.

EDIT2 : on pourrait également (mais l'idée est toujours la même : constat d'un clic "ailleurs" et plus sur le contrôle que l'on quitte) s'amuser à "relever" l'évènement d'un clic, s'assurer qu'il est fait non seulement sur le userform, mais en plus ailleurs que sur la textbox, mais en plus dans le "rectangle" d'un contrôle non inhibé, etc, etc ... (ouille ouille ...). Cela impliquerait en outre l'intervention d'une variable lors de l'entrée dans la textbox (pour comparaison subséquente ...)
Vraiment, Franck, un tel chemin serait ardu, démesuré et, surtout, sans réel grand intérêt.


________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
Commenter la réponse de ucfoutu
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 23 mars 2016 à 21:20
0
Merci
Bonsoir Jacques,

Merci de ta réponse, elle est tout à fait en adéquation avec mes attentes.
A savoir, comment sont "créés", "gérés", "générés", les événements en VB.
Je n'ai pu lire aucun tutoriel, aucun cours à ce sujet dans mes recherches.
Oui, bien sur, on en parle à droite et gauche, mais on ne rentre pas dans le "vif du sujet".

Je vais, maintenant, reprendre tes arguments à la suite :
1- Soit gérer (lourd lourd) à l'aide de Ontime
Alors, ce type de procédure, je l'ai rencontré dans mes recherches. Ils utilisent une procédure "toujours" active lors de l'affichage de l'UserForm, en utilisant un DoEvents en boucle. Toi et moi en connaissons le résultat sur l'utilisation de l'UC de l'ordi...
A éviter.
Même avec OnTime en substitution, on arrive à un code pas très fonctionnel.
2- soit gérer à l'aide d'un "rappel" (addressof) constant (et ralentisseur)
Je suppose qu'ici tu parles de Timer avec des appels aux api KillTimer etc...
Pas top, pour les mêmes raisons que ci-dessus
3- soit gérer la totalité des autres contrôles du userform dans une classe également ...
C'était ma première idée.
Impossible (*) à mettre en oeuvre, car hyper complexe selon le nombre, le type de control présents dans l'Userform.
(*) nécessite en plus de boucler sur d'éventuels contrôles supplémentaires, contrôles pas forcément présents sur toutes les machines ==> Usine à gaz évidente.

Donc...
Il reste ton argument principal (selon moi) :
Le fait d'avoir constitué une collection des textboxes subordonnées à des évènements définis dans une classe n'inhibe en rien le(s) évènement(s) non gérés par la classe concernée.
Et là, je te réponds que : oui. Avec le code donné ci-dessus, en utilisant l'api ConnectToConnectionPoint et l'attribut "correct", on arrive à "créer" un événement non-natif. Il faut, bien entendu, déclarer l'objet qui subit ces événements "As Object", et non "As Control" ou "As MsForms.Machin", mais cela semble fonctionner.
Néanmoins, n'ayant pas compris l'aide msdn en ligne relative à l'api ConnectToConnectionPoint, je suis avide de renseignements à ce propos.
Si tu connais, n'hésite pas!
Je pense que la bonne réalisation, ou l'abandon, de mon projet dépend de cette compréhension...
Commenter la réponse de pijaku
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 11 avril 2018 Dernière intervention - Modifié par ucfoutu le 24/03/2016 à 08:28
0
Merci
C'est apparemment un peu plus complexe que cela.
Il semblerait que tu doives d'abord "déléguer" les évènements depuis l'userform lui-même (je n'ai pour l'instant que lu "en diagonale").
Regarde cette discussion :
http://www.mrexcel.com/forum/excel-questions/820733-one-code-multiple-userform-control-changes.html
il semble qu'elle est susceptible de t'apporter un éclairage.

Ceci étant : gérer de cette manière ne me parait pas être véritablement une simplification. Il me parait beaucoup plus simple :
- de n'ajouter qu'un module (pas de classe) contenant la procédure (publique) de contrôle de saisie, procédure recevant par référence comme paramètres tous ceux nécessaires (le contrôle, le keyascii, le "format" de date souhaité, ...)
- d'utiliser ensuite "normalement" (depuis l'userform) les évènements de la textboix concernée :
------ dans l'évènement keydown : appeler la procédure de contrôle du module
------ dans l'évènement exit : se contenter de vérifier que contient bien 10 caractères sinon cancel = true

Il est ici "bon" de rappeler que les chances sont vraiment faibles d'avoir sur un même userform une grande quantité de textboxes devant être ainsi contrôlées en saisie. Mais même si tel était le cas, d'une part, et que, d'autre part, on voulait absolument alors éviter d'écrire toujours la même ligne d'appel d'une procédure publique de contrôle, on pourrait toujours attribuer cette procédure à l'évènement keydown dans un module de classe, mais continuer à utiliser quant à lui l'évènement exit depuis l'userform (comme je l'ai dit plus haut).
Je demeure vraiment convaincu qu'une simple procédure dans un module se prêtera toujours mieux à la maintenance éventuelle, y compris dans le cas d'un nombre relativement important de textboxes de dates.


EDIT : je vais dans la semaine en cours tenter de mettre en oeuvre un autre mécanisme beaucoup plus simple et que j' "entrevois" ainsi :
- une textbox "spéciale" unique, utilisée comme tremplin de contrôle de saisie (on pourra y ajouter des contrôles divers (dates, nombres, etc ...)
- superposition systématique de toute textbox présente (en y entrant) par ce tremplin
- utilisation de la propriété tag des textboxes à contrôler pour déterminer le type de contrôle à faire (ou à ne pas faire ...)
Je vais à ce propos "voir" s'il est plus "adroit" d'utiliser cette propriété tag ou de "jouer" avec les noms des textboxes concernées par un contrôle de saisie ...
- saisie "réelle" sur la textbox "contrôlée", synchronisée sur la saisie dans le "tremplin"
- utilisation (en sortie) du seul évènement exit de la textbox tremplin
etc ...

________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 24 mars 2016 à 08:47
EDIT : je vais dans la semaine en cours tenter de mettre en oeuvre un autre mécanisme beaucoup plus simple et que j' "entrevois" ainsi :
- une textbox "spéciale" unique, utilisée comme tremplin de contrôle de saisie (on pourra y ajouter des contrôles divers (dates, nombres, etc ...)
- superposition systématique de toute textbox présente (en y entrant) par ce tremplin
- utilisation de la propriété tag des textboxes à contrôler pour déterminer le type de contrôle à faire (ou à ne pas faire ...)
Je vais à ce propos "voir" s'il est plus "adroit" d'utiliser cette propriété tag ou de "jouer" avec les noms des textboxes concernées par un contrôle de saisie ...
- saisie "réelle" sur la textbox "contrôlée", synchronisée sur la saisie dans le "tremplin"
- utilisation (en sortie) du seul évènement exit de la textbox tremplin
etc ...

Je n'avais même pas songé à ces différents types de contrôles que l'on peut faire sur un TextBox...
Je vais m'y pencher également, avec la méthode exposée plus haut.
Commenter la réponse de ucfoutu
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 24 mars 2016 à 08:15
0
Merci
Bonjour Jacques,

C'est de cette discussion (et des liens inclus) que j'ai tiré le code plus haut (clsBpca).

Je te rejoins sur le fait que ce que je souhaite faire (un (des) textobx date) n'est pas très utile.
L'intérêt ici ne réside que dans la création d'événements non natifs pour les TextBox. Cela réponds à un réel besoin, une réelle demande.
Le TextBox_Date n'est ici qu'un exemple d'utilisation.

Toutefois, la procédure d'appel de ce type de contrôle personnalisé est grandement simplifié pour l'utilisateur lambda. Plutôt que d'écrire 2 procédures événementielles par textbox de saisie de date, un simple appel à la classe dans le UserForm_Initialise() suffit.
Commenter la réponse de pijaku
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 25 mars 2016 à 14:10
0
Merci
Bonjour,

Des nouvelles du jour.
Le plus gros souci du code que je vous donnais avant-hier, réside dans la "sortie" d'un textbox faisant partie d'un controle container (Frame ou Multipage).
J'ai réussi à contourner cette difficulté en :
> ajoutant les contrôles "container" à la classe
> ajoutant une variable Public A_Focus dans un Module standard
> bouclant, lors de leur sortie, sur les contrôles containers pour vérifier si tous les textbox contenus ont bien effectuer leur "sortie". Si un textbox est encore "actif", en déclencher la sortie.

Cela nous donne un code convenable, sans grosse difficulté pour l'utilisateur.
Néanmoins, dans un souci de simplification extrème, j'aimerais me débarasser de :
> la variable Publique
> l'ajout dans le code de l'userform, des conteneurs à la classe.

Je vais donc voir s'il n'y a pas possibilité d'intégrer cela directement dans le code de la classe.

Voici le Fichier exemple.
(Pour toi, Jacques, je peux te l'envoyer par mail, si intéressé).
Commenter la réponse de pijaku
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 11 avril 2018 Dernière intervention - Modifié par ucfoutu le 26/03/2016 à 07:54
0
Merci
Je veux bien regarder le classeur que tu m'enverrais par mail, mais je demeure de plus en plus persuadé de ce que le chemin pris est de plus en plus tortueux.
Je ne crois pas qu'une classe soit vraiment ce qu'il y a de plus souhaitable.
Ceci étant dit : s'il n'est pas possible de constater depuis une classe qu'une textbox n'a plus le focus, il est par contre assez simple de la forcer à le garder tant que la saisie qui y est faite n'est pas acceptable.
Nous allons commencer par du simple (sans classe pour l'instant).
J'utilise ici l'évènement Change (qui sera, lui, reconnu depuis la classe).
Un userform - des textboxes dont l'une nommée teste - d'autres contrôles divers (commandbuttons, par exemple)
et ce code exemple super-bâclé pour l'instant :
Private deja As Boolean
Private col As New Collection

Private Sub Teste_Change()
If ActiveControl.Text <> "" And Len(ActiveControl.Text) < 10 Then
If Not deja Then inhibe ActiveControl: deja = True
Else
activer ActiveControl
End If
End Sub

Private Sub inhibe(ct As Object)
For i = 1 To col.Count
col.Remove (i)
Next
Dim c As Object
For Each c In Me.Controls
If Not c Is ct And c.Enabled Then
c.Enabled = False
col.Add c.Name, c.Name
End If
Next
End Sub

Private Sub activer(ct As Object)
Dim c As Object
For i = col.Count To 1 Step -1
Me.Controls(col.Item(i)).Enabled = True
col.Remove (i)
Next
deja = False
End Sub

Il est tel qu'on ne peut quitter la textbox teste que si vide ou qu'elle contient au moins 10 caractères.
Voilà l'idée de base....

NB : tu observeras qu'un contrôle qui serait déjà "normalement" inhibé ne serait pas "touché", lui (ce qui préserve donc son état originel).


________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 26 mars 2016 à 09:16
Bonjour Jacques,
Merci de ta réponse, je vais tester ce week-end.
Cependant, il faut également que je repense à tout ça, car peu importe la solution retenue, il est toujours nécessaire de faire un contrôle final des saisies, via un commandbutton, pour transférer les saisies de l'userform dans une feuille par exemple.
Or si un tel contrôle demeure obligé, pourquoi vouloir le faire en cours de saisie?
Je vais donc réfléchir ce week-end avec cette idée en tête, et je reviens mardi.
Bon week-end de pâques à toi et tes proches.
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 11 avril 2018 Dernière intervention - 26 mars 2016 à 11:27
Or si un tel contrôle demeure obligé, pourquoi vouloir le faire en cours de saisie?

Des raisons peuvent exister, notamment (mais pas uniquement) de convivialité.
J'ai encore en mémoire les mouvements d'humeur de mes collaborateurs à qui avait été imposée une application qui "attendait" la fin d'une saisie de formulaire pour leur dire "gna gna gna ... la saisie du champ "toto" n'est pas cohérente, ou celle attendue, ou ....etc ...).
C'était encore plus cocasse lorsque les champs suivant le champ concerné étaient, selon que le champ concerné était "rempli" ou non, à ignorer (sauter) ou au contraire devenaient à saisie obligatoire (on devine bien alors le côté "comique" (pas drôle du tout) de la situation en résultant)
J'avais à l'époque longtemps combattu pour mettre un terme à ce qui était un confort pour l'équipe de développement, mais un supplice pour les utilisateurs. Je n'ai pu mettre un terme à ces faits que lorsque, deux ans plus tard, on m'a admis comme chef de projet au centre de traitement de l'information de mon administration de tutelle.
Commenter la réponse de ucfoutu
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 11 avril 2018 Dernière intervention - Modifié par ucfoutu le 29/03/2016 à 08:26
0
Merci
Bonjour, Franck,
Il m'est ce matin venu à l'esprit une autre idée : empêcher la sortie de la textbox si pas acceptable, mais sans :
- ni superposition par "tremplin"
- ni l'inhibition de tous les autres contrôles de l'userform.
Ce n'est pas encore concrétisé, mais je pense pouvoir y arriver.
A plus.

EDIT : étape 1 (la souris) passée avec succès.
J'ai d'abord travaillé avec VB6 et ai pu transposer pour VBA
Je m'attaque maintenant à l'étape 2 (clavier), plus ardue du fait que Windows intercepte et gère en priorité la touche tab (entre autres).
Mais bon ... je vais contourner par feinte déjà entrevue... (et que j'ai déjà réussie avec VB6 .. reste à transposer pour VBA)
A plus (après la pêche)

________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 29 mars 2016 à 10:47
Bonjour Jacques,

Je viens de t'envoyer mon fichier par mail.

Je ne suis pas sur de parvenir à mes fins par cette voie.
J'attends donc impatiemment ta solution.

J'ai également testé ta solution en "inhibant" tous les autres contrôles lors de la saisie.
C'est plutôt pas mal, ça a le mérite d'être fonctionnel.
Commenter la réponse de ucfoutu
pijaku 12205 Messages postés jeudi 15 mai 2008Date d'inscriptionModérateurStatut 13 septembre 2017 Dernière intervention - 5 avril 2016 à 11:57
0
Merci
Bonjour,

Je crois être enfin parvenu à mes fins.
Pour pouvoir le confirmer, il me faudrait un petit coup de main pour des tests. Tous ceux (les tests) que j'ai pu faire tendent à prouver que cette méthode fonctionne.
J'aurais donc besoin, avant d'en faire un snippet, de testeurs.

Je précise que, pour l'instant, je n'ai créé que 2 événements (Enter et Exit), que ce n'est valable (pour l'instant) que pour des textbox (l'évolution sera possible pour tous contrôles ayant une propriété Text et une méthode SetFocus), pour le seul test si vide (évolution plus que facile).

Les principaux inconvénients restent :
- les deux variables à déclarer Public dans un module (je voulais, en effet, me passer de module supplémentaire),
- l'ordre de tabulation en cas d'encapsulation de plusieurs Frame (il y a un exemple dans le fichier, dans le bas de l'UserForm)
- être contraint d'implémenter la classe avec les contrôles conteneurs...

Je vous mets donc mon fichier en ligne : cjoint
(@ Jacques : je te l'envoie par mail de suite)

Merci de vos retours.
Bonjour,
Je suis tombé par hasard sur ce sujet, mais étant sur Office 2016 cela ne semble pas fonctionner, dommage :-(
Commenter la réponse de pijaku

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.