// =======================================-====================================
// Filename: DIMouse.h
// Description: Header file for the DirectInput Mouse class
//
// This code corresponds to DirectX Techniques Series 1 Tutorial 5, at
// www.32bits.co.uk
// ============================================================================
#include "DIMouse.h"
// =============================================================================
// Constructor and Destructor
// =============================================================================
CDIMouse::CDIMouse()
{
m_pDIObject = NULL;
m_pDIMouseDevice = NULL;
m_iCursorX = 0;
m_iCursorY = 0;
m_iHotSpotX = 0;
m_iHotSpotY = 0;
}
CDIMouse::~CDIMouse()
{
// All DInput devices must be properly released or problems will occur.
if(m_pDIMouseDevice != NULL)
{
m_pDIMouseDevice->Unacquire();
m_pDIMouseDevice->Release();
m_pDIMouseDevice = NULL;
}
}
// =============================================================================
// Initialisation
// =============================================================================
HRESULT CDIMouse::Initialise(HWND hWnd, int iWindowWidth, int iWindowHeight)
{
HRESULT rslt = S_OK;
// First, create the DirectInput object (exactly the same as Direct3DCreate9())
rslt = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (void**)&m_pDIObject, NULL);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not create DInput object"); }
// Next, create a device for the mouse
rslt = m_pDIObject->CreateDevice(GUID_SysMouse, &m_pDIMouseDevice, NULL);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not create DInput device"); }
// Define the data format for the mouse device. c_dfDIMouse is a precreated struct
// provided with DInput that is already configured for a generic mouse.
rslt = m_pDIMouseDevice->SetDataFormat(&c_dfDIMouse);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not configure mouse data."); }
// Set the cooperation level - how DInput should work with this device & the rest of Windows
rslt = m_pDIMouseDevice->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not set cooperation."); }
// All done, now we need to acquire the device (grab it for our own use)
rslt = m_pDIMouseDevice->Acquire();
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not acquire mouse."); }
/*
// This code is not needed for the tutorial sample. It's provided here to demonstrate how
// to obtain the features of a DirectInput device. Search the SDK for
// IDirectInputDevice8::GetCapabilities() and DIDEVCAPS for more info.
DIDEVCAPS kMouseCaps;
ZeroMemory(&kMouseCaps, sizeof(DIDEVCAPS));
kMouseCaps.dwSize = sizeof(DIDEVCAPS);
m_pDIMouseDevice->GetCapabilities(&kMouseCaps);
*/
m_iWindowWidth = iWindowWidth;
m_iWindowHeight = iWindowHeight;
return S_OK;
}
// =============================================================================
// Updates the position of the cursor
// =============================================================================
BOOL CDIMouse::Update()
{
if(m_pDIObject == NULL || m_pDIMouseDevice == NULL)
return FALSE;
// If we can't get the device state, we've lost the device so we need to try to get it back.
// This is very similar to a lost D3D device.
if(FAILED(m_pDIMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&m_kMouseState)))
{
if(FAILED(m_pDIMouseDevice->Acquire()))
{
return FALSE;
}
else
{
if(FAILED(m_pDIMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&m_kMouseState)))
return FALSE;
}
}
// DInput *always* provides relative movement. IE: DInput says "The mouse moved 5 units", not
// "The mouse is now at X, Y". To get absolute coordinates, we have to track it manually.
m_iCursorX += m_kMouseState.lX;
if(m_iCursorX < 0)
m_iCursorX = 0;
if(m_iCursorX > m_iWindowWidth)
m_iCursorX = m_iWindowWidth;
m_iCursorY += m_kMouseState.lY;
if(m_iCursorY < 0)
m_iCursorY = 0;
if(m_iCursorY > m_iWindowHeight)
m_iCursorY = m_iWindowHeight;
return TRUE;
}
// =============================================================================
// Draws the cursor on screen
// =============================================================================
HRESULT CDIMouse::Render(LPDIRECT3DDEVICE9 pDevice)
{
// This is just a very simple way to display the mouse position. We use
// Clear to draw a rect where the cursor is. Normally this would of course
// be a sprite rendered at the mouse position (which is why we use a hotspot,
// to allow different cursors to be used)
D3DRECT rcCursor;
rcCursor.x1 = m_iCursorX; rcCursor.y1 = m_iCursorY;
rcCursor.x2 = m_iCursorX + 10; rcCursor.y2 = m_iCursorY + 10;
pDevice->Clear(1, &rcCursor, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,150,200), 1.0f, 0);
return S_OK;
}
// =============================================================================
// Accessor methods for mouse states
// =============================================================================
int CDIMouse::GetRelativeX()
{
return m_kMouseState.lX;
}
int CDIMouse::GetRelativeY()
{
return m_kMouseState.lY;
}
int CDIMouse::GetAbsoluteX()
{
return m_iCursorX;
}
int CDIMouse::GetAbsoluteY()
{
return m_iCursorY;
}
void CDIMouse::GetAbsolutePos(POINT* kMousePos)
{
if(kMousePos != NULL)
{
kMousePos->x = m_iCursorX + m_iHotSpotX;
kMousePos->y = m_iCursorY + m_iHotSpotY;
}
return;
}
void CDIMouse::SetHotSpot(int iX, int iY)
{
m_iHotSpotX = iX;
m_iHotSpotY = iY;
}
BOOL CDIMouse::IsMouseButtonDown(int iButton, POINT* kClickPoint)
{
// Logical AND the button states to check if the mouse button flag is set. The iButton
// parameter is a number representing the button to check, or use the #define's in
// the header file (DIMOUSE_LEFTBUTTON etc).
if(m_kMouseState.rgbButtons[iButton] & 0xF0)
{
// If it is, the button is clicked, so set kClickPoint to the current hotspot
// location (ie: where the mouse was clicked).
if(kClickPoint != NULL)
{
kClickPoint->x = m_iCursorX + m_iHotSpotX;
kClickPoint->y = m_iCursorY + m_iHotSpotY;
}
return TRUE;
}
// We could else{} this call, but we might want to check for other
// buttons later
if(kClickPoint != NULL)
{
kClickPoint->x = -1;
kClickPoint->y = -1;
}
return FALSE;
}