?? input.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 + -