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()