cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 2013
-
4 janv. 2006 à 14:02
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 2013
-
7 janv. 2006 à 10:32
Bonjour,
Je suis entrain de faire un Control, appelons-le "x" (qui dérive de Usercontrol) qui devra faire certaines actions lorsque la souris est au-dessus de lui.
Mon problème, c'est que ce Control ("x") possède d'autres Control, disons "y" (en loccurance, y'a pour le moment des Labels et une PictureBox) et que lorsque ma souris passe sur l'un des "y" qui se trouve dans "x" je reçois un MouseLeave puis un MouseEnter quand la souris entre repectivement quitte "y" (mais reste toujours dans "x" !).
Et ça me pose bien-entendu tout un tas de problème...
J'aurais aimé savoir comment régler ce problème le plus proprement possible (autrement dit, comment faire pour savoir si la souris est dans un Control, y compris un des sous-Control).
(J'espère que la question était claire )
Merci d'avance aux réponses !
cs_coq
Messages postés6349Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 6 janv. 2006 à 13:45
Un peu trop vite d'ailleurs, j'ai écrit une connerie ^^ :
public class ContainerLevelMouseEventsMessageFilter : IMessageFilter
{
public ContainerLevelMouseEventsMessageFilter(Control container)
{
if ( container = = null )
throw new ArgumentNullException("container");
this._container = container;
this._container.Disposed += new EventHandler(_container_Disposed);
}
private Control _container = null;
private bool _isEntered = false;
private const int WM_MOUSEMOVE = 0x0200;
#region Membres de IMessageFilter
public bool PreFilterMessage(ref Message m)
{
if ( m.Msg == WM_MOUSEMOVE )
{
// détermine si la cible est notre contrôle ou est contenue par notre contrôle
Control ctrl = Control.FromHandle(m.HWnd); if ( ctrl !null && (ctrl this._container || this._container.Contains(ctrl)) )
{
if ( !this._isEntered )
{
// levée de MouseEnter
this.OnMouseEnter();
this._isEntered = true;
}
// récupération du point (en coordonnées du contrôle cible)
Point pt = new Point(m.LParam.ToInt32());
// conversion en coordonnée du contrôle
Point containerPoint;
if ( ctrl != this._container )
containerPoint = this._container.PointToClient(ctrl.PointToScreen(pt));
else
containerPoint = pt;
// levée de MouseMove
this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, containerPoint .X, containerPoint.Y, 0));
}
else
{
// si la cible n'est pas un enfant, et que la sortie n'a pas encore été notifiée
if ( this._isEntered )
{
// levée de MouseLeave
this.OnMouseLeave();
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 4 janv. 2006 à 18:25
Salut et merci de la réponse.
A vrai dire j'ai toujours eu un peu de peine avec le WndProc, comme savoir par exemple quel message m'intéresse?
Tu pourrais un peu m'aiguiller stp? Merci
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 4 janv. 2006 à 22:43
Ben si je met ce code, alors j'observe dans ma Form de test, que quand j'entre dans le Control il m'affiche correctement ce qu'il faut dans la console (il dit qu'il est entré et que la souris bouge au dessus) mais le problème est toujours le même : la souris est à l'intérieur du Control et lorsqu'elle passe sur un label (compris dans le Control) ca vient écrit que la souris a quitter le Control (hors, ce n'est pas le cas, dumoins je ne veux justement pas que ça le soit !).
Je sais pas si tu vois ?
cs_coq
Messages postés6349Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 4 janv. 2006 à 22:51
Le problème c'est que le message WM_MOUSEMOVE est envoyé directement au Label et non pas relayé par le contrôle.
Je pense que le salut peut être dans l'utilisation d'un filtre au niveau de l'application (IMessageFilter) avec vérification pour savoir si le contrôle destinataire est enfant du contrôle "x".
Ou carrement en mode bourrin (mais probablement moins gourmand en ressources) regarder si les coordonnées du pointeur sont dans le rectangle du contrôle "x".
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 4 janv. 2006 à 23:08
En fait, l'idée est toute simple (ce que je veux faire finalement) : quand on entre sur un Control, je veux le colorier. Et quand on sort, je veux qu'il reprenne sa forme normal. Ca marche, sauf que quand on entre sur un label qui se trouve dans ce Control ben il reprend sa forme normal alors que ma souris est toujours dans le Control.
C'est vraiment si compliqué de faire ça ? lol
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 5 janv. 2006 à 10:11
Salut Lutinore,
Oui en fait j'avais cette solution avant que je pose la question, mais elle me déplait très fortement pour plusieurs raison. Une des raisons principale c'est qu'après je ne peux plus utiliser le tooltip (qui fonctionne avec MouseHover) : Le tooltip est displayé seulement quand on est sur le Control à proprement dit, mais pas quand on est sur un sous-Control.
Une autre raison, c'est que si je quitte brusquement le Control avec le souris, on dirait qu'il n'a pas le temps d'effectuer le OnLeave et mon Control reste en couleur, alors que le curseur est en dehors.
J'aimerais bien une solution général, qui me permet de ne pas être notifié des events qui se produisent sur un de ces sous-controls (ou autres solutions propres)
Je ne sais pas si c'est très clair ??
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 5 janv. 2006 à 18:36
Peut être si tu abonnes tous les MouseMove des contrôles enfants sur le même évènement du contrôle parent ça te permet de connaitre la position de la souris à tout moment et de déduire si elle entre ou quite le contrôle.. Sinon implementer IMessageFilter ou alors si tu veux faire une sorte de MousePreview sur le même principe que la propriète KeyPreview faut faire un hook ( un WH_MOUSE_LL ).
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 6 janv. 2006 à 08:31
Moui à vrai dire je ne sais pas encore vraiment comment je vais résoudre ce problème mais je viendrai poster un message si j'y arrive...
Merci de votre aide en tout cas.
cs_coq
Messages postés6349Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 6 janv. 2006 à 13:34
Bon, je t'ai rapidement illustré le fond de ma pensée avec un petit exemple, ça sera plus clair :
public class ContainerLevelMouseEventsMessageFilter : IMessageFilter
{
public ContainerLevelMouseEventsMessageFilter(Control container)
{
if ( container == null )
throw new ArgumentNullException("container");
this._container = container;
this._container.Disposed += new EventHandler(_container_Disposed);
}
private Control _container = null;
private bool _isEntered = false;
private const int WM_MOUSEMOVE = 0x0200;
#region Membres de IMessageFilter
public bool PreFilterMessage(ref Message m)
{
if ( m.Msg == WM_MOUSEMOVE )
{
// détermine si la cible est notre contrôle ou est contenue par notre contrôle
Control ctrl = Control.FromHandle(m.HWnd); if ( ctrl !null && (ctrl this._container || this._container.Contains(ctrl)) )
{
if ( !this._isEntered )
{
// levée de MouseEnter
this.OnMouseEnter();
this._isEntered = true;
}
// récupération du point (en coordonnées du contrôle cible)
Point pt = new Point(m.LParam.ToInt32());
// conversion en coordonnée du contrôle
Point containerPoint = this._container.PointToClient(ctrl.PointToScreen(pt));
// levée de MouseMove
this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, pt.X, pt.Y, 0));
}
else
{
// si la cible n'est pas un enfant, et que la sortie n'a pas encore été notifiée
if ( this._isEntered )
{
// levée de MouseLeave
this.OnMouseLeave();
Utilisation :
ContainerLevelMouseEventsMessageFilter panelLevelEvents = new ContainerLevelMouseEventsMessageFilter(this.panel1);
Application.AddMessageFilter(panelLevelEvents);
panelLevelEvents.MouseEnter += new EventHandler(panelLevelEvents_MouseEnter);
panelLevelEvents.MouseLeave += new EventHandler(panelLevelEvents_MouseLeave);
panelLevelEvents.MouseMove += new MouseEventHandler(panelLevelEvents_MouseMove);