2015-09-14 1 views
1

Je souhaite colorer la propriété BackColor d'un PictureBox lorsque la souris y entre.Windows Forms MouseEnter ne se déclenche pas après le déplacement du contrôle

Je transforme le BackColor en jaune lorsque l'événement MouseEnter se déclenche, et je réinitialise à transparent dans MouseLeave.

Puis quand je clique sur un PictureBox, je change de position, donc j'ai aussi un événement Move qui le réinitialise en transparent.

Le problème est, une fois que je l'ai déplacé, j'ai besoin d'entrer deux fois le PictureBox avec la souris pour déclencher l'événement MouseEnter!

C'est un problème très graphique, donc j'ai téléchargé un peu video pour vous montrer ce qui se passe, il va sûrement expliquer mon problème mieux que moi.

J'ai essayé d'une autre manière, en changeant la couleur pas dans MouseEnter mais dans MouseHover. Dans ce cas, cela fonctionne bien, sauf que j'ai un retard de 500ms avant de déclencher l'événement Move, ce qui n'est évidemment pas ce que je veux.

Je n'ai pas de solution viable pour le moment.

Pour le code, il est très simple, pour le moment je:

private void pictureBoxMouseUp(object sender, MouseEventArgs e) 
{ 
    // I move the PictureBox here 
} 
  
private void pictureBoxMove(object sender, EventArgs e) 
{ 
    (sender as PictureBox).BackColor = Color.Transparent; 
} 
  
private void pictureBoxMouseEnter(object sender, MouseEventArgs e) 
{ 
    (sender as PictureBox).BackColor = Color.LightYellow; 
} 
  
private void pictureBoxMouseLeave(object sender, MouseEventArgs e) 
{ 
    (sender as PictureBox).BackColor = Color.Transparent; 
} 

Dans le Designer.cs, mes événements pour chaque PictureBox sont comme:

this.pictureBox2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBoxMouseDown); 
this.pictureBox2.MouseEnter += new System.EventHandler(this.pictureBoxMouseEnter); 
this.pictureBox2.MouseLeave += new System.EventHandler(this.pictureBoxMouseLeave); 
this.pictureBox2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBoxMouseUp); 
this.pictureBox2.Move += new System.EventHandler(this.pictureBoxMove); 

EDIT: Pour répondre à ma question, c'est le code que j'utilise maintenant: (les commentaires sont en français)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Diagnostics; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using EmoTEDTherapeute; 

namespace ControlSceneImage { 

    public class SceneImage : PictureBox { 

     public static readonly int defaultWidth = 100; 
     public static readonly int defaultHeight = 100; 

     static readonly int activePbPosY; // Position en Y des scènes actives 

     static readonly Dictionary<string, Point> scenesPos = null; // Invariant, stocke la position initiale des PictureBox 
     static readonly List<Point>[] activeScenesPos = null; // Invariant, stocke les positions des PictureBox en fonction du nombre de scènes actives 

     static List<SceneImage> activeScenes = null; 

     const int maxActiveScenes = 5; 
     const int ecart = 80; 
     const int decalage = 15; 
     const int panelScenesWidth = 909; 
     const int panelScenesHeight = 154; 
     const int panelScenesLocationX = 35; 
     const int panelScenesLocationY = 36; 

     bool isActive; 

     static SceneImage() { 
      // Constructeur initialisant tous les membres statiques, n'est appelé qu'une seule fois, avant tout le reste 
      activePbPosY = (panelScenesLocationY + panelScenesHeight - (int)(0.6 * defaultHeight))/2; 
      scenesPos = new Dictionary<string, Point>(); 
      activeScenesPos = new List<Point>[maxActiveScenes]; 
      for (int i = 0; i < maxActiveScenes; i++) { 
       activeScenesPos[i] = CalcActiveScenesPos(i+1); 
      } 
      activeScenes = new List<SceneImage>(); 
     } 

     public SceneImage() { 
      MouseEnter += new EventHandler(OnMouseEnter); 
      MouseDown += new MouseEventHandler(OnMouseDown); 
      MouseUp += new MouseEventHandler(OnMouseUp); 
      MouseLeave += new EventHandler(OnMouseLeave); 
      BorderStyle = BorderStyle.FixedSingle; 
      Size = new Size(defaultWidth, defaultHeight); 
      SizeMode = PictureBoxSizeMode.Zoom; 
      isActive = false; 
     } 

     private static List<Point> CalcActiveScenesPos(int nbActiveScenes) { 
      List<Point> ret = new List<Point>(); 
      for (int i = 0; i < nbActiveScenes; i++) { 
       ret.Add(new Point((panelScenesLocationX + panelScenesWidth + ecart)/2 + (int)((ecart + defaultWidth) * (i - nbActiveScenes/2.0)) + decalage, activePbPosY)); 
      } 
      return ret; 
     } 

     private void UpdateScenesPos() { 
      for(int i = 0; i < activeScenes.Count; i++) { 
       activeScenes[i].Location = activeScenesPos[activeScenes.Count - 1][i]; 
      } 
     } 

     private void OnMouseEnter(object sender, EventArgs e) { 
      BackColor = Color.LightYellow; 
      Cursor = Cursors.Hand; 
     } 

     private void OnMouseDown(object sender, MouseEventArgs e) { 
      BorderStyle = BorderStyle.Fixed3D; 
     } 

     private void OnMouseUp(object sender, MouseEventArgs e) { 
      if (!scenesPos.ContainsKey(Name)) { 
       // Si ce n'est pas déjà fait, on stocke la position initiale de notre PictureBox 
       scenesPos.Add(Name, Location); 
       // Et on crée un Panel vide sous elle 
       Panel panel = new Panel(); 
       panel.Location = Location; 
       panel.Size = Size; 
       panel.BorderStyle = BorderStyle.Fixed3D; 
       // On ajoute notre panel à notre form 
       Form1.AddInSeance(panel); 
      } 
      if (!isActive) { 
       activeScenes.Add(this); 
      } else { 
       Location = scenesPos[Name]; 
       activeScenes.Remove(this); 
      } 
      isActive = !isActive; 
      UpdateScenesPos(); 
     } 

     private void OnMouseLeave(object sender, EventArgs e) { 
      BorderStyle = BorderStyle.FixedSingle; 
      BackColor = Color.Transparent; 
     } 
    } 
} 

J'utilise la même méthode que précédemment, et f ou une raison inconnue, maintenant cela fonctionne. Merci à vous tous pour m'aider :)

+0

J'ai écrit un « bonjour tout le monde » au-dessus de mon message, mais il semble qu'il a été coupé quand je poste pour certains raison étrange, même lorsque je l'ai édité, alors ne soyez pas impoli :) –

+0

pouvez-vous s'il vous plaît fournir plus de code pour montrer quels événements vous avez assigné à vos gestionnaires? –

+0

Peut-être que cela a à voir avec certaines parties focales. – kevintjuh93

Répondre

1

Je vais éviter de déplacer le PictureBox. Clairement, votre bug vient de ça.

Lorsque vous déplacez le composant, la souris n'y est plus mais son statut n'est pas mis à jour.

Vous pouvez nager au fond de the windows form reference code ou vous pouvez simplement vous avez dit N petit aperçu (les images sur la ligne de fond) et un grand aperçu (celui du haut).

Créez une zone d'image N + 1 et ne la modifiez pas. Il suffit de changer leur image property.

Lorsqu'un petit aperçu est cliqué, changez sa propriété d'image avec le grand aperçu.

En outre, un bon MVC pattern est recommandé.

+0

Oui, je vais essayer ça et je reviens quand je l'ai fait fonctionner, merci! –

4

Le problème est que lorsque vous déplacez le PictureBox, il ne recevra pas l'événement de quitter la souris. Vous l'avez peut-être déjà remarqué, c'est pourquoi vous avez également défini le BackColor dans l'événement Move.

Après avoir déplacé le contrôle, il ne recevra pas de seconde MouseEnter lorsque vous le survolez à nouveau, uniquement après avoir déplacé et réactivé la souris.

Essayez d'envoyer un événement de congé de la souris manuellement (je ne l'ai pas testé):

private const int WM_MOUSELEAVE = 0x02A3; 

[DllImport("user32.dll")] 
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 

private void pictureBoxMouseUp(object sender, MouseEventArgs e) 
{ 
    // move the PictureBox... 

    SendMessage(((PictureBox)sender).Handle, WM_MOUSELEAVE, IntPtr.Zero, IntPtr.Zero); 
} 
+0

Vous avez raison, j'ai remarqué que MouseLeave n'a pas été élevé et c'est pourquoi j'ai utilisé Move event;) Merci pour ça, j'ai essayé mais ça n'a rien changé ... Mais on est peut-être proche de la solution! –

+0

Peut-être que vous devriez l'utiliser avec le 'TrackMouseEvent': https://msdn.microsoft.com/en-us/library/ms646265%28VS.85%29.aspx Ceci est un événement one shot, il doit donc être appelé à nouveau après un événement est géré afin de recevoir des événements futurs. Voir le bas de la page liée pour l'utilisation de C#. – taffer

+0

Je cherche et je cherche mais je ne peux pas le faire fonctionner ... Le code donné au bas de la page me donne des erreurs que je ne comprends pas, et la solution semble super-lourde pour un petit problème comme le mien –