DirectX Input 键盘实现

来源:互联网 发布:随身带着淘宝去异界301 编辑:程序博客网 时间:2024/05/01 20:49

// DInputKeyboard.h: interface for the CDInputKeyboard class.
//
//////////////////////////////////////////////////////////////////////

#pragma once

#define DIRECTINPUT_VERSION 0x800
#include <afxtempl.h>
#include <dinput.h>
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "DXguid.Lib")

class CDInputKeyboard 
{
 #define BUFFERCOUNT 256
 LPDIRECTINPUT         lpDirectInput;           
 LPDIRECTINPUTDEVICE   lpdiKeyboard;  
 BOOL                  KeyboardAcquired;
 BOOL                  KeyboardFound;
 CTypedPtrArray <CPtrArray, LPDIDEVICEINSTANCE> m_KeyboInstance_Array;

protected:
 virtual BOOL ProcessInputKey(TCHAR tChar)
 {
  return false;
 }

  static BOOL CALLBACK DIEnumDevicesProc(LPCDIDEVICEINSTANCE lpddi,
                                  LPVOID pvRef)
  { 
    if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_KEYBOARD
   || ((lpddi->dwDevType & DIDEVTYPE_HID) && GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_DEVICE ) )
    {
      LPDIDEVICEINSTANCE pNewdid = (LPDIDEVICEINSTANCE) new DIDEVICEINSTANCE;
      memcpy(pNewdid, lpddi, sizeof(DIDEVICEINSTANCE));
      ((CDInputKeyboard *)pvRef)->m_KeyboInstance_Array.Add(pNewdid);
    }
    return DIENUM_CONTINUE; 
  } // DIEnumDevicesProc

  void RemoveGUID()
  {
    KeyboardFound = 0;
    while(m_KeyboInstance_Array.GetSize() > 0)
    {
      delete m_KeyboInstance_Array.GetAt(0);
      m_KeyboInstance_Array.RemoveAt(0);
    }
  }

public: 
  HWND                hMainWindow;         // app window handle
 
  virtual BOOL InitInput(HWND hWnd)
  {
    ASSERT(lpDirectInput == NULL);
    ASSERT(hWnd);

    hMainWindow = hWnd;

    HINSTANCE hInstance = (HINSTANCE) GetWindowLong(hMainWindow, GWL_HINSTANCE); // program instance
    // try to create DirectInput object
    if(DirectInput8Create(hInstance, DIRECTINPUT_VERSION,  IID_IDirectInput8, (LPVOID*)&lpDirectInput, NULL) != DI_OK)
    {
      lpDirectInput = NULL;
      OutputDebugString( _T("Failed to create DirectInput object./n") );
      return FALSE;
    }
    return TRUE;
  }

  INT_PTR EnumKeyboard()
  {
    RemoveGUID();
    if(lpDirectInput)
    {
      // enumerate devices so we can get the GUIDs
      if (lpDirectInput->EnumDevices(0,
                            DIEnumDevicesProc,
                            this,
                            DIEDFL_ALLDEVICES) != DI_OK)
      {
        OutputDebugString( _T("Could not enumerate devices./n") );
      }
    }
    return m_KeyboInstance_Array.GetSize();
  }

  BOOL Unacquire()
  {
    if(lpdiKeyboard)
    {
      lpdiKeyboard->Unacquire();
      lpdiKeyboard->Release();
      lpdiKeyboard = NULL;
    }
    KeyboardAcquired = false;
    return TRUE;
  }

  BOOL Acquire(INT_PTR nPos = -1)
  {
    Unacquire();

    if(lpDirectInput == NULL)
    {
      OutputDebugString( _T("lpDirectInput is NULL./n") );
      return FALSE;
    }

    GUID KeyboardGUID =  GUID_SysKeyboard;
    if(nPos >=0 && nPos < m_KeyboInstance_Array.GetSize())
    {
      KeyboardGUID = m_KeyboInstance_Array.GetAt(nPos)->guidInstance;
    }
   
   // try to create keyboard device
    if(lpDirectInput->CreateDevice(KeyboardGUID, &lpdiKeyboard, NULL) != DI_OK ) //GUID_SysKeyboard
    {
      OutputDebugString( _T("Failed to create keyboard device./n") );
   Unacquire();
      return FALSE;
    }

    // set kbd cooperative level
    if (lpdiKeyboard->SetCooperativeLevel(hMainWindow, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE) != DI_OK)
    {
      OutputDebugString( _T("Failed to set keyboard cooperative level./n") );
   Unacquire();
      return FALSE;
    }

    // set kbd data format
    if (lpdiKeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK)
    {
      OutputDebugString( _T("Failed to set keyboard data format./n") );
   Unacquire();
      return FALSE;
    }

   // set kbd buffer size
    DIPROPDWORD dipdw = {0};
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj = 0;
    dipdw.diph.dwHow = DIPH_DEVICE;
    dipdw.dwData = BUFFERCOUNT; // * sizeof(DIDEVICEOBJECTDATA);
    if (lpdiKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) != DI_OK)
    {
      OutputDebugString( _T("Failed to set keyboard buffer size./n") );
   Unacquire();
      return FALSE;
    }

    // try to acquire the keyboard
    if (lpdiKeyboard->Acquire() != DI_OK)
    {
      OutputDebugString( _T("Failed to acquire the keyboard./n") );
   Unacquire();
      return FALSE;
    }

    KeyboardAcquired = TRUE;
    return TRUE;     
  }

  BOOL ReacquireInput(void)
  {
  //the keyboard
    if(lpdiKeyboard != NULL)
    {
      lpdiKeyboard->Acquire();
    }
    else
    {
      // keyboard device has not been created.
      return FALSE;
    }
    // if we get here, we are acquired again
    KeyboardAcquired = TRUE;

    return TRUE;
  }  // ReacquireInputDevices()

  BOOL PollKeyboard(void) //Reads the keyboard state
  {
    if(lpdiKeyboard && KeyboardAcquired)
    {
      BYTE diKeys[257] = {0};
      if (lpdiKeyboard->GetDeviceState(256, &diKeys) == DI_OK)
      {
        if(diKeys[DIK_LWIN] & 0x80) /* Left Windows key */
        {
        }
        if(diKeys[DIK_RWIN] & 0x80) /* Right Windows key */
        {
        }
     
        return TRUE;  // success
      }
    }
    return FALSE;
  } // PollKeyboard()

  HRESULT ReadKeyboardInput(void)
  {
  HRESULT hRes = DI_OK;
  if(KeyboardAcquired)
  {
   DIDEVICEOBJECTDATA  KbdBuffer[BUFFERCOUNT] = {0};
   DWORD dwItems = BUFFERCOUNT;
   hRes = lpdiKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),
                 KbdBuffer, &dwItems, 0);
   if(hRes == DI_OK || hRes == DI_BUFFEROVERFLOW)
   {

    for (DWORD k = 0; k < dwItems; k++)
    {
     LPDIDEVICEOBJECTDATA lpdidod = &KbdBuffer[k];

     TCHAR VKey = MapVirtualKey(lpdidod->dwOfs, 3); //映射到虚拟键
     ProcessInputKey(VKey); //处理输入

     CString dbgStr, tmpStr;
     dbgStr.Format(_T("%d"), lpdidod->dwSequence);
     tmpStr.Format(_T(". Scan code 0x%04X"), lpdidod->dwOfs);
     dbgStr += tmpStr;           
     dbgStr += (lpdidod->dwData & 0x80)? _T(" pressed ") : _T(" released ");       
     tmpStr.Format(_T(". Age: %d ms"), GetTickCount() - lpdidod->dwTimeStamp);
     dbgStr += tmpStr;
     dbgStr += _T("/n");
     OutputDebugString(dbgStr);       
    }
   }
   else if(hRes == DIERR_INPUTLOST)
   {
    ReacquireInput();
    hRes = S_FALSE;
   }
  }
    return hRes;
  }


////////////////////////////////////////////////
  CDInputKeyboard()
  {
    hMainWindow = NULL;
    lpDirectInput = NULL;
    lpdiKeyboard = NULL;
    KeyboardAcquired = 0;
    KeyboardFound = 0;
    m_KeyboInstance_Array.RemoveAll();
  }

  virtual ~CDInputKeyboard()
  {
    if(lpdiKeyboard)
    {
      lpdiKeyboard->Unacquire();
      lpdiKeyboard->Release();
      lpdiKeyboard = NULL;
    }

    if(lpDirectInput)
    {
      lpDirectInput->Release();
      lpDirectInput = NULL;
    }

    RemoveGUID();
  }


};