One of the annoying things with XNA, happens when handling mouse clicks. If you’ve ever worked on an XNA windows game (note: this only really applies to a windows game) in windowed mode and tried switching applications, you may have noticed that XNA still captures the clicks even when the window is not active! It also reports the mouse position when it’s outside of the window which can cause more issues in and of itself. Unfortunately, the fix for the first problem doesn’t work if you’re using multiple forms in the same application.

So, we have three issues:

  • XNA captures clicks while the game is not active (i.e. from other applications)
  • and it reports the mouse position when it’s outside of the viewable area
  • and the fix for the first item above doesn’t work when you have multiple forms in your application.

Fortunately, there’s an easy way to resolve these! “Great!”, you say, “now how do I do it?”. Click on, my friend.

Ok, let’s start out in our Update statement with a basic mouse click check:

Ok, so we’ve got it checking to make sure that during the last Update call, the the left mouse button was in a state of Released and now it’s in a state of Pressed. That’s great, but this allows you to click in other applications or even off-screen and the code inside our if statement will still be executed!

Active or not Active? That is the question.

First, let’s tackle the issue of the game capturing clicks while it’s not active (when another application has focus). There is an easy solution to this: use the Microsoft.Xna.Framework.Game’s IsActive property. This property is true when the game application has focus and is false otherwise. Our main game class should be derived from Game, so all we have to do is add “&& this.IsActive” into our if statement like so:

There is one caveat with this method and that is that when you run the application “IsActive” is set to true no matter what. So, if you run the game and quickly switch to another application, when the game finished loading it will think it’s active (IsActive == true). Be aware of this since it could cause unexpected behaviour.

A Click Too Far

Ok, so now we’ve (more or less) established that the click happened while our game was active, but we still have the problem that if our game is in window mode, clicks can be captured off of the drawing area. All we have to do here, is make sure that the mouse’s X/Y coordinates are within the drawing surface by checking them against the graphics buffer’s (essentially, the window’s) width and height. You can do this like so:

So, we check to make sure that the mouse X/Y coordinates are above 0 and that they’re below the backbuffer width and height, respectively.

Which one is which?

For most games, this should be enough. However, in my case, I am making a map editor which uses a windows Form for the controls and the Game window for drawing the tile engine. I noticed while working on it on my netbook, which doesn’t have a lot of screen real-estate, that when I would click on the controls form while it was over the game window, it would click through. This got really annoying because when I’d switch a tile in the controls form, it would draw the tile in the game form.

So, after some searching for different ideas, I managed to figure out a way to do this pretty easily using System.Windows.Forms.Form’s ActiveForm property. This property “Gets the currently active form for this application.” (MSDN) Using this, we can just add a quick check to see if the game form is active within the application. I do this by checking to see if the active form’s Text property is equal to the game’s Window.Title property because it’s generic enough for this tutorial, but you can use something else such as checking the object Types. I should also mention that obviously doing it this way requires your game’s Window.Title to be different from your other forms’ Text property values. Ok, on to the code:

Just a note: the reason I fill out the namespaces rather than adding a using statement is because if you add using System.Windows.Forms, you’ll get conflicts with other variables because the namespaces have overlapping class names. It’s just easier to do it this way.

So, that’s how I check to see if clicks are being handled properly. It takes into account whether the form is active, whether the mouse is within the screen and even whether the form itself is active within the application. I hope this helped you. Please drop a comment if you have any questions or remarks!