ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!
Mouse Handling
Here kitty-kitty! It's time to catch a mouse. Actually, we're not going to catch it,
we're going to acquire it. If you've been looking for a more robust and
precise alternative to standard VB mouse handling, you've come to the right place
my feline friend!
But enough Lucky babble, lets talk DirectX. There are a few things you'll have to come
to terms with if you'd like to use DirectInput to handle your mousey:
The standard mouse cursor will disappear
You'll have to draw your own cursor
You won't be given absolute X and Y coordinates
There will be no events, you must actively poll the device
Mommy isn't here to hold your hand anymore
Still with me? Check out these initialization steps:
Dim mobjdx As New DirectX7
Dim mobjdi As DirectInput
Dim mobjdiMouse As DirectInputDevice
Set mobjdi = mobjdx.DirectInputCreate()
Set mobjdiMouse = mobjdi.CreateDevice("GUID_SysMouse")
mobjdiMouse.SetCommonDataFormat DIFORMAT_MOUSE
mobjdiMouse.SetCooperativeLevel frmMouse.hWnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE
mobjdiMouse.Acquire
Here we have initialized the DirectInput object, and then used it to create a
device. The DirectInput.CreateDevice method accepts one argument, the "GUID" of
the device we'd like to create. To access the system's standard mouse, simply pass
"GUID_SysMouse". Next, we set the data format we'll be using for the device. This tells
DirectInput how to interpret the data that it receives. Obviously, we want to interpret
the data as DIFORMAT_MOUSE. Finally, we set the cooperative level (much like DirectDraw),
and call the DirectInputDevice.Acquire method to initialize data acquisition for
the device.
It is important to note: If the Form object passed as the first parameter of the
SetCooperativeLevel method is not yet visible, the Acquire method will fail!
Be sure to call Form.Show when needed. Also, if we lose exclusivity (if some other
program takes the mouse away from us), we will have to reacquire the mouse or face the
consequences (errors)!
Once acquired, we can poll the device for input whenever we feel like:
Dim mdiMState As DIMOUSESTATE
mobjdiMouse.GetDeviceStateMouse mdiMState
DIMOUSESTATE is like a UDT for mouse data. It can contain info on the X, Y, and Z (!!!)
motion of the mouse, in addition to info on the various button states. Calling the
DirectInputDevice.GetDeviceStateMouse method fills the variable with the most
recent data received from the mouse. You may want to place some error handling code
around this call, it will fail and raise an error if we've lost exclusivity.
The info returned, as I said before, is NOT absolute. Checking the value of
mdiMState.x will NOT give you the current X-coordinate of the mouse. What it
will give you is the mouse X-displacement since the last time you checked the
mouse state. This means that you have to keep track of the mouse's position yourself:
Const MOUSE_SPEED = 2
Dim mintMouseX As Integer
mintMouseX = mintMouseX + mdiMState.x * MOUSE_SPEED
This code will add the observed X-displacement of the mouse to the current cursor
X-coordinate. Also, it multiplies the displacement by some constant, allowing us to
increase the sensitivity of motion. Do the same thing for the Y-displacement, and you've
got yourself some absolute coordinates! You should probably include some code that
checks for the edges of the screen (or form) to ensure that the cursor doesn't escape
and run amok.
Dim mblnLMouseButton As Boolean
Dim mblnRMouseButton As Boolean
If mdiMState.buttons(0) <> 0 Then mblnLMouseButton = True
If mdiMState.buttons(0) = 0 Then mblnLMouseButton = False
If mdiMState.buttons(1) <> 0 Then mblnRMouseButton = True
If mdiMState.buttons(1) = 0 Then mblnRMouseButton = False
Buttons! Can't forget those! DirectInput gives support for up to 8 buttons (or something
crazy like that), but we'll just use the standard left and right mouse buttons here. The
buttons member of the DIMOUSESTATE type is an array, the first index represents the
state of the left mouse button, the second index represents the state of the right mouse
button. We need only check these values as compared to zero to determine if they are
currently being held or not. Then, assigning values to some booleans makes it easy for us
to check this info whenever we like.
That's all there is to it. You now have some variables that describe the X and Y
coordinates, and some booleans that describe the button states. Use this information as
you see fit!
mobjdiMouse.Unacquire
Set mobjdiMouse = Nothing
Set mobjdi = Nothing
Termination is always fun. Don't forget to Unacquire the mouse when you're done.