0

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");
    }
}
TaW
  • 53,122
  • 8
  • 69
  • 111
Corey
  • 835
  • 1
  • 9
  • 32
  • When the mouse leaves the picturebox, do you reset the `formOpen` back to `false`? – Michel de Nijs Feb 12 '15 at 21:32
  • Yes, that way it's not continually opening forms as you hover the image. – Corey Feb 12 '15 at 21:34
  • Not sure why you are using a 2nd form in the fist place. but the problems seem to come from topmost by default stealing the focus. See [Hans' answer here for a possible solution](http://stackoverflow.com/questions/3729899/opening-a-winform-with-topmost-true-but-not-having-it-steal-focus) – TaW Feb 12 '15 at 21:37
  • I don't really know what I'm doing, I'm just beginning to program applications. Would you suggest another means of showing a larger view of an image, outside or hovering over the form? – Corey Feb 12 '15 at 21:40
  • @TaW A second form is necessary because this will allow the enlarged view to go outside of the parent form. – Setsu Feb 12 '15 at 22:00
  • Ah, @Setsu, that would make sense..then I guess Hans' trick should be tested.. – TaW Feb 12 '15 at 22:05
  • @TaW I would recommend going with RenniePet's method of overriding `CreateParams` as well. When I played with this I found that overriding `ShowWithoutActivation` was not enough because of the weird behavior of `TopMost`. – Setsu Feb 12 '15 at 22:14
  • Either that or do without `TopMost` . `Show` will bring it up anyway and `Focus` will set the focus back to the main form, so I don't think `TopMost` is needed at all. – TaW Feb 12 '15 at 22:41

2 Answers2

2

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();
}
TaW
  • 53,122
  • 8
  • 69
  • 111
  • BTW the new form should be placed at an offset rather than directly where the mouse is. I ran into this problem before where 1) Mouse moves to the right 2) Mouse enters second form before it could be repositioned 3) Form no longer moves because mouse is now in child form – Setsu Feb 12 '15 at 22:29
  • This solution actually works pretty well, but can have tearing depending on what the OP wants to show. Setting the form to be double-buffered will make for a better user-experience, but would require implementing a separate form class. – Setsu Feb 12 '15 at 22:53
  • _would require implementing a separate form class._ Which would not be a problem, imo. A cleaner way to code, but it is up to the OP to make that change.. – TaW Feb 12 '15 at 22:57
  • @Taw Would you be able to set me in the right direction for implementing double-buffering? (Useful code or links) – Corey Feb 13 '15 at 13:58
  • It is really very simple: Instead of creating the form in the code above you create the form in the designer. Call it Form2 (or something more helpful!!) This way it is automatically a class of its own. Set __all__ the properties you set in the code above in the property editor and in addition you also set its `doublebuffered` property to true. - The creation code above is thus simplified to `if (form == null) { form = new Form2();this.AddOwnedForm(form); }` - Done. – TaW Feb 13 '15 at 14:03
  • Thank you. Give a man a fish, feed him for a day. Teach a man to fish, he will never go hungry. – Corey Feb 13 '15 at 15:37
0

MouseHover = Occurs when the mouse pointer rests on the control. (msdn)

Try MouseMove instead.

meica
  • 123
  • 1
  • 5
  • I tried MouseMove as well, the same problem seems to occur. That being once the other Form opens the application isn't able to detect the movement of the mouse or the location of what the bounds are. – Corey Feb 12 '15 at 21:45
  • The Location of the second form is set only if it is created, write this Line after the if, so that it is done every time the mouse is moving – meica Feb 12 '15 at 21:54