⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.cpp

📁 用vc++结合directinput编程序实现键盘时间捕捉
💻 CPP
字号:
//======================================================================
/**
*  @file      Input.cpp
*
*  项目描述: DirectInput输入系统
*   
*  文件描述:  输入系统类CInputSystem
*             其中,类CKeyboard、CMouse和CJoystick分别用来处理键盘、鼠标
*             和游戏手柄,CInputSystem是输入设备的管理类。
*  适用平台: Windows98/2000/NT/XP
*  
*  作者:     WWBOSS
*  电子邮件:  wwboss123@gmail.com
*  创建日期: 2007-07-24	
*  修改日期: 2007-07-24
*/																			
//======================================================================

#include "Input.h"

//************** 键盘类CKeyboard的实现 **************************/
/** 构造函数 */
CKeyboard::CKeyboard(LPDIRECTINPUT8 pDI, HWND hwnd)
{
	/** 创建设备对象 */
	if (FAILED(pDI->CreateDevice(GUID_SysKeyboard, &m_pDIDev, NULL)))
	{
		MessageBox(NULL,"创建键盘设备对象失败!","错误",MB_OK);
	}

    /** 设置数据格式 */
	if (FAILED(m_pDIDev->SetDataFormat(&c_dfDIKeyboard)))
	{
		MessageBox(NULL,"设置键盘数据格式失败!","错误",MB_OK);
	}

    /** 设置协作层次 */ 
	if (FAILED(m_pDIDev->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
	{
		MessageBox(NULL,"设置键盘协作层次失败!","错误",MB_OK);
	}

	/** 捕获设置 */ 
	if (FAILED(m_pDIDev->Acquire()))
	{
		MessageBox(NULL,"捕获键盘设备失败!","错误",MB_OK);
	}

	/** 键盘数据清零 */
	Clear();
}

/** 析构函数 */
CKeyboard::~CKeyboard()
{
	if (m_pDIDev)
	{
		m_pDIDev->Unacquire();
		m_pDIDev->Release();
	}
}

/** 更新键盘数据 */
bool CKeyboard::Update()
{
  if (FAILED(m_pDIDev->GetDeviceState(sizeof(m_keys), (LPVOID)m_keys)))
  {
		if (FAILED(m_pDIDev->Acquire()))
			return false;

		if (FAILED(m_pDIDev->GetDeviceState(sizeof(m_keys),(LPVOID)m_keys)))
			return false;
	}

	return TRUE;
}

//************** 鼠标类CMouse的实现 **************************/
/** 构造函数 */
CMouse::CMouse(LPDIRECTINPUT8 pDI, HWND hwnd, bool isExclusive)
{
	/** 得到当前窗口的大小 */
	RECT r;
	GetClientRect(hwnd , &r);
	m_iWidth = r.right - r.left;
	m_iHeight = r.bottom - r.top;

	m_iMousePos.x = m_iWidth/2;
	m_iMousePos.y = m_iHeight/2;

	/** 创建设备对象 */
	if (FAILED(pDI->CreateDevice(GUID_SysMouse, &m_pDIDev, NULL)))
	{
		MessageBox(NULL,"创建鼠标设备对象失败!","错误",MB_OK);
	}

	/** 设置数据格式 */
	if (FAILED(m_pDIDev->SetDataFormat(&c_dfDIMouse)))
	{
		MessageBox(NULL,"设置鼠标数据格式失败!","错误",MB_OK);
	}

	DWORD flags;

	if (isExclusive)
		flags = DISCL_FOREGROUND|DISCL_EXCLUSIVE|DISCL_NOWINKEY;
	else
		flags = DISCL_FOREGROUND|DISCL_NONEXCLUSIVE;

	/** 设置协作层次 */
	if (FAILED(m_pDIDev->SetCooperativeLevel(hwnd, flags)))
	{
		MessageBox(NULL,"设置鼠标协作层次失败!","错误",MB_OK);
	}
    
	/** 设置鼠标属性 */
	DIPROPDWORD  dipROPWORD;
	dipROPWORD.diph.dwSize = sizeof(DIPROPDWORD);
	dipROPWORD.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipROPWORD.diph.dwObj = 0;
	dipROPWORD.diph.dwHow = DIPH_DEVICE;
	dipROPWORD.dwData = DINPUT_BUFFERSIZE;
	
	if(FAILED(m_pDIDev->SetProperty(DIPROP_BUFFERSIZE,&dipROPWORD.diph)))
	{
		MessageBox(NULL,"设置鼠标设备属性失败!","错误",MB_OK);
	}
	
	/** 捕获设备 */
	if (FAILED(m_pDIDev->Acquire()))
	{
		MessageBox(NULL,"捕获鼠标设备失败!","错误",MB_OK);
	}

}

/** 判断鼠标左键是否按下 */
bool CMouse::IsLButtonPressed()
{
	for(int i=0;i<DINPUT_BUFFERSIZE; i++)
	{
		if((m_diData[i].dwOfs == DIMOFS_BUTTON0) && 
		   (m_diData[i].dwData & 0x80))
		   return true;
	}
	return false;
}

/** 判断鼠标右键是否按下 */
bool CMouse::IsRButtonPressed()
{
	for(int i=0;i<DINPUT_BUFFERSIZE; i++)
	{
		if((m_diData[i].dwOfs == DIMOFS_BUTTON1) && 
		   (m_diData[i].dwData & 0x80))
		   return true;
	}
	return false;
}


/** 判断鼠标中键是否按下 */
bool CMouse::IsMButtonPressed()
{
	for(int i=0;i<DINPUT_BUFFERSIZE; i++)
	{
		if((m_diData[i].dwOfs == DIMOFS_BUTTON2) && 
		   (m_diData[i].dwData & 0x80))
		   return true;
	}
	return false;
}

/** 析构函数 */
CMouse::~CMouse()
{
	if (m_pDIDev)
	{
		m_pDIDev->Unacquire();
		m_pDIDev->Release();
	}
}


/** 更新鼠标参数 */
bool CMouse::Update()
{
	HRESULT  hr;
	DWORD  dwReadNum = 1;
	int i;

	/** 清零鼠标缓冲区 */
	ZeroMemory(m_diData,sizeof(DIDEVICEOBJECTDATA) * DINPUT_BUFFERSIZE);

	/**循环读取鼠标数据 */
	for(i=0; i<DINPUT_BUFFERSIZE;i++)
	{
		hr = m_pDIDev->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),
							&m_diData[i],&dwReadNum,0);
		if(hr == DIERR_INPUTLOST)
		{
			m_pDIDev->Acquire();
			hr = m_pDIDev->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),
							&m_diData[i],&dwReadNum,0);
			if(FAILED(hr))
			{
				MessageBox(NULL,"取得鼠标缓冲区数据失败!","错误",MB_OK);
				return false;
			}
		}

		/** 更新鼠标位置 */
		if(m_diData[i].dwOfs == DIMOFS_X)
			m_iMousePos.x += m_diData[i].dwData;

		if(m_diData[i].dwOfs == DIMOFS_Y)
			m_iMousePos.y += m_diData[i].dwData;
		
		/** 限制鼠标在窗口范围 */
		if(m_iMousePos.x < 0)
			m_iMousePos.x = 0;
		if(m_iMousePos.x> m_iWidth)
			m_iMousePos.x = m_iWidth;
		if(m_iMousePos.y < 0)
			m_iMousePos.y = 0;
		if(m_iMousePos.y > m_iHeight)
			m_iMousePos.y = m_iHeight;
        		
	}
	return true;
}


//************** 游戏手柄CJoystick的实现 *******************************/

CJoystick::CJoystick(LPDIRECTINPUT8 pDI,HWND hwnd,HINSTANCE appInstance)
:m_iMin(-100),m_iMax(100),m_iDeadZone(20)
{
	HRESULT hr;
	m_pDI = pDI;

	/** 枚举已安装的所有游戏杆 */
	/**hr = m_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL,(LPDIENUMDEVICESCALLBACKA)EnumJSCallback,&m_pDIDev,DIEDFL_ATTACHEDONLY);
	if(FAILED(hr))
	{
		MessageBox(NULL,"枚举游戏杆失败!","错误",MB_OK);
		exit(-1);
	}*/
	if(m_pDIDev == NULL)
	{
		MessageBox(NULL,"没有安装游戏杆!","错误",MB_OK);
		exit(-1);
	}

	/** 设置游戏杆的数据格式 */
	hr = m_pDIDev->SetDataFormat(&c_dfDIJoystick2);
	if(FAILED(hr))
		MessageBox(NULL,"设置游戏杆数据格式失败!","错误",MB_OK);

	/** 设置游戏杆的协作层级 */
	hr = m_pDIDev->SetCooperativeLevel(hwnd,DISCL_BACKGROUND|DISCL_NONEXCLUSIVE);
	if(FAILED(hr))
		MessageBox(NULL,"设置游戏杆协作层级失败!","错误",MB_OK);

	/** 设置游戏杆的轴范围 */
	DIPROPRANGE  dipROPRANGE;
	dipROPRANGE.diph.dwSize = sizeof(DIPROPRANGE);
	dipROPRANGE.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipROPRANGE.diph.dwObj = 0;
	dipROPRANGE.diph.dwHow = DIPH_DEVICE;
	dipROPRANGE.lMin = m_iMin;
	dipROPRANGE.lMax = m_iMax;

	hr = m_pDIDev->SetProperty(DIPROP_RANGE,&dipROPRANGE.diph);
	if(FAILED(hr))
		MessageBox(NULL,"设置游戏杆轴范围失败!","错误",MB_OK);

	/** 设置游戏杆的死区范围 */
	DIPROPDWORD  dipROPDWORD;
	dipROPDWORD.diph.dwSize = sizeof(DIPROPDWORD);
	dipROPDWORD.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipROPDWORD.diph.dwObj = 0;
	dipROPDWORD.diph.dwHow = DIPH_DEVICE;
	dipROPDWORD.dwData = 100 * m_iDeadZone;

	hr = m_pDIDev->SetProperty(DIPROP_DEADZONE,&dipROPDWORD.diph);
	if(FAILED(hr))
		MessageBox(NULL,"设置游戏杆死区范围失败!","错误",MB_OK);

	/** 初始化数据区 */
	ZeroMemory(&m_diJoyState2,sizeof(DIJOYSTATE2));
    

}

/** 回调函数 */
bool CALLBACK CJoystick::EnumJSCallback(LPCDIDEVICEINSTANCE  pDIDeviceInstance, LPVOID pvRef)
{
	HRESULT hr;
	LPDIRECTINPUTDEVICE8* ppDID = (LPDIRECTINPUTDEVICE8* )pvRef;
	hr = m_pDI->CreateDevice(pDIDeviceInstance->guidInstance,ppDID,NULL);
	if(FAILED(hr))
		return DIENUM_CONTINUE;
	else
		return DIENUM_STOP;
}

/** 更新,获取输入 */
bool CJoystick::Update()
{
	/** 获取游戏杆的访问权 */
	HRESULT hr;
	hr = m_pDIDev->Acquire();
	if(FAILED(hr))
	{
		MessageBox(NULL,"获得游戏杆访问权失败!","错误",MB_OK);
		return false;
	}

	/** 检测游戏杆 */
	hr = m_pDIDev->Poll();
	if(FAILED(hr))
	{
		MessageBox(NULL,"检测游戏杆失败!","错误",MB_OK);
		return false;
	}

	/** 读取游戏杆的输入 */
	hr = m_pDIDev->GetDeviceState(sizeof(DIJOYSTATE2),&m_diJoyState2);
	
	/** 设备丢失 */
	if(hr == DIERR_INPUTLOST)
	{
		m_pDIDev->Acquire();  /**< 重新获得设备使用权 */
		m_pDIDev->GetDeviceState(sizeof(DIJOYSTATE2),&m_diJoyState2);
		if(FAILED(hr))
		{
			MessageBox(NULL,"获取游戏杆数据失败!","错误",MB_OK);
			return false;
		}

	}
	return true;

}

CJoystick::~CJoystick()
{
	if (m_pDI)
		m_pDI->Release();


	if (m_pDIDev)
	{
		m_pDIDev->Unacquire();
		m_pDIDev->Release();
	}
}


//************** 输入系统类CInputSystem的实现 **************************/

CInputSystem* CInputSystem::m_pInput = NULL;
HWND CInputSystem::m_hWnd = NULL;

/** 初始化设备 */
bool CInputSystem::Init(HWND hwnd,HINSTANCE appInstance,
						bool isExclusive,DWORD flags)
{
	m_pKeyboard = NULL; 
	m_pMouse = NULL;
	m_pJoystick = NULL;

	m_hWnd = hwnd;

	/** 创建DirectInput接口对象 */
	if (FAILED(DirectInput8Create(appInstance,
								DIRECTINPUT_VERSION,
								IID_IDirectInput8,
								(void **)&m_pDI,NULL)))
	{
		MessageBox(NULL,"创建DirectInput接口对象失败!","错误",MB_OK);
		return false;
	}
    
	/** 创建键盘 */
	if (flags & IS_USEKEYBOARD)
	{
		m_pKeyboard = new CKeyboard(m_pDI, hwnd);
	}

	/** 创建鼠标 */
	if (flags & IS_USEMOUSE)
	{
		m_pMouse = new CMouse(m_pDI, hwnd, true);
	}
	
	/** 创建游戏杆 */
	if (flags & IS_USEJOYSTICK)
	{
		m_pJoystick = new CJoystick(m_pDI,hwnd,appInstance);
	}

	return true;

}

/** 更新输入设备的参数 */
void CInputSystem::Update()
{
	/** 键盘更新 */
	if (m_pKeyboard)	
		m_pKeyboard->Update();
	
	/** 鼠标更新 */
	if (m_pMouse)		
		m_pMouse->Update();
	
	/** 游戏杆更新 */
	if (m_pJoystick)		
		m_pJoystick->Update();

}

/** 释放输入设备资源 */
bool CInputSystem::ShutDown()
{
	UnacquireAll();

    if (m_pKeyboard)
	{  
		delete m_pKeyboard;
		m_pKeyboard  = NULL;
	}

    if (m_pMouse)
	{
	   delete m_pMouse;
	   m_pMouse = NULL;
	}

	if (m_pJoystick)
	{
	   delete m_pJoystick;
	   m_pJoystick = NULL;
	}
    
	/** 释放接口对象 */
	if (FAILED(m_pDI->Release()))
		return false;

     return true;
}

/** 获得光标的3D坐标 */
Vector3  CInputSystem::GetMousePosition()
{
	float depth[2];
	Point2 p;

	/** 得到鼠标的当前2D位置 */
	p = m_pMouse->GetMousePos();

	GLdouble x,y,z;

	/** 得到像素的深度值 */
	glReadPixels(p.x,p.y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,depth);
	
	/** 得到模型矩阵和投影矩阵 */
	GLdouble model[16],project[16];
	glGetDoublev(GL_MODELVIEW_MATRIX,model);
	glGetDoublev(GL_PROJECTION_MATRIX,project);

	/** 计算该点的世界坐标 */
	GLint viewport[4]={0,0,m_pMouse->m_iWidth,m_pMouse->m_iHeight};
	gluUnProject(p.x,p.y,depth[0],model,project,viewport,&x,&y,&z);

	return Vector3((float)x,(float)y,(float)z);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -