XL 2016 VBA - Comment détecter la changement de position d'une fenêtre ?

Dudu2

XLDnaute Barbatruc
Bonjour,

En gestion des évènements d'une fenêtre on a ces options:
1734412001934.png

Il n'y a pas d'évènement WindowLayout() comme il y a un évènement UserForm_Layout() et donc on ne peut pas détecter de déplacement de la Window.

Y a-t-il une parade à part faire mouliner sans fin une macro pour surveiller le layout de la Window ?
 
Dernière édition:
Solution
Et donc après une bonne dizaine d'heures de tests pour trouver la cause et la parade !!!
Ça m'a épuisé ! 😰

La cause: Après une initialisation du projet dans le VBE et uniquement dans ce cas (faut quand même le faire Excel !!!) crash Excel à cause d'un conflit entre l'évènement Application WindowResize et l'évènement SetWinEventHook EVENT_SYSTEM_MOVESIZEEND.

La parade: Désactiver les évènements Application sur l'évènement SetWinEventHook EVENT_SYSTEM_MOVESIZESTART et les réactiver sur EVENT_SYSTEM_MOVESIZEEND pour empêcher l'évènement Application WindowResize de se produire car ce dernier arrive entre les 2.

jurassic pork

XLDnaute Occasionnel
Patrick je persiste à dire que tes boucles c'est pas bon pour la planète :
Avec ces deux tests qui font la même chose :
VB:
Sub TestTimerX()
Dim x As Integer
  For x = 1 To 10000
    TimerX 50
  Next x
End Sub
Sub TestSleep()
Dim x As Integer
  For x = 1 To 10000
    Sleep 50: DoEvents
  Next x
End Sub

Le TimerX occupe presque 100% d'un de mes cores de CPU tandis que le Sleep même pas 1%. Le Sleep repose le CPU et il ne gèle pas si il est court.
 

patricktoulon

XLDnaute Barbatruc
a ben là tu biaise tu fait une boucle sur x avec un sleep de 50
tu gèle les procc 50 milliseconde tout les tours de boucle
soit 50X 10000
autrement dit un sleep de 500 000 par intermittence

après il est possible que ma méthode prenne plus de cpu j'en doute pas d'ailleurs
mais l'impact dans une gestion d'attente n'est pas le même ça c'est sur
ce qui veux dire aussi que ta gestion d'attente dans certains cas devra être plus longue que la mienne pour le même travail
 

Dudu2

XLDnaute Barbatruc
Bonsoir la liste de rythmeur de temps,
Toujours avec les Hook de SetWinEventHook, j'y ai passé des heures pour trouver la raison d'un plantage.

Les Hook, ça marche bien SAUF si on commence à faire un Project Init dans le VBE à l'ouverture du classeur. Vas savoir pourquoi ! Or quand on modifie du code, on est toujours dans ce cas.

J'ai identifié la cas du crash après le Project Init dans le VBE. Je ne vous le décris pas en détails, ça ne servirait à rien.
C'est apparemment un conflit entre le WindowResize de l'Event Application et l'Event du Hook WindowMoveEnd . Le problème c'est qu'on ne peut pas se passer du WindowResize car en resizant la fenêtre par le menu système, seul ce dernier se déclenche contrairement à ce que la doc dit pour les Hook:
1734552732751.png


Bref, je galère.
 

Dudu2

XLDnaute Barbatruc
et ben crée un event resize avec un rect avec les donnée en point de la fenêtre
Je sais pas faire ça.
Pour l'instant j'ai trouvé une parade qui consiste à faire Application.EnableEvents = False dans WindowMoveStart et = True dans le WindowMoveEnd pour ne pas déclencher le WindowResize. qui vient entre les 2.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Et donc après une bonne dizaine d'heures de tests pour trouver la cause et la parade !!!
Ça m'a épuisé ! 😰

La cause: Après une initialisation du projet dans le VBE et uniquement dans ce cas (faut quand même le faire Excel !!!) crash Excel à cause d'un conflit entre l'évènement Application WindowResize et l'évènement SetWinEventHook EVENT_SYSTEM_MOVESIZEEND.

La parade: Désactiver les évènements Application sur l'évènement SetWinEventHook EVENT_SYSTEM_MOVESIZESTART et les réactiver sur EVENT_SYSTEM_MOVESIZEEND pour empêcher l'évènement Application WindowResize de se produire car ce dernier arrive entre les 2.
 

Pièces jointes

  • Window Events and Move.xlsm
    40.7 KB · Affichages: 0
Dernière édition:

patricktoulon

XLDnaute Barbatruc
a ben des fois c'est ça
je veux dire
si dans le WindowMoveStart tu met un select case
et dans ce select case tu test le width et height de ta fentre
si il a changé tu ajoute un event perso et tu l'appelle dans ce case
dans le case else tu appelle la WindowMoveStart
c'est tout
 

patricktoulon

XLDnaute Barbatruc
Bonjour à tous les deux
je reviens un peu sur le timer perso xla
voici un fichier xlam accompagné de son fichier test.xlsm
dans le quel j'ai créer 2 rithmer un avec mon double do/loop et un autre avec le sleep
@jurassic pork tu constatera que le double do/loop avec doevent est moins bloquant que celui avec le sleep

le principe est simple dans les sub de test on lance le rythmeur avec ou sans sleep on peut l’arrêter
et dans l'appel on lui envoie la sub a déclencher
NE PAS OUBLIER D ACTIVER LA REF DANS OUTILS /REFERENCE
Voila dans l'appel on precise les milli sec le classeur dans le quel est la sub a déclencher, et le nom de la sub
 

Pièces jointes

  • test.xlsm
    13.6 KB · Affichages: 2
  • Xtimer.xlam
    14.4 KB · Affichages: 2

Dranreb

XLDnaute Barbatruc
Bonjour @Dudu2.
Coté utilisation, une fois déclaré en tête Private WithEvents MonRythmeur As Rythmeur, MonRythmeur figure dans la liste de gauche (Objet) qui surmonte la fenêtre de code. Il suffit de l'y sélectionner pour implanter un modèle de Private Sub MonRythmeur_Intervient(ByVal Tic As Long), procédure de prise en charge de l'évènement dans laquelle on peut mettre directement le code à exécuter, ou, s'il doit être aussi exécuté dans d'autres cas, invoquer une autre procédure qui le contient.
Dans l'UserForm_Initialize il doit bien sûr avoir été initialisé par Set MonRythmeur = New Rythmeur et ensuite lancé quelque part par une invocation de sa méthode Lancer.
Coté fonctionnement de la classe c'est simple : la fonction XRythmeur.IdtRythmeurLancé reçoit en tant que Ryth le Me du Rythmeur qui l'invoque. Elle le note dans son tableau TRythmeurs comme poste Idt une fois celui-ci calculé. Cet Idt est ensuite communiqué au SetTimer, de sorte que la Sub TimerProc le reçoit à son tour.
Il n'en faut pas plus pour qu'elle puisse invoquer TRythmeurs(Idt).Actionner Tic
 
Dernière édition:

jurassic pork

XLDnaute Occasionnel
Bonjour à tous les deux
je reviens un peu sur le timer perso xla
voici un fichier xlam accompagné de son fichier test.xlsm
dans le quel j'ai créer 2 rithmer un avec mon double do/loop et un autre avec le sleep
@jurassic pork tu constatera que le double do/loop avec doevent est moins bloquant que celui avec le sleep
Hello Patrick,
comme je j'avais indiqué le sleep est intéressant que sur des temps courts ( < 200 ms)
On peut faire comme cela par exemple :
VB:
Function StartRithmeurBySleep(mS As Long, wbk As Workbook, fonction As String)
    tim = True
    Do While tim = True
        ' Pause pour réduire la charge processeur
        x = 0
        Do While x < mS / 100
             x = x + 1
             Sleep 100
             Application.Run wbk.Name & "!" & fonction
             DoEvents
        Loop
    Loop
End Function
Par contre il y a un truc qui m'inquiète dans ton rythmeur on a plus la main dans l'éditeur VBA quand on le lance. Comment on fait pour lancer la procédure ArreterTimer ? et ça coince aussi quand on fait de la saisie dans la feuille. Le timer par une autre instance d'excel n'a pas ces problèmes. Un complément n'utilise pas une autre instance.
Faut faire gaffe les tontons flingueurs sont de retour ;)
Ami calmant, J.P
 
Dernière édition:

Discussions similaires

Membres actuellement en ligne

Aucun membre en ligne actuellement.

Statistiques des forums

Discussions
315 087
Messages
2 116 083
Membres
112 655
dernier inscrit
fannycordi