Search code examples
c#formscursormouseleavemousehover

MouseLeave detection not working with ImageForm


I've got a smaller image in my form. When the user hovers over the image it brings up a larger view of the image (that follows the mouse, but stays a certain distance from the mouse). In order to do this I am generating a Form with no FormBorderStyles when the cursor hovers the image.

The problem I'm running into is that the first form doesn't seem to detect any longer that the mouse is hovering or leaving the PictureBox once the form activates. The Form also doesn't follow the cursor.

Here is the slimmed down version of what I've got:

C#

    bool formOpen = false;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        pictureBox1.MouseHover += pictureBox1_MouseHover;
        pictureBox1.MouseLeave +=pictureBox1_MouseLeave;
    }

    void pictureBox1_MouseHover(object sender, EventArgs e)
    {
        if (formOpen == false)
        {
            Form form = new Form();
            form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            form.BackColor = Color.Orchid;
            //Show the form
            form.Show();
            form.Name = "imageForm";
            this.AddOwnedForm(form);

            //Set event handler for when the mouse leaves the image area.
            //form.MouseLeave += form_MouseLeave;
            //Set the location of the form and size
            form.BackColor = Color.Black;
            form.Dock = DockStyle.Fill;
            form.Size = new Size(30, 30);
            form.BackgroundImageLayout = ImageLayout.Center;
            this.TopMost = true;
            formOpen = true;

            form.Location = new Point(Cursor.Position.X, Cursor.Position.Y);
        }
    }


    private void pictureBox1_MouseLeave(object sender, EventArgs e)
    {
        //MessageBox.Show("Worked");
    }
}

Solution

  • The MouseLeave (and other events) was not recognized because the opening of the popup window and especially making it topmost=true took away the focus from the original form and its PictureBox.

    It also didn't move because not code for moving was provided..

    Here are a few changes that will make the form move:

    • You need a reference to it at the form1 level
    • you need to move it in the MouseMove event

    Note that Hover is a once-only type of event. It fires only once until you leave the control.. (Note: Setsu has switched from Hover to Enter. This works fine, but lacks the short delay before showing the 2nd Form. If you want that back you can either switch back to Hover or you can fake the hover delay by a Timer, which is what I often do.)

    // class level variable 
    Form form;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        pictureBox1.MouseEnter += pictureBox1_MouseEnter;
        pictureBox1.MouseLeave +=pictureBox1_MouseLeave;
        pictureBox1.MouseMove += pictureBox1_MouseMove;  // here we move the form..
    }
    
    // .. with a little offset. The exact numbers depend on the cursor shape
    void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if ((form != null) && form.Visible)
        {
            form.Location = new Point(Cursor.Position.X + 5, Cursor.Position.Y + 5);
        }
    }
    
    void pictureBox1_MouseEnter(object sender, EventArgs e)
    {
        // we create it only once. Could also be done at startup!
        if (form == null)
        {
             form = new Form();
             form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
             //form.BackColor = Color.Orchid;
             form.Name = "imageForm";
             this.AddOwnedForm(form);
             form.BackColor = Color.Black;
             form.Dock = DockStyle.Fill;
             form.Size = new Size(30, 30);
             form.BackgroundImageLayout = ImageLayout.Center;
             //this.TopMost = true;  // wrong! this will steal the focus!!
             form.ShowInTaskbar = false;
        }
        // later we only show and update it..
        form.Show();
        form.Location = new Point(Cursor.Position.X + 5, Cursor.Position.Y + 5);
        // we want the Focus to be on the main form!
        Focus();
    }
    
    private void pictureBox1_MouseLeave(object sender, EventArgs e)
    {
        if (form!= null) form.Hide();
    }