3

I was building a simple form with one simple effect- opacity reduced when mouse is not over the form, and form becomes opaque when mouse is over it. I am currently encountering couple of difficulties:-

  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.

Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
vish213
  • 748
  • 3
  • 12
  • 27
  • I don't know why is it displaying my 2nd point(starting from "If the mouse is NOT" as 1st point again. I have tried editing,its labelled number 2. there. Anyways... – vish213 Sep 23 '12 at 13:53
  • You need to leave a blank line before the beginning of a numbered list. Since Markdown does not let you start a numbered list at 2, it starts your list at 1 there. I have fixed it for you. – Kevin Panko Oct 29 '14 at 19:46

4 Answers4

8

The MouseEnter/Leave events are too unreliable to do this. Best thing to do is just use a Timer that checks if the mouse is still inside the window. Drop a Timer on the form and make the code look like this:

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

Btw: avoid increasing the Opacity to 1.0, that forces the native window to be recreated and that can have a lot of side-effects. Using 0.99 is best.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
6

I might be wrong, but why would you use MouseHover event? MouseHover detects when the mouse stop moving on the form and is usually used to show Tooltips.

The event you are looking for is MouseEnter which is the opposite of MouseLeave and detects when the mouse enters the client rect of a window.

In the Leave event, just check if the cursor position is in the window client rect to know if it did actually leave the form or if it is just on top of child control.

Ofc if you use a region, you'll have to adapt the code.

 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;
        }
    }
Samy Arous
  • 6,794
  • 13
  • 20
  • I forgot to mention I tried MouseHover as a change for MouseEnter itself,thinking this might be the problem why form is losing opacity when it goes between richtextbox and form( you always start experimenting stupid things when usual ones are not working :-D) – vish213 Sep 23 '12 at 13:50
  • Its still losing opacity whenever mouse goes in the fine gap between richtextbox and Form boundry. Also, the form does not become opaque when I take the mouse on title bar. What gives? – vish213 Sep 23 '12 at 14:00
  • Yup. Its was not working as expected. I thought I am not understanding something. – vish213 Sep 23 '12 at 14:06
  • Code updated. The error came from the fact that Cursor.Position returns the mouse position in screen coordinate which have to be converted first. As for the title bar, the LeaveEvent only fire when the mouse is in the client rectangle, which exclude the title bar. You can fix this but this will require another API heavy approach. Or you can use a hack by extending the client rectangle by 5 px on top. Won't work everytime though. – Samy Arous Sep 23 '12 at 14:18
1

Add a timer control then use below in timer's tick event. Above answers won't work if you have custom/user controls in your form. So have to use ClientRectangle

this.Opacity = this.ClientRectangle.Contains(this.PointToClient(Cursor.Position)) ? 0.99 : 0.20;
PUG
  • 4,301
  • 13
  • 73
  • 115
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;
}
Baz
  • 36,440
  • 11
  • 68
  • 94
Afshin
  • 4,197
  • 3
  • 25
  • 34
  • Thanks but There isn't any problem with EventHandlers. The Second problem(solved by Icfseth) was related to WHEN event is fired. First one is still pending. – vish213 Sep 23 '12 at 13:56