www.pudn.com > coolMEMORY.rar > AS_DXInput.cpp
//-----------------------------------------------------------------------------
// File: AS_DXInput.cpp
//-----------------------------------------------------------------------------
#include "AS_ENGINE.h"
// Definations: ***************************************************************
#define MOUSE_SAMPLE_BUFFER_SIZE 16 // arbitrary number of buffer elements
#define KEYBOARD_SAMPLE_BUFFER_SIZE 8 // arbitrary number of buffer elements
///////////////////////////////////////////////////////////////////////////////
// Variables: *****************************************************************
AS_DX_INPUT_KEY AS_DXInputKeys[AS_DX_INPUT_KEYS];
AS_MOUSE ASMouse;
///////////////////////////////////////////////////////////////////////////////
// Functions: *****************************************************************
int ConvertScancodeToASCII(DWORD, USHORT *);
DWORD ConvertASCIIToScancode(char byASCII);
int GetDXInputKey(int);
BOOL ASIsKeyPressed(void);
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// Name: AS_ENGINE::CreateDXInputDevices()
// Desc: Setups the mouse and the keyboard device.
//-----------------------------------------------------------------------------
HRESULT AS_ENGINE::CreateDXInputDevices(HWND hWnd, BOOL bExclusive, BOOL bForeground, BOOL bImmediate, BOOL bDisableWindowsKey)
{ // begin AS_ENGINE::CreateDXInputDevices()
HRESULT iHr;
DWORD dwCoopFlags;
// Cleanup any previous call first
FreeDXInputDevices();
if(bExclusive)
dwCoopFlags = DISCL_EXCLUSIVE;
else
dwCoopFlags = DISCL_NONEXCLUSIVE;
if(bForeground)
dwCoopFlags |= DISCL_FOREGROUND;
else
dwCoopFlags |= DISCL_BACKGROUND;
// Create a DInput object
if(FAILED(iHr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (void **) &pDXDI, NULL)))
return iHr;
// Setup mouse:
// Obtain an interface to the system mouse device.
if(FAILED(iHr = pDXDI->CreateDevice(GUID_SysMouse, &pDXMouse, NULL)))
return iHr;
// Set the data format to "mouse format" - a predefined data format
//
// A data format specifies which controls on a device we
// are interested in, and how they should be reported.
//
// This tells DirectInput that we will be passing a
// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
if(FAILED(iHr = pDXMouse->SetDataFormat(&c_dfDIMouse)))
return iHr;
// Set the cooperativity level to let DirectInput know how
// this device should interact with the system and with other
// DirectInput applications.
iHr = pDXMouse->SetCooperativeLevel(hWnd, dwCoopFlags);
if(iHr == DIERR_UNSUPPORTED && !bForeground && bExclusive)
{
FreeDXInputDevices();
return S_OK;
}
// Setup keyboard:
// Disabling the windows key is only allowed only if we are in foreground nonexclusive
if(bDisableWindowsKey && !bExclusive && bForeground)
dwCoopFlags |= DISCL_NOWINKEY;
// Obtain an interface to the system keyboard device.
if(FAILED(iHr = pDXDI->CreateDevice(GUID_SysKeyboard, &pDXKeyboard, NULL)))
return iHr;
// Set the data format to "keyboard format" - a predefined data format
//
// A data format specifies which controls on a device we
// are interested in, and how they should be reported.
//
// This tells DirectInput that we will be passing an array
// of 256 bytes to IDirectInputDevice::GetDeviceState.
if(FAILED(iHr = pDXKeyboard->SetDataFormat(&c_dfDIKeyboard)))
return iHr;
// Set the cooperativity level to let DirectInput know how
// this device should interact with the system and with other
// DirectInput applications.
iHr = pDXKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags);
if(iHr == DIERR_UNSUPPORTED && !bForeground && bExclusive)
{
FreeDXInputDevices();
return S_OK;
}
if(FAILED(iHr))
return iHr;
if(!bImmediate)
{
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
//
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
// If you want to read buffered data, you need to set a nonzero
// buffer size.
//
// Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
//
// The buffer size is a DWORD property associated with the device.
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = MOUSE_SAMPLE_BUFFER_SIZE; // Arbitary buffer size
// Setup mouse:
if(FAILED(iHr = pDXMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
return iHr;
dipdw.dwData = KEYBOARD_SAMPLE_BUFFER_SIZE; // Arbitary buffer size
// Setup keyboard:
if(FAILED(iHr = pDXKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
return iHr;
}
// Acquire the newly created device
pDXMouse->Acquire();
pDXKeyboard->Acquire();
ASEnumerateDXInputKeys();
return S_OK;
} // end AS_ENGINE::CreateDXInputDevices()
//-----------------------------------------------------------------------------
// Name: AS_ENGINE::ReadDXInputData()
// Desc: Read the input device's state.
//-----------------------------------------------------------------------------
HRESULT AS_ENGINE::ReadDXInput(HWND hWnd)
{ // begin AS_ENGINE::ReadDXInput()
HRESULT iHr;
DIMOUSESTATE dims2; // DirectInput mouse state structure
DWORD dwElements;
int i;
// Get the input's device state, and put the state in dims
if(pDXMouse)
{
ZeroMemory(&dims2, sizeof(dims2));
iHr = pDXMouse->GetDeviceState(sizeof(DIMOUSESTATE), &dims2);
if(FAILED(iHr))
{
// DirectInput may be telling us that the input stream has been
// interrupted. We aren't tracking any state between polls, so
// we don't have any special reset that needs to be done.
// We just re-acquire and try again.
// If input is lost then acquire and keep trying
iHr = pDXMouse->Acquire();
while(iHr == DIERR_INPUTLOST)
iHr = pDXMouse->Acquire();
// iHr may be DIERR_OTHERAPPHASPRIO or other errors. This
// may occur when the app is minimized or in the process of
// switching, so just try again later
}
ASMouse.lX = dims2.lX;
ASMouse.lY = dims2.lY;
ASMouse.lZ = dims2.lZ;
memcpy(&ASMouse.byLastButtons, ASMouse.byButtons, sizeof(dims2.rgbButtons));
memcpy(&ASMouse.byButtons, dims2.rgbButtons, sizeof(dims2.rgbButtons));
ASMouse.bButtonDown = FALSE;
for(i = 0; i < MAX_MOUSE_BUTTONS; i++)
{
if(ASMouse.byButtons[i] == ASMouse.byLastButtons[i])
ASMouse.bFirstButtons[i] = FALSE;
else
ASMouse.bFirstButtons[i] = TRUE;
if(CHECK_KEY(ASMouse.byButtons, i))
ASMouse.bButtonDown = TRUE;
else
ASMouse.bFirstButtons[i] = FALSE;
}
}
// Keyboard:
if(pDXKeyboard)
{
dwElements = KEYBOARD_SAMPLE_BUFFER_SIZE;
iHr = pDXKeyboard->GetDeviceState(sizeof(ASKeys), &ASKeys);
if(iHr != DI_OK)
{
// We got an error or we got DI_BUFFEROVERFLOW.
//
// Either way, it means that continuous contact with the
// device has been lost, either due to an external
// interruption, or because the buffer overflowed
// and some events were lost.
//
// Consequently, if a button was pressed at the time
// the buffer overflowed or the connection was broken,
// the corresponding "up" message might have been lost.
//
// But since our simple sample doesn't actually have
// any state associated with button up or down events,
// there is no state to reset. (In a real game, ignoring
// the buffer overflow would result in the game thinking
// a key was held down when in fact it isn't; it's just
// that the "up" event got lost because the buffer
// overflowed.)
//
// If we want to be cleverer, we could do a
// GetDeviceState() and compare the current state
// against the state we think the device is in,
// and process all the states that are currently
// different from our private state.
iHr = pDXKeyboard->Acquire();
while(iHr == DIERR_INPUTLOST )
iHr = pDXKeyboard->Acquire();
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
// may occur when the app is minimized or in the process of
// switching, so just try again later
for(i = 0; i < 256; i++)
ASKeyFirst[i] = ASKeyPressed[i] = ASKeys[i] = FALSE;
return S_OK;
}
}
if(ASKeys[29])
{
ASMouse.byButtons[2] = 128;
ASMouse.bButtonDown = TRUE;
}
if(ASKeyFirst[AS_SCREENSHOT_KEY])
_AS->bMakeScreenshot = TRUE;
// Check if the keys were already pressed:
for(i = 0; i < 256; i++)
{
if(ASKeys[i] && !ASKeyPressed[i])
{
ASKeyPressed[i] = TRUE;
ASKeyFirst[i] = TRUE;
}
else
{
ASKeyFirst[i] = FALSE;
if(!ASKeys[i])
ASKeyPressed[i] = FALSE;
}
}
return S_OK;
} // end AS_ENGINE::ReadDXInput()
//-----------------------------------------------------------------------------
// Name: AS_ENGINE::FreeDXInputDevices()
// Desc: Initialize the DirectInput variables.
//-----------------------------------------------------------------------------
void AS_ENGINE::FreeDXInputDevices()
{ // begin AS_ENGINE::FreeDXInputDevicest()
// Unacquire the device one last time just in case
// the app tried to exit while the device is still acquired.
// Mouse:
if(pDXMouse)
pDXMouse->Unacquire();
// Keyboard:
if(pDXKeyboard)
pDXKeyboard->Unacquire();
// Release any DirectInput objects.
// Mouse:
SAFE_RELEASE(pDXMouse);
// Keyboard:
SAFE_RELEASE(pDXKeyboard);
SAFE_RELEASE(pDXDI);
} // end AS_ENGINE::FreeDXInputDevices()
void AS_ENGINE::ASEnumerateDXInputKeys(void)
{ // begin AS_ENGINE::ASEnumerateDXInputKeys()
DIDEVICEOBJECTINSTANCE didoi;
int i, i2 = 0;
didoi.dwSize = sizeof(didoi);
if(pDXKeyboard)
{
for(i = 0; i < AS_DX_INPUT_KEYS; i++)
{
if(SUCCEEDED(pDXKeyboard->GetObjectInfo(&didoi,
i,
DIPH_BYOFFSET)))
{
strcpy(AS_DXInputKeys[i2].byName, didoi.tszName);
AS_DXInputKeys[i2].iCode = i;
i2++;
}
}
}
for(; i2 < AS_DX_INPUT_KEYS; i2++)
AS_DXInputKeys[i2].iCode = -1;
_ASConfig->Check();
} // end AS_ENGINE::ASEnumerateDXInputKeys()
// Functions: *****************************************************************
int ConvertScancodeToASCII(DWORD dwScancode, USHORT *iResult)
{ // begin ConvertScancodeToASCII()
static HKL Layout = GetKeyboardLayout(0);
static UCHAR byState[256];
if(GetKeyboardState(byState) == FALSE)
return 0;
UINT vk = MapVirtualKeyEx(dwScancode, 1, Layout);
return ToAsciiEx(vk, dwScancode, byState, iResult, 0, Layout);
} // end ConvertScancodeToASCII()
int GetDXInputKey(int iCode)
{ // begin GetDXInputKey()
for(int i = 0; i < AS_DX_INPUT_KEYS; i++)
if(iCode == AS_DXInputKeys[i].iCode)
return i;
return 0;
} // end GetDXInputKey()
BOOL ASIsKeyPressed(void)
{ // begin ASIsKeyPressed()
int i;
// Check if the 'any key' is pressed:
for(i = 0; i < 256; i++)
{
if(i == AS_SCREENSHOT_KEY)
continue;
if(ASKeyFirst[i])
return true;
}
for(i = 0; i < 3; i++)
{
if(CHECK_KEY(ASMouse.byButtons, i))
return true;
}
return false;
} // begin ASIsKeyPressed()