草庐IT

c# - 控件移动后 Windows 窗体 MouseEnter 不触发

coder 2024-06-16 原文

我想在鼠标进入时为 PictureBoxBackColor 属性着色。

MouseEnter 事件触发时,我将 BackColor 变为黄色,并在 MouseLeave 中重置为透明。

然后当我点击一个 PictureBox 时,我改变了它的位置,所以我也有一个 Move 事件将它重置为透明。

问题是,一旦我移动它,我需要用鼠标输入 PictureBox 两次以触发 MouseEnter 事件!

这是一个非常图形化的问题,所以我上传了一点video向您展示正在发生的事情,它肯定会比我更好地解释我的问题。

我尝试了另一种方法,不是在 MouseEnter 中而是在 MouseHover 中更改颜色。在这种情况下,它运行良好,除了我在触发 Move 事件之前有 500 毫秒的延迟,这显然不是我想要的。

我现在没有可行的解决方案。

对于代码来说,很简单,目前我有:

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);
}

关于c# - 控件移动后 Windows 窗体 MouseEnter 不触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32559891/

有关c# - 控件移动后 Windows 窗体 MouseEnter 不触发的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  5. ruby-on-rails - 如何在 Rails Controller Action 上触发 Facebook 像素 - 2

    我有一个ruby​​onrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  8. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  9. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  10. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

随机推荐