XL 2016 UserForm vbModeless - Ré-activation ne donne pas le Focus à l'ActiveControl

Dudu2

XLDnaute Barbatruc
Bonjour,

C'est expliqué dans le fichier:

1640470057461.png


Bien que j'ai pu ré-activer le UserForm vbModeless sur son MouseMove() (différentes options essayées), le focus ne vient pas dans l'ActiveControl du UserForm.
Si vous avez un idée...

Edit: Faut-il se rabattre sur la génération d'un clic souris sur les coordonnées de l'ActiveControl ?
Cordialement.
 

Pièces jointes

  • Classeur1.xlsm
    26.4 KB · Affichages: 12
Dernière édition:
Solution
re
Bonjour @Dudu2
comme je te l'ai dit il faut sortir des sentiers battus
je reprend ton userform
j'ajoute un textebox en plus qui sera masqué si il faut si tu en a déjà plusieurs c'est pas la peine d'en ajouter

donc
dans ton exemple j'ajoute un textbox même de taille zero si tu veux

demo.gif


ensuite je vire tout ton code entièrement
je vais gérer le sélection change dans le userform directement
dans cet event je vais pointer l'activecntrol

et au mouve dans le userform si un control a été pointer je le reactive en le disablant et le re enabilisant
parti de la il est actif et je lui done le focus et selstart
le tour est joué
VB:
Public WithEvents feuille As Worksheet
Public ctrl As Object

Private Sub...

patricktoulon

XLDnaute Barbatruc
re
Bonjour @Dudu2
comme je te l'ai dit il faut sortir des sentiers battus
je reprend ton userform
j'ajoute un textebox en plus qui sera masqué si il faut si tu en a déjà plusieurs c'est pas la peine d'en ajouter

donc
dans ton exemple j'ajoute un textbox même de taille zero si tu veux

demo.gif


ensuite je vire tout ton code entièrement
je vais gérer le sélection change dans le userform directement
dans cet event je vais pointer l'activecntrol

et au mouve dans le userform si un control a été pointer je le reactive en le disablant et le re enabilisant
parti de la il est actif et je lui done le focus et selstart
le tour est joué
VB:
Public WithEvents feuille As Worksheet
Public ctrl As Object

Private Sub feuille_SelectionChange(ByVal Target As Range)
Set UserForm1.ctrl = ActiveControl
End Sub

Private Sub UserForm_Activate()
Set feuille = ActiveSheet
End Sub


Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Not UserForm1.ctrl Is Nothing Then
ctrl.Enabled = False: ctrl.Enabled = True: ctrl.SetFocus
ctrl.SelStart = Len(ctrl.Value)
End If
End Sub
démonstration
demo.gif
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Bonjour @patricktoulon,

Je sais pas d'où t'es venue l'idée mais c'est très original.
Le problème avec ta solution, c'est que le Selectionchange() de la feuille est dans le code du UserForm.
Du coup tous les traitements normalement liés à cet évènement il faut les mettre là-dedans ?
Ou bien le SelectionChange standard de la feuille marche encore ?

J'ai remarqué que ta séquence:
VB:
ctrl.Enabled = False: ctrl.Enabled = True: ctrl.SetFocus
a un effet dans mon code.
L'ActiveControl est initialement sur TextBox1, il passe de TextBox1 à TextBox2 et TextBox1enabled = False !
Ça c'est un truc de ouf !
Je vais essayer d'exploiter cet étrange phénomène !
 

patricktoulon

XLDnaute Barbatruc
re
Je sais pas d'où t'es venue l'idée mais c'est très original.
ben c'est de notoriété public que je suis un original 😅😂🤣😂


Du coup tous les traitements normalement liés à cet évènement il faut les mettre là-dedans ?
Ou bien le SelectionChange standard de la feuille marche encore ?
non tu peux laisser l'events original faire son job comme si rien n’était l'event dans le userform est un calque
il me semblait te l'avoir déjà dit dans une autre discussion ou alors c'est quelqu'un d'autre je sais plus
je vais tester un exemple a plusieurs textbox pour voir

pourquoi le calque de l'event dans le userform
et bien tout simplement par ce feuille est devenu enfant du userform (Attention uniquement dans le calque) )mais pas réellement c'est une simple question d'instance de classe event
 

Dudu2

XLDnaute Barbatruc
Ceci dit, ce qui agite le cocotier dans le SetFocus au retour de la pseudo-réactivation du UserForm, c'est comme je le disais ci-dessus ton improbable séquence:
Code:
ctrl.Enabled = False: ctrl.Enabled = True: ctrl.SetFocus

Merci pour cette improbable séquence de génie ! ;)

Aussi l'ai-je intégrée dans mon code et ça fonctionne.
A condition effectivement, comme pour ton code, d'avoir au moins un autre Control dans le UserForm (TextBox, CommandButon, etc...) parce que le ctrl.Enabled = False fait évidemment passer le Focus au Control suivant qui doit exister.


1640518949005.png


Voir fichier ci-dessous.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
En fait, si tu remplaces la séquence:
VB:
Set Ctrl = Me.ActiveControl
Ctrl.Enabled = False
Ctrl.Enabled = True
Ctrl.SetFocus

Par la séquence:
VB:
Set Ctrl = Me.ActiveControl
CreateObject("wscript.shell").SendKeys ("{TAB}")
DoEvents    'SendKeys synchrone
Ctrl.SetFocus

Tu obtiens le même résultat.
Car il faut agiter le cocotier dans le UserForm pour que ce
1640519701222.gif
SetFocus se décide à faire ce pour quoi il est fait !!!
 

Pièces jointes

  • UserForm vbModeless - Réactivation SetFocus.xlsm
    30.8 KB · Affichages: 1

patricktoulon

XLDnaute Barbatruc
j'avoue je comprends les ligne de code mais (comme c'est dans le même event ) je ne comprends pas ton fonctionnement

si je comprends bien
au move tu senkeys un tab pour activer un ctrl (bref tu secoue tout çà)et tu active celui qui a été précédemment déterminé

mais a quel moment AVEC_SENDKEYS devient false
est ce que ces dieze devant les if dans l'event "move" ferait que l'on serait alors en fonctionnement adressof
ce qui permet effectivement un subclassing et donc un ré amorcage de la variable AVEC_SENDKEYS ??
sinon je pige pas
 

patricktoulon

XLDnaute Barbatruc
ok je pense avoir pigé
c'est toujours le enabled true false qui sauve la mise
en effet quand on le dé active et réactive c'est lui qui reprend le focus même si ça n'est pas traduit graphiquement à l’écran donc avec la condition du bon handle soit c'est le send keys soit c'est lma manip qui réactive le textbox
+le set focus et selstart a la fin
c'est tordu quand même
je préfère ma version qui est explicite quand on sélectionne on mémorise quand on revient on fait ma manip "enabled"
 

patricktoulon

XLDnaute Barbatruc
heu... ben non j'avais tout faux
en fait la condition handle suffit
le sendkeys c'est juste pour activer n'importe le quel
et ensuite les 3 ligne pour le setfocus du ctrl qui me remet le bon
c'est tout
à cela j'ajoute(j’enlève tout du moins les apis et les remplace par la macro4
et voilà j'ai le même résultat
en gros ta constante ne sert a rien
VB:
Option Explicit
Private MeHWnd As Variant
'-------------------
'Activation UserForm
'-------------------
Private Sub UserForm_Activate()
    MeHWnd = ExecuteExcel4Macro("CALL(""user32"",""GetActiveWindow"",""JCC"")")          'handle fenetre active
    Me.TextBox1.SetFocus
End Sub

'----------------------
'Survol souris UserForm
'----------------------
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Dim Ctrl As Variant
    If MeHWnd <> ExecuteExcel4Macro("CALL(""user32"",""GetActiveWindow"",""JCC"")") Then
        Me.Show vbModeless
        Set Ctrl = Me.ActiveControl
        CreateObject("wscript.shell").SendKeys ("{TAB}")
        DoEvents    'SendKeys synchrone
        Ctrl.SetFocus
        If TypeOf Ctrl Is TextBox Then
            Ctrl.SelStart = Len(Ctrl.Value)
        End If
    End If
End Sub

rigolo non ?;)
 

Dudu2

XLDnaute Barbatruc
C'est ça, il faut secouer le cocotier d'une manière ou d'une autre (c'est à dire passer au Control suivant par un moyen quelconque***) pour que le SetFocus joue enfin son rôle à l'écran ce qu'il devrait normalement faire mais ne fait pas dans ce cas, ce qui n'est PAS normal.

***Ce moyen est ici:
- soit un Ctrl.Enabled = False (fait passer le Focus sur le Control suivant si Ctrl a le Focus car on ne peut pas avoir le Focus sur un Control non-Enabled, donc Excel passe au suivant)
- soit un SendKeys Tabulation synchrone (fait passer le Focus sur le Control suivant)

en gros ta constante ne sert a rien
En effet, d'ailleurs, au UserForm_Activate() tu as judicieusement replacé le FindWindow par un GetActiveWindow ce qui simplifie l'affaire. J'ai reporté la modif dans mon fichier avec API ci-dessus.

Merci pour ta version ExecuteExcel4Macro dont tu es LE Grand Spécialiste ;).
 
Dernière édition:

Membres actuellement en ligne

Statistiques des forums

Discussions
312 196
Messages
2 086 101
Membres
103 116
dernier inscrit
kutobi87