Comportement étrange de l'événement mousemove

cs_User8 Messages postés 30 Date d'inscription jeudi 24 juillet 2008 Statut Membre Dernière intervention 13 novembre 2012 - 13 nov. 2012 à 11:51
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 - 17 nov. 2012 à 18:06
Bonjour,

je viens de constater un comportement étrange lorsqu'on exécute une application en debug avec un point d’arrêt dans un événement mousemove. L'événement est exécuté en boucle même si la souris ne bouge pas.

Pour le reproduire :
- Créer une application avec juste un TMemo en alignement client sur la fiche principale.
- Ajouter un événement MouseMove sur le mémo contenant la ligne suivant :
Memo1.Lines.Append(Format('line %d: x %d y %d', [memo1.Lines.Count+1,x,y]));

- Exécuter normalement ---> les déplacements de la souris sont affichés normalement. Si la souris s’arrête, le log s’arrête!
- Maintenant rajouter un point d’arrêt dans le mousemove. Vous pouvez décocher l'actions 'arrêter' dans les options avancées du point d’arrêt.
- Exécuter en debug --> On peut voir que même si la souris est immobile, l'événement onmousemove est appelé en boucle.

Quelqu'un a-t-il déjà constaté et trouvé une explication à ce comportement qui peut être problématique dans certains cas?
j'ai regardé un peu sur la toile mais je ne trouve rien.

Est-il possible que le point d’arrêt bloque la propagation du message? Le message est il relancé tant qu'il n'est pas correctement interprété?

Merci.

23 réponses

cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
13 nov. 2012 à 14:59
Bonjour,

le simple fait de mettre placer un point d'arrêt en runtime, déplace la souris..

A noter que si ta souris reste dans le mémo, le onmousmove ne se déclenche que si tu en sors..

Pour ce faire il faut répéter l'évènement également sur le OnMousMove
du mémo.

cantador
0
cs_User8 Messages postés 30 Date d'inscription jeudi 24 juillet 2008 Statut Membre Dernière intervention 13 novembre 2012
13 nov. 2012 à 15:21
Merci pour cette réponse mais peut être que tu aurai pu lire mes explications avant de répondre....

le simple fait de mettre placer un point d'arrêt en runtime, déplace la souris..

Comme expliqué, j'ajoute un point d’arrêt puis exécute en debug. A aucun moment je bouge la souris pour aller créer le point d’arrêt. De plus, vu que je retire l'option "arrêter" du point d’arrêt, a aucun je ne bouge la souris pour relancer l’exécution.

A noter que si ta souris reste dans le mémo, le onmousmove ne se déclenche que si tu en sors..

Non, puisque comme expliqué, l'événement on mousemove est associé au mémo.

Pour ce faire il faut répéter l'évènement également sur le OnMousMove du mémo.

L'événement n'est associé qu'au mémo puisque celui ci est en alignement client sur la forme.
0
cs_User8 Messages postés 30 Date d'inscription jeudi 24 juillet 2008 Statut Membre Dernière intervention 13 novembre 2012
13 nov. 2012 à 15:25
J'insiste sur le fait que la souris est immobile. le log des coordonnées dans le memo à chaque passage dans le onmousemove est là pour le prouver ...
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
13 nov. 2012 à 15:57
Bonjour,

Pour moi, c'est un comportement normal:
- Delphi intercepte en boucle les messages Windows provenant de la souris.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_User8 Messages postés 30 Date d'inscription jeudi 24 juillet 2008 Statut Membre Dernière intervention 13 novembre 2012
13 nov. 2012 à 16:13
Ce comportement apparait uniquement en débogage et si un point d'arret est présent dans le onmousemove.
Si on exécute sans débogage ou si on exécute en débogage mais sans point d'arret, l’événement est appelé une fois et pas indéfiniment avec les même coordonées.

Je ne pense pas que ce soit normal.
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
13 nov. 2012 à 16:32
Pour que Delphi sache si la souris a bougé ou non, il faut bien que Delphi scrute en boucle les messages de la souris !

Je ne vois pas ce qu'il y a d'anormal là-dedans?
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
13 nov. 2012 à 16:39
oui, oui bien sûr, le phénomène se déclenche à l'endroit où le OnMousMove
est placé..(soit la forme, soit le mémo, soit les deux)

et je confirme l'information de Caribensila.

Mais, comme tu ne nous as pas dit ce que tu souhaites faire
on ne peut aller bien loin dans cette discussion..

cantador
0
cs_User8 Messages postés 30 Date d'inscription jeudi 24 juillet 2008 Statut Membre Dernière intervention 13 novembre 2012
13 nov. 2012 à 17:01
Caribensila :

Je suis d'accord avec toi. Delphi scrute les messages puis les propage aux TControl concernés. Mais dans le cas présent, si je fais un déplacement de un pixel, l'application va recevoir un et un seul message WM_MOUSEMOVE. L'application va propager le message à mon Tmemo qui doit appeler l'événement OnMouseMove. Dans le cas que je décris, il semble qu'il y ai bien qu'un seul message WM_MOUSEMOVE(si on en croit spy ++) avec les coordonnées (x1,y1) mais l'événement OnMouseMove lui est appelé indéfiniment avec ces coordonnées (x1,y1). Normalement, quand un message a été interprété, il me semble qu'une propriété handled doit être passé à true pour stopper la propagation du message. Je me demande donc si le point d'arret ne bloquerait pas ce changement de status, ce qui expliquerait pourquoi mon message se propage en boucle coté delphi.

Cantador :
J'ai constaté ce comportement par hasard et j'essaye juste de le comprendre...
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 20:55
Salut,

Le problème soulevé est intéressant.

Ils semblerait que l'évènement TMouseMoveEvent d'un Control se produise 2 fois :
1 : au moment où le curseur quitte sa position initiale,
2 : au moment où le curseur arrive sur une position différente de ce point initial.

On peut le vérifier en se plaçant dans les conditions décrites par User8, c'est à dire un TMemo placé sur un TForm, avec la propriété Align := alClient.
Puis on place ce code dans l'évènement OnMouseMove du Memo :

var
  Done: Boolean;

procedure TForm1.Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Memo1.Lines.Append(Format('x %d y %d', [x, y]));
  Done := not Done;
  if Done then Memo1.Lines.Append('done');
end;


On peut remarquer, d'après ce qui s'affiche dans le Memo, que quelle que soit la rapidité avec laquelle on déplace la souris, il n'y a jamais plus d'un pixel d'écart pour les coordonnées x ou y...

Étonnant, non ?

JP
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 22:05
Encore plus bizarre : je viens de revenir sur mon ordi, j'avais laissé tourner l'exécutable.
Même si le pointeur reste immobile, l'évènement OnMouseMove a bien lieu, puisque le Memo continue à se remplir !
Ou alors ma souris a un problème ?

Je me demande néanmoins cependant quand même comment il se fait-il je ne l'avais pas pas observé tout à l'heure auparavant...
Je vais débrancher ma souris pour vérifier.
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 22:12
C'est PAS la souris.
Avec une autre souris, sans souris, l'évènement a lieu quand même à un rythme régulier.
Bien sûr, les coordonnées xy affichées dans le Memo ne changent pas...
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 23:00
Bon.

1) Quel que soit le Control, l'évènement OnMouseMove a lieu à intervalle régulier, sans toucher à la souris.
2) L'intervalle est d'environ 1 seconde entre 2 évènements OnMouseMove.

Pour le vérifier, j'ai placé ce code dans l'évènement OnMouseMove de différents Controls disposés sur une fiche :

Memo1.Lines.Append(Format('%sMouseMove at %s', [(Sender as TControl).Name, TimeToStr(Now)]));


Reste à trouver le pourquoi.

JP
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 23:12
Heu... y'a quelqu'un ?
On va croire que je m'incruste.
J'ajouterai juste que l'évènement OnMouseMove se déclenche aussi avec le clic gauche de la souris.
Voilà, j'ai de quoi cogiter ce soir avant de m'endormir, pas sûr que ça va m'aider...

Bonne soirée.
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
13 nov. 2012 à 23:25
Il ne faut jamais mettre un point d'arrêt dans un evenement MouseMove/OnPaint/OnDraw*

parce que ça génère des boucles infinies et donc t'es obligé de tuer la session de debog en cours :)

Donc toujours tester via un control de boucle unique :

var Limit : integer = 0;

procedure TFormX.TrucMouseMove(Sender: TObject;X,Y: integer);
begin
  if Limit > 4 then 
    exit;
  inc(Limit);
  faireUnBidule(X, Y);
end;

procedure TFormX.FaireUnBidule(X, Y: integer);
begin
  Self.Caption := Format('%d x %d',[X,Y]);
end;

________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
13 nov. 2012 à 23:46
Ah, OK pour l'explication de f0xi à propos du point d'arrêt.

Sinon pour ce qui concerne tout ce que je viens d'exposer concernant OnMouseMove qui se déclenche tout seul comme un grand, je viens de découvrir le pot aux roses, du moins sur ma bécane.

C'est WinAmp qui me fout la m....

C'est WinAmp qui provoque OnMouseMove dans mon appli, dès qu'il est en mode lecture.
J'avais fait un dernier test, et tout ce que j'avais décrit précédemment ne se produisait plus.
Tout était rentré dans l'ordre.
La seule différence étant que j'avais stoppé la zique. WinAmp était encore lancé, mais pas en mode lecture.
Si vous utilisez WinAmp, faites l'essai svp.
Celà se produit-il avec d'autres applications ?
Celà soulève pas mal de questions concernant l'interaction entre des applications fonctionnant en multitache sous Windows (XP pro en l'occurence).
Et remet en cause la fiabilité de la gestion du multitache par krosoft.
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
14 nov. 2012 à 11:29
« C'est WinAmp qui provoque OnMouseMove dans mon appli, dès qu'il est en mode lecture. »

« L'intervalle est d'environ 1 seconde entre 2 évènements OnMouseMove. »

Si ça vient des vibrations, t'as pas l'air d'écouter des trucs fort rythmés...

----------------------

Je me demande si OnMouseMove n'est pas mal nommé.
En fait ça a l'air de réagir davantage aux mouvements du curseur sur l'écran q'aux réels mouvements de la souris.
En effet, je pense que la souris, en fonction de son réglage, peut envoyer des messages de mouvement au système sans que le curseur saute un pixel.

----------------------

« Et remet en cause la fiabilité de la gestion du multitache par krosoft. »


Franchement, ça m'étonnerait. La gestion du multitâche, c'est quand même la base du fonctionnement du système...
D'un autre côté, on voit mal le rapport entre la gestion du curseur et un lecteur MP3.
Sauf que les Threads doivent avoir la même priorité (maximale!)...
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
16 nov. 2012 à 15:20
Je me demande si OnMouseMove n'est pas mal nommé.
En fait ça a l'air de réagir davantage aux mouvements du curseur sur l'écran q'aux réels mouvements de la souris


Je suis plutôt d'accord avec toi vu que je m'en étais déjà fait la réflexion et que je ne change pas d'avis facilement...

Pour le reste, je continuerai à "investiguer" quand j'aurai le temps et la disposition d'esprit.
Car en effet, lequel des message envoyé par WinAmp peut bien être interprété par Windows comme un message venant de la souris ? et être récupéré comme tel par une appli externe à WinAmp ? La faute à Windows ? la faute à la gestion par Delphi des messages du système ?

Que de questions, que de doutes, quelle belle prise de tête en perspective... Miam miam

Mais bon, après on s'étonne que nos codes si savamment et rigoureusement élaborées plantent... (hé hé)
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
16 nov. 2012 à 15:21
élaborés (les codes)
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
16 nov. 2012 à 16:30
« Car en effet, lequel des message envoyé par WinAmp peut bien être interprété par Windows comme un message venant de la souris ? »

Pour le moment, je ne vois qu'un truc qui peut faire que WinAmp joue avec le curseur, c'est pour interdire la mise en veille, genre dans un Timer :
mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);

Ca ne déplace pas le curseur, mais ça le simule.

J'ai pas WinAmp et reste à vérifier qu'il empêche bien la mise en veille...



Tit'zannonce:
C'est d'ailleurs le seul moyen que je connaisse pour empêcher la mise en veille. Mais si quelqu'un connais une autre méthode, ça m'intéresse...
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
16 nov. 2012 à 20:41
C'est d'ailleurs le seul moyen que je connaisse pour empêcher la mise en veille. Mais si quelqu'un connais une autre méthode, ça m'intéresse...

Sous XP pro 32 bits, l'utilisation de l'API Windows ne pose pas de problème, à tester avec les autres versions...
Pour désactiver la mise en veille :
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE);

Pour la réactiver :
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1, 0, SPIF_SENDWININICHANGE);

Pour connaître l'état de la mise en veille avant modification :
var
  Status: Boolean;
begin
  SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, @Status, 0);
  // si Status retourne True, la mise en veille est active
end;
0
Rejoignez-nous