代码改变世界

Direct3D轮回:构建基于DirectInput机制的键盘输入设备

2011-06-22 22:20  独孤残云  阅读(2005)  评论(2编辑  收藏  举报

有了鼠标输入设备,这一篇简单讨论基于DirectInput机制的键盘输入设备的构建。

继续上一篇,我们再原有基础上丰富DirectInput.h和DirectInput.cpp的内容:

/*-------------------------------------

代码清单:D3DInput.h
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/
…………
…………
class CKeyboardInput
{
public:
    CKeyboardInput();
    
~CKeyboardInput();
    HRESULT Initialize(HINSTANCE hInst,HWND hWnd);      
//初始化输入设备
    void    GetState();                                 //获取设备状态
    BOOL    IsKeyDown(int KeyCode);                     //键位是否按下
    BOOL    IsKeyUp(int KeyCode);                       //键位是否弹起
    void    Release();                                  //释放输入设备
private:
    HWND                 m_hWnd;                           
//设备所属的窗口句柄
    LPDIRECTINPUT8       m_pIDirectInput;                  //IDirectInput接口对象
    LPDIRECTINPUTDEVICE8 m_pIDirectInputDevice;            //IDirectInput设备对象
    char keyBuffer[256];                                   //键盘缓冲区,对应全盘256个字符
};

 

D3DInput.cpp
/*-------------------------------------

代码清单:D3DInput.cpp
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/
…………
…………
CKeyboardInput::CKeyboardInput() : m_pIDirectInput(NULL),
                                   m_pIDirectInputDevice(NULL)
{

}

CKeyboardInput::
~CKeyboardInput()
{

}

HRESULT CKeyboardInput::Initialize(HINSTANCE hInst,HWND hWnd)
{
    m_hWnd
=hWnd;
    HRESULT hr;
    
//创建IDirectInput接口对象
    hr=DirectInput8Create(hInst,DIRECTINPUT_VERSION,
        IID_IDirectInput8,(
void**)&m_pIDirectInput,NULL);
    
if(FAILED(hr)){
        
return hr;
    }
    
//初始化键盘输入设备
    hr=m_pIDirectInput->CreateDevice(GUID_SysKeyboard,&m_pIDirectInputDevice,NULL);//GUID_SysKeyboard代表初始化设备为键盘设备
    if(FAILED(hr)){
        ReleaseCOM(m_pIDirectInput);
        
return hr;
    }
    
//设置键盘设备的数据格式
    hr=m_pIDirectInputDevice->SetDataFormat(&c_dfDIKeyboard);
    
if(FAILED(hr)){
        ReleaseCOM(m_pIDirectInputDevice);
        ReleaseCOM(m_pIDirectInput);
        
return hr;
    }
    
//设置键盘设备的协调级别
    hr=m_pIDirectInputDevice->SetCooperativeLevel(hWnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE);
    
if(FAILED(hr)){
        ReleaseCOM(m_pIDirectInputDevice);
        ReleaseCOM(m_pIDirectInput);
        
return hr;
    }
    
//获取键盘设备访问权限
    hr=m_pIDirectInputDevice->Acquire();
    
//键盘缓冲区清零
    ZeroMemory(keyBuffer,sizeof(char)*256);
    
return S_OK;
}

void CKeyboardInput::GetState()
{
    HRESULT hr;
    
//键盘缓冲区清零
    ZeroMemory(keyBuffer,sizeof(char)*256);
    
//立即模式下获取设备状态
    hr = m_pIDirectInputDevice->GetDeviceState(sizeof(keyBuffer),(LPVOID)keyBuffer);
    
if(FAILED(hr))
    {
        
//如果失败,则重新获取键盘设备的访问权限
        hr=m_pIDirectInputDevice->Acquire();
    }
}

BOOL CKeyboardInput::IsKeyDown(
int KeyCode)
{
    
return keyBuffer[KeyCode] & 0x80;
}

BOOL CKeyboardInput::IsKeyUp(
int KeyCode)
{
    
return !IsKeyDown(KeyCode);
}

void CKeyboardInput::Release()
{
    // 释放键盘设备的访问权
    m_pIDirectInputDevice
->Unacquire();
    ReleaseCOM(m_pIDirectInputDevice);
    ReleaseCOM(m_pIDirectInput);
}

通过如上代码不难发现,键盘输入设备的构建流程其实与鼠标设备很类似~

区别在于,这次我们将输入设备的相关信息记录到了

char keyBuffer[256];

之中,长度256代表键盘上的256个键位(我没有仔细统计,感兴趣的朋友可以详细的数一下~囧~),换言之,键盘设备通过GetDeviceState记录下了键盘当前256个键位的所有状态。

理解清楚这些内容,我们可以在原有工程基础上新增一个键盘输入设备检测函数:

void TestKeyboardInput()
{
    TCHAR tmpText[
50];
    
// 获得键盘输入设备状态
    g_pKeyboardInput->GetState();
    
// 单键检测
    if(g_pKeyboardInput->IsKeyDown(DIK_D))
    {
        sprintf(tmpText,
"D键被按下");
        MessageBox(NULL,tmpText,
"提示",MB_OK|MB_ICONINFORMATION);
    }
    
// 组合键检测
    else if(g_pKeyboardInput->IsKeyDown(DIK_A)&g_pKeyboardInput->IsKeyDown(DIK_S))
    {
        sprintf(tmpText,
"A&S组合键被按下");
        MessageBox(NULL,tmpText,
"提示",MB_OK|MB_ICONINFORMATION);
    }
}

大家不难看出,组合键检测的实现其实相当容易~

当然,最后不要忘记释放我们构建的键盘设备~

ReleaseCOM(g_pKeyboardInput);

如下效果图: