C# how to show a form at a specific mouse position on the screen?

feedwall picture feedwall · Jul 19, 2012 · Viewed 18.5k times · Source

I have two Forms, my main form is Form1 and my secondary form shown on demand as a dialog is Form2. Now if I call Form2 it shows always up in the upper left corner on my screen. First time I thought my form isn't there at all, but then I saw it hanging in the upper screen corner. I would like to show my form at the current mouse position where the user clicks a context menu to show up the modal dialog. I have already tried different things and searched for code samples. But I found nothing besides thousand of different codes on how to get the actual mouse position in different ways which I already know. But this position is anyway always relative to the screen, the main form, the control or whatever the current context is. Here my code (the desktop positioning which I also tried doesn't work and center-to-screen centers the form only, so I left the property to Windows.Default.Position):

        Form2 frm2 = new Form2();
        frm2.textBox1.Text = listView1.ToString();
        frm2.textBox1.Tag = RenameFile;
        DialogResult dlgres=frm2.ShowDialog(this);
        frm2.SetDesktopLocation(Cursor.Position.X, Cursor.Position.Y);

Answer

Mike Dinescu picture Mike Dinescu · Jul 19, 2012

Your problem is that your first call: frm2.ShowDialog(this); and then call frm2.SetDesktopLocation which in fact only gets called after the form (frm2) has already closed.

ShowDialog is a blocking call - meaning that it returns only when the form your are calling ShowDialog on closes. So you will need a different approach to setting the form position.

Probably the easiest way to accomplish that would be to create a second constructor on your Form2 (that you want positioned) which takes two parameters, for the X and Y coordinates.

public class Form2
{

    // add this code after the class' default constructor

    private int desiredStartLocationX;
    private int desiredStartLocationY;

    public Form2(int x, int y)
           : this()
    {
        // here store the value for x & y into instance variables
        this.desiredStartLocationX = x;
        this.desiredStartLocationY = y;

        Load += new EventHandler(Form2_Load);
    }

    private void Form2_Load(object sender, System.EventArgs e)
    {
        this.SetDesktopLocation(desiredStartLocationX, desiredStartLocationY);
    }

Then, when you create the form to display it, use this constructor instead of the default one:

Form2 frm2 = new Form2(Cursor.Position.X, Cursor.Position.Y);
frm2.textBox1.Text = listView1.ToString();
frm2.textBox1.Tag = RenameFile;
DialogResult dlgres=frm2.ShowDialog(this);

You can also try using this.Move(...)' instead of 'this.SetDesktopLocation in the Load handler.