DirectInput - Mouse coordinates problem.

wyrd

Senior Contributor
Joined
Aug 23, 2002
Messages
1,405
Location
California
I'm having trouble getting the correct coordinates from a mouse device. It displays mostly 0s and a few negative numbers when I move the mouse around. :confused:

Here's my mouse initialization;

C#:
		/// <summary>
		/// Instantiates a new Mouse for the specified window.
		/// </summary>
		/// <param name="window">Window to obtain mouse input for.</param>
		public Mouse(Control window)
		{
			// Store window.
			_window = window;

			// Get mouse device.
			_device = new Device(SystemGuid.Mouse);
	
			_device.SetDataFormat(DeviceDataFormat.Mouse);
			_device.SetCooperativeLevel(_window, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground);

			// Try to acquire mouse access.
			_acquireMouse();
		}

And this is the method where I retrieve mouse coordinate info (note MouseAxis is just an enum that describes X, Y and Z);

C#:
		/// <summary>
		/// Gets mouse coordinates for the specified axis.
		/// </summary>
		/// <param name="axis">Axis to retrieve coordinates for.</param></param>
		/// <returns>Coordinates for the specified axis, or 0 on failure.</returns>
		private int _getMouseCoordinates(MouseAxis axis) 
		{
			try {
				// Get mouse state.
				MouseState state = _device.CurrentMouseState;
				
				// Retrieve mouse coordinate info.
				switch(axis) {
					case MouseAxis.X:
						return state.X;

					case MouseAxis.Y:
						return state.Y;

					case MouseAxis.Z:
						return state.Z;

					default:
						// No other axis.
						break;
				}
			}
			catch {
				// Lost access to mouse.
				_acquireMouse();
			}

			// Couldn't retrieve mouse information, return error.
			return 0;
		}

I'm totally baffled by this. :(
 
I found out that the X, Y and Z are related to how far the mouse has moved since the last call to CurrentMouseState. Now isn't that convenient? (Note: Sarcasm).

I've got it semi-working I guess. I keep track of the X, Y and Z via int variables and just increment them based on what the CurrentMouseState returns.

The problem now is;
- Z still isn't working.
- Y still isn't working.
- How can I get or set the initial coordinates of the mouse or the ACTUAL x,y position?

EDIT:
Nevermind, I know why Y and Z aren't working. I guess the only thing I need to know now is how to set the initial mouse position or get the actual x,y coordinates.
 
I was thinking of just using the Cursor object to retrieve the exact position of the cursor over the screen or window (in windowed mode). It's certainly make my life a lot easier... but then I wouldn't be able to keep track of the wheel.

Thoughts?
 
WOOT! Finally. Yeesh.

I tried doing it by updating myself with the X and Y from the mouse (every little bit of efficiency helps), but it was majorly flawed and writing code to check accuracy would of been a waste of time. So in the end I ended up using the Cursor object to retrieve the mouse coordinates.

I also needed a way to get the wheel info, which proved a task in itself, because once you call GetMouseState, it resets the wheel info.. so if I retrieved button information, then wheel information, wheel would always return 0. :(

I thought about using a thread which would just update the mouse info by itself, and then call events when a button is clicked, etc. But at that point I might as well be using the provided mouse handling events inside .NET.

After much debate and banging my head against the wall, I decided to make a MouseInfo property, which returns a MouseInfo object that contains the information I need. If the mouse isn't acquired, it returns null. I've done quite a few tests, and so far it works.

*pats self on back* I have yet to see a tutorial which covers mouse handling of the wheel and screen coordinates, so I'm quite happy that I figured all this out.

For those who may have similar troubles, here's the code;

MouseEnums
C#:
using System;

namespace GameUtil
{
	public enum DIWheelDirections { Up, Down, Idle }
	public enum DIMouseButtons { Left, Right, Wheel }
	public enum DIMouseClicked { False }
}

Mouse
C#:
using System;
using System.Windows.Forms;
using System.Drawing;
using Microsoft.DirectX.DirectInput;

namespace GameUtil
{
	/// <summary>
	/// Responsible for mouse device.
	/// </summary>
	public class Mouse
		: IDisposable
	{
		#region Member Variables

		Device _device = null;
		Control _window = null;

		private bool _disposed = false;

		#endregion

		#region Constructor

		/// <summary>
		/// Instantiates a new Mouse for the specified window.
		/// </summary>
		/// <param name="window">Window to obtain mouse input for.</param>
		public Mouse(Control window)
		{
			// Store window.
			_window = window;

			// Get mouse device.
			_device = new Device(SystemGuid.Mouse);
	
			_device.SetDataFormat(DeviceDataFormat.Mouse);
			_device.SetCooperativeLevel(_window, 
				CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground);

			// Try to acquire mouse access.
			_acquireMouse();
		}

		#endregion

		#region Dispose And Destructor

		/// <summary>
		/// Dispose of this Mouse.
		/// </summary>
		public void Dispose() 
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Dispose of this Mouse.
		/// </summary>
		/// <param name="disposing">Set to true if disposing.</param>
		protected void Dispose(bool disposing) 
		{
			// Check if already disposed.
			if (_disposed) {
				return;
			}

			if (disposing) {
				// Cleanup managed resources.
				_device.Unacquire();
				_device.Dispose();
			}

			// Mouse is now disposed of.
			_disposed = true;
		}

		/// <summary>
		/// Destroys this Mouse.
		/// </summary>
		~Mouse() 
		{
			this.Dispose(false);
		}

		#endregion

		#region Helper Methods

		/// <summary>
		/// Attempts to acquire access to the mouse.
		/// </summary>
		private void _acquireMouse() 
		{
			try {
				_device.Acquire();
			}
			catch (Exception) {
				// Ignore errors.
			}
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets the information of this Mouses current state.
		/// </summary>
		public MouseInfo MouseInfo 
		{
			get {
				try {
					return new MouseInfo(this);
				}
				catch (Exception) {
					// Lost access to mouse.
					_acquireMouse();
				}

				// No info found.
				return null;
			}
		}

		/// <summary>
		/// Gets the Device for this Mouse.
		/// </summary>
		public Device Device 
		{
			get {
				return _device;
			}
		}

		/// <summary>
		/// Gets the control this Mouse is accessing input for.
		/// </summary>
		public Control Window 
		{
			get {
				return _window;
			}
		}

		#endregion
	}
}

MouseInfo
C#:
using System;
using System.Windows.Forms;
using System.Drawing;
using Microsoft.DirectX.DirectInput;

namespace GameUtil
{
	/// <summary>
	/// Mouse information.
	/// </summary>
	internal class MouseInfo
	{
		#region Member Variables

		private bool[] _buttons = { false, false, false };

		private Point _position = Point.Empty;
		private int _wheelMovement = 0;
		private DIWheelDirections _wheelDirection = DIWheelDirections.Idle;

		#endregion

		#region Constructors

		/// <summary>
		/// Instantiates a new MouseInfo object based off of a Mouse.
		/// </summary>
		/// <param name="mouse">Mouse to get information from.</param>
		internal MouseInfo(Mouse mouse) 
		{
			// Get mouse state.
			MouseState state = mouse.Device.CurrentMouseState;	

			_setButtons(state.GetMouseButtons());
			_position = mouse.Window.PointToClient(Cursor.Position);
			_setWheel(state.Z);
		}

		#endregion

		#region Helper Methods

		/// <summary>
		/// Sets mouse button information.
		/// </summary>
		/// <param name="buttonState">Array of button states.</param>
		private void _setButtons(byte[] buttonState) 
		{
			// Set each button based off its state.
			for (DIMouseButtons button = DIMouseButtons.Left; button <= DIMouseButtons.Wheel; button = button + 1) {
				if (buttonState[(int) button] == (int) DIMouseClicked.False) {
					_buttons[(int) button] = false;
				}
				else {
					_buttons[(int) button] = true;
				}
			}
		}

		/// <summary>
		/// Sets the wheel direction and movement.
		/// </summary>
		/// <param name="amount">Amount the wheel has moved.</param>
		private void _setWheel(int amount) 
		{
			// Set amount moved.
			_wheelMovement = amount;

			// Check if wheel was moved up.
			if (_wheelMovement > 0) {
				_wheelDirection = DIWheelDirections.Up;
			}
				// Check if wheel was moved down.
			else if (_wheelMovement < 0) {
				_wheelDirection = DIWheelDirections.Down;
			}
				// Wheel is idle.
			else {
				_wheelDirection = DIWheelDirections.Idle;
			}
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets whether the left button is clicked.
		/// </summary>
		public bool LeftClick 
		{
			get {
				return _buttons[(int) DIMouseButtons.Left];
			}
		}

		/// <summary>
		/// Gets or sets whether the right button is clicked.
		/// </summary>
		public bool RightClick 
		{
			get {
				return _buttons[(int) DIMouseButtons.Right];
			}
		}

		/// <summary>
		/// Gets whether the wheel button is clicked.
		/// </summary>
		public bool WheelClick 
		{
			get {
				return _buttons[(int) DIMouseButtons.Wheel];
			}
		}

		/// <summary>
		/// Gets XCoordinates of mouses cursor.
		/// </summary>
		public int X 
		{
			get {
				return _position.X;
			}
		}

		/// <summary>
		/// Gets or sets YCoordinates of mouses cursor.
		/// </summary>
		public int Y 
		{
			get {
				return _position.Y;
			}
		}

		/// <summary>
		/// Gets the amount the mouse wheel was moved.
		/// </summary>
		public int WheelMovement 
		{
			get {
				return _wheelMovement;
			}
		}

		/// <summary>
		/// Gets the direction the mouse wheel was moved in.
		/// </summary>
		public DIWheelDirections WheelDirection 
		{
			get {
				return _wheelDirection;
			}
		}

		#endregion
	}
}

Example:
C#:
Mouse mouse = new Mouse(this);
MouseInfo mouseInfo = null;

// Game loop.
while (_running) {
   mouseInfo = mouse.MouseInfo;
   if (mouseInfo != null) {
      // mouseInfo.LeftClick etc...
      // ...
   }
}
 
Last edited:
Back
Top