当鼠标input时,我想为PictureBox
的BackColor
属性着色。
当MouseEnter
事件触发时,我将BackColor
变成黄色,并在MouseLeave
重置为透明。
然后,当我点击一个PictureBox
,我改变了它的位置,所以我也有一个Move
事件,它重置它透明。
问题是,一旦我移动它,我需要用鼠标两次inputPictureBox
来触发MouseEnter事件!
这是一个非常graphics化的问题,所以我上传了一个小video ,告诉你发生了什么,它肯定会比我更好地解释我的问题。
我试过另一种方式,改变颜色不是在MouseEnter
而是在MouseHover
。 在这种情况下,它运行良好,除了在发生Move事件之前有500毫秒的延迟,这显然不是我想要的。
我现在没有可行的解决scheme。
对于代码,这是非常简单的,现在我有:
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; }
在Designer.cs中,每个PictureBox的事件都是这样的:
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);
编辑:要回答我的问题,这是我现在使用的代码:(评论是法语)
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; } } }
我使用和以前一样的方法,并且由于一个未知的原因,现在它可以工作。 感谢大家帮助我:)
问题是当您重新定位PictureBox
,它将不会收到鼠标离开事件。 也许你已经注意到了,这就是为什么在Move
事件中设置BackColor
的原因。
移动控件后,只有在将鼠标移开并重新打开之后,再次将其悬停时,才会再次收到MouseEnter
。
尝试手动发送鼠标离开事件(我还没有测试过):
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); }
我将避免移动PictureBox
。 显然你的错误来自于此。
移动组件时,鼠标不在其中,但状态不会更新。
你可以在窗体参考代码中游得很深,或者你可以说你有N个小预览(底线上的图片)和一个大预览(上图)。
创建N + 1图片框,不要更改它。 只要改变他们的图像属性 。
当点击一个小预览,切换它的图像属性与大预览。
另外,推荐一个好的MVC模式 。