1
\$\begingroup\$

I'm looking for some help figuring out the current position of the Monogame windowed form. My ultimate goal is to figure out when the user is clicking inside of the game window and where they're clicking.
Getting the mouse position is easy:

var mouseState = OpenTK.Input.Mouse.GetState();
var mousePosition = new Point(mouseState.X, mouseState.Y);

That returns a Point relative to the computer's display. I'm running my app as a windowed form, so I need to compute the mouse position inside of the window based off the forms current location on the monitor.
And in reading up on the subject, it looks like this should give me the point data I need:

System.Windows.Forms.Form form = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle(this.Window.Handle);
var formPosition = new Point(form.Location.X, form.Location.Y);

Trouble is, that the object form is always coming back as a null object. this.Window.Handle will return a valid (System.IntPtr) handle ID, but the form object is never created.

While I'm stopped at a break point, I can see the data I need inside the this.Window located at ((OpenTK.NativeWindow)(((Microsoft.Xna.Framework.OpenTKGameWindow)(this.Window)).window)).Location - but that location is a non-public location so I can't get it out of there.

Any suggestions?

\$\endgroup\$
  • 1
    \$\begingroup\$ Shouldn't MonoGame's implementation of the XNA Mouse API do this already? \$\endgroup\$ – Andrew Russell Dec 11 '13 at 8:25
2
\$\begingroup\$

I think you're using the wrong Mouse.GetState() method. It appears you are using the OpenTK implementation, you should really be using the MonoGame implementation that lives in the Microsoft.Xna.Framework.Input namespace.

var mouseState = Microsoft.Xna.Framework.Input.Mouse.GetState();

// this is the position relative to the top left corner of the window.
var mousePosition = new Point(mouseState.X, mouseState.Y); 

The documentation on MSDN is pretty terrible around this, but if you read the words around the related method Mouse.SetPosition you'll notice it says "Sets the position of the mouse cursor relative to the upper-left corner of the window."

It stands to reason then, that the MouseState.X and Y are also relative to the upper-left corner of the window.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Actually, well crap. This works great unless you move the window. Then the coordinates get messed up and you start getting negative numbers or really large numbers depending on which direction you move the window. \$\endgroup\$ – EtanSivad Dec 11 '13 at 15:13
  • \$\begingroup\$ Are you calling GetState every update? You should be. \$\endgroup\$ – craftworkgames Dec 12 '13 at 5:29
  • \$\begingroup\$ Yep. In the protected override void Update(GameTime gameTime) area I'm calling Microsoft.Xna.Framework.Input.MouseState mouseWindowedState = Microsoft.Xna.Framework.Input.Mouse.GetState(); to update every time. What's happening is if I click in the upper left corner I'll get 0,0 back. But say I move the main window up and then click in the upper left it'll return 0,-200. So it seems that while the state is getting updated, the MS XNA piece doesn't realize that the window has been moved. \$\endgroup\$ – EtanSivad Dec 12 '13 at 17:17
  • \$\begingroup\$ That's weird. I tried exactly the same thing and it behaves as I expected. It's probably a bug in MonoGame, I would check that you are using the latest version (3.2). build.monogame.net/job/develop-win/lastSuccessfulBuild/artifact/… Also, if you look at the MonoGame source code, there's a number of things happening depending on the platform you are targeting. github.com/mono/MonoGame/blob/develop/MonoGame.Framework/Input/… \$\endgroup\$ – craftworkgames Dec 12 '13 at 22:42
  • \$\begingroup\$ Wait... that gave me the clue I needed to figure out what's going on. I have Game1 spawn a second thread and open a second form window. That window has a bunch of controls for running the Sprite AI and stuff like that. If I don't open that second window and have just Game1 running, the mouse behavior works even when moving the main window around. So that's problem. Haven't the foggiest how I'll fix it though. Maybe if I spawn it from Program.cs instead.... \$\endgroup\$ – EtanSivad Dec 12 '13 at 22:53
1
\$\begingroup\$

If you only need to know if the user is clicking inside the form, you wouldn't need all that code.

int width = graphics.PreferredBackBufferWidth;
int height = graphics.PreferredBackBufferHeight;

var mouseState = OpenTK.Input.Mouse.GetState();
var mousePosition = new Point(mouseState.X, mouseState.Y);

if (mousePosition.X < 0 || mousePosition.Y < 0 || mousePosition.X >= width || mousePosition.Y >= height)
{
    // Click was outside window
}
else
{
    // Click *inside* window
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ That doesn't work as OpenTK.Input.Mouse.GetState(); returns my coordinates relative to the screen not the window. I have 2 monitors (Effective resolution is 3840x1280) so when I click in the upper left corner, it returns -108: -352 since it's not in the center of my monitors. \$\endgroup\$ – EtanSivad Dec 11 '13 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.