鼠标悬停和鼠标离开事件的控制

3

我正在构建一个简单的表单,其中有一个简单的效果-当鼠标不在表单上时,透明度降低,当鼠标悬停在表单上时,表单变为不透明。我目前遇到了一些困难:

  1. Firstly, I did this-

     this.MouseHover += new EventHandler(Form1_MouseHover);
     this.MouseLeave += new EventHandler(Form1_MouseLeave);
    

    But I had 1 richtextbox in form too, and as mouse went over it, the form lost opacity again. I had to add this too:-

     richTextBox1.MouseHover+=new EventHandler(Form1_MouseHover);
     richTextBox1.MouseLeave+=new EventHandler(Form1_MouseLeave);
    

    wondering if there was any better way,because there is still some gap between richtextbox and form boundaries, and form is losing opacity when mouse cursor goes there.

  2. If the mouse is NOT over the form (suppose initially), the form is less opaque. Now, I want form to become opaque as soon as mouse goes over it, but it only happens when mouse movement over form stops completely. If I keep moving mouse over the form, it does not become opaque. Is this a problem with the way events are stored in message queue and all that or will I be able to do something, because I have seen applications with the effect I am trying to implement.


我不知道为什么它又显示了我的第二点(从“如果鼠标不是”开始的点,又变成了第一个点)。我已经尝试过编辑,但是它在那里被标记为2号。无论如何... - vish213
在开始一个编号列表之前,您需要留出一行空白。由于Markdown不允许您从2开始编号列表,因此它会从1开始。我已经为您修复了这个问题。 - Kevin Panko
4个回答

8
鼠标进入/离开事件太不可靠了,无法实现此操作。最好的方法是使用一个计时器来检查鼠标是否仍在窗口内。将计时器拖到窗体上,并将代码编写成下面这样:
public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        this.Opacity = 0.99;
        timer1.Interval = 200;
        timer1.Enabled = true;
        timer1.Tick += timer1_Tick;
    }
    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
        timer1_Tick(this, e);
    }
    private void timer1_Tick(object sender, EventArgs e) {
        this.Opacity = this.Bounds.Contains(this.PointToClient(Cursor.Position)) ? 0.99 : 0.20;
    }
}

顺便提一下:避免将不透明度增加到1.0,这会强制重新创建本机窗口,可能会产生很多副作用。使用0.99最好。


进入/离开事件为什么不可靠? - Kyle Baran
一个好的答案无法适应评论框,您必须单击"提问"按钮。 - Hans Passant
他发布了他的问题:https://dev59.com/6oTba4cB1Zd3GeqP97Zh - Lasse V. Karlsen
请参见Pug的答案,他建议使用ClientRectangle而不是Bounds - ToolmakerSteve

6
我可能错了,但是为什么要使用MouseHover事件? MouseHover 检测鼠标停留在窗体上的时间,并通常用于显示工具提示。
你需要的事件是 MouseEnter,它是 MouseLeave 的相反事件,用于检测鼠标进入窗口客户端区域。
在Leave事件中,只需检查光标位置是否在窗口客户端区域内,即可知道它是否实际离开了窗体,还是只停留在子控件上。
当然,如果使用了Region,则需要调整代码。
 private void Form1_MouseEnter(object sender, EventArgs e)
    {
        this.Opacity = 1;
    }

    private void Form1_MouseLeave(object sender, EventArgs e)
    {

        if (!this.ClientRectangle.Contains(this.PointToClient(Cursor.Position)))
        {
            this.Opacity = 0.5;
        }
    }

我忘了提到我尝试将MouseHover作为MouseEnter本身的更改,认为这可能是当窗体在richtextbox和form之间移动时失去不透明度的问题所在(当通常的方法不起作用时,你总是开始尝试愚蠢的事情 :-D)。 - vish213
每当鼠标进入RichTextBox和窗体边界之间的细小间隙时,它仍然会失去不透明度。而且,当我将鼠标放在标题栏上时,窗体并没有变得不透明。这是怎么回事? - vish213
是的,它没有按预期工作。我以为自己没有理解到什么。 - vish213
代码已更新。错误是由于Cursor.Position返回屏幕坐标中的鼠标位置,需要先进行转换。至于标题栏,LeaveEvent仅在鼠标位于客户端矩形内时触发,不包括标题栏。您可以修复此问题,但这将需要另一种API重型方法。或者您可以通过在顶部将客户端矩形扩展5像素来使用hack。但并非每次都有效。 - Samy Arous

1
在窗体中添加计时器控件,然后在计时器的Tick事件中使用以下内容。如果您的窗体中有自定义/用户控件,则上述答案将无效。因此必须使用ClientRectangle
this.Opacity = this.ClientRectangle.Contains(this.PointToClient(Cursor.Position)) ? 0.99 : 0.20;

0
private void Form1_MouseEnter(object sender, EventArgs e)
{
    this.Opacity = 1.0;
}

private void Form1_MouseLeave(object sender, EventArgs e)
{ 
    this.Opacity = 0.8;
}

谢谢,但是EventHandlers没有任何问题。第二个问题(由Icfseth解决)与WHEN事件触发有关。第一个问题仍然未解决。 - vish213

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接