1 // DInputKeyboard.h: interface for the CDInputKeyboard class. 2 // 3 // 4 5 #pragma once 6 7 #define DIRECTINPUT_VERSION 0x800 8 #include9 #include 10 #pragma comment(lib, "dinput8.lib") 11 #pragma comment(lib, "DXguid.Lib") 12 13 class CDInputKeyboard 14 { 15 #define BUFFERCOUNT 256 16 LPDIRECTINPUT lpDirectInput; 17 LPDIRECTINPUTDEVICE lpdiKeyboard; 18 BOOL KeyboardAcquired; 19 BOOL KeyboardFound; 20 CTypedPtrArray m_KeyboInstance_Array; 21 22 protected: 23 virtual BOOL ProcessInputKey(TCHAR tChar) 24 { 25 return false; 26 } 27 28 static BOOL CALLBACK DIEnumDevicesProc(LPCDIDEVICEINSTANCE lpddi, 29 LPVOID pvRef) 30 { 31 if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_KEYBOARD 32 || ((lpddi->dwDevType & DIDEVTYPE_HID) && GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_DEVICE ) ) 33 { 34 LPDIDEVICEINSTANCE pNewdid = (LPDIDEVICEINSTANCE) new DIDEVICEINSTANCE; 35 memcpy(pNewdid, lpddi, sizeof(DIDEVICEINSTANCE)); 36 ((CDInputKeyboard *)pvRef)->m_KeyboInstance_Array.Add(pNewdid); 37 } 38 return DIENUM_CONTINUE; 39 } // DIEnumDevicesProc 40 41 void RemoveGUID() 42 { 43 KeyboardFound = 0; 44 while(m_KeyboInstance_Array.GetSize() > 0) 45 { 46 delete m_KeyboInstance_Array.GetAt(0); 47 m_KeyboInstance_Array.RemoveAt(0); 48 } 49 } 50 51 public: 52 HWND hMainWindow; // app window handle 53 54 virtual BOOL InitInput(HWND hWnd) 55 { 56 ASSERT(lpDirectInput == NULL); 57 ASSERT(hWnd); 58 59 hMainWindow = hWnd; 60 61 HINSTANCE hInstance = (HINSTANCE) GetWindowLong(hMainWindow, GWL_HINSTANCE); // program instance 62 // try to create DirectInput object 63 if(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&lpDirectInput, NULL) != DI_OK) 64 { 65 lpDirectInput = NULL; 66 OutputDebugString( _T("Failed to create DirectInput object./n") ); 67 return FALSE; 68 } 69 return TRUE; 70 } 71 72 INT_PTR EnumKeyboard() 73 { 74 RemoveGUID(); 75 if(lpDirectInput) 76 { 77 // enumerate devices so we can get the GUIDs 78 if (lpDirectInput->EnumDevices(0, 79 DIEnumDevicesProc, 80 this, 81 DIEDFL_ALLDEVICES) != DI_OK) 82 { 83 OutputDebugString( _T("Could not enumerate devices./n") ); 84 } 85 } 86 return m_KeyboInstance_Array.GetSize(); 87 } 88 89 BOOL Unacquire() 90 { 91 if(lpdiKeyboard) 92 { 93 lpdiKeyboard->Unacquire(); 94 lpdiKeyboard->Release(); 95 lpdiKeyboard = NULL; 96 } 97 KeyboardAcquired = false; 98 return TRUE; 99 }100 101 BOOL Acquire(INT_PTR nPos = -1)102 {103 Unacquire();104 105 if(lpDirectInput == NULL)106 {107 OutputDebugString( _T("lpDirectInput is NULL./n") );108 return FALSE;109 }110 111 GUID KeyboardGUID = GUID_SysKeyboard;112 if(nPos >=0 && nPos < m_KeyboInstance_Array.GetSize())113 {114 KeyboardGUID = m_KeyboInstance_Array.GetAt(nPos)->guidInstance;115 }116 117 // try to create keyboard device118 if(lpDirectInput->CreateDevice(KeyboardGUID, &lpdiKeyboard, NULL) != DI_OK ) //GUID_SysKeyboard119 {120 OutputDebugString( _T("Failed to create keyboard device./n") );121 Unacquire();122 return FALSE;123 }124 125 // set kbd cooperative level126 if (lpdiKeyboard->SetCooperativeLevel(hMainWindow, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE) != DI_OK)127 {128 OutputDebugString( _T("Failed to set keyboard cooperative level./n") );129 Unacquire();130 return FALSE;131 }132 133 // set kbd data format134 if (lpdiKeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK)135 {136 OutputDebugString( _T("Failed to set keyboard data format./n") );137 Unacquire();138 return FALSE;139 }140 141 // set kbd buffer size142 DIPROPDWORD dipdw = { 0};143 dipdw.diph.dwSize = sizeof(DIPROPDWORD);144 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);145 dipdw.diph.dwObj = 0;146 dipdw.diph.dwHow = DIPH_DEVICE;147 dipdw.dwData = BUFFERCOUNT; // * sizeof(DIDEVICEOBJECTDATA);148 if (lpdiKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) != DI_OK) 149 {150 OutputDebugString( _T("Failed to set keyboard buffer size./n") );151 Unacquire();152 return FALSE;153 }154 155 // try to acquire the keyboard156 if (lpdiKeyboard->Acquire() != DI_OK)157 {158 OutputDebugString( _T("Failed to acquire the keyboard./n") );159 Unacquire();160 return FALSE;161 }162 163 KeyboardAcquired = TRUE;164 return TRUE; 165 }166 167 BOOL ReacquireInput(void)168 {169 //the keyboard170 if(lpdiKeyboard != NULL)171 {172 lpdiKeyboard->Acquire();173 }174 else175 {176 // keyboard device has not been created.177 return FALSE;178 }179 // if we get here, we are acquired again180 KeyboardAcquired = TRUE;181 182 return TRUE;183 } // ReacquireInputDevices()184 185 BOOL PollKeyboard(void) //Reads the keyboard state186 {187 if(lpdiKeyboard && KeyboardAcquired)188 {189 BYTE diKeys[257] = { 0};190 if (lpdiKeyboard->GetDeviceState(256, &diKeys) == DI_OK)191 {192 if(diKeys[DIK_LWIN] & 0x80) /* Left Windows key */193 {194 }195 if(diKeys[DIK_RWIN] & 0x80) /* Right Windows key */196 {197 }198 199 return TRUE; // success200 }201 }202 return FALSE;203 } // PollKeyboard()204 205 HRESULT ReadKeyboardInput(void)206 {207 HRESULT hRes = DI_OK;208 if(KeyboardAcquired)209 {210 DIDEVICEOBJECTDATA KbdBuffer[BUFFERCOUNT] = { 0};211 DWORD dwItems = BUFFERCOUNT;212 hRes = lpdiKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),213 KbdBuffer, &dwItems, 0);214 if(hRes == DI_OK || hRes == DI_BUFFEROVERFLOW)215 {216 217 for (DWORD k = 0; k < dwItems; k++)218 {219 LPDIDEVICEOBJECTDATA lpdidod = &KbdBuffer[k];220 221 TCHAR VKey = MapVirtualKey(lpdidod->dwOfs, 3); //映射到虚拟键222 ProcessInputKey(VKey); //处理输入223 224 CString dbgStr, tmpStr;225 dbgStr.Format(_T("%d"), lpdidod->dwSequence);226 tmpStr.Format(_T(". Scan code 0x%04X"), lpdidod->dwOfs);227 dbgStr += tmpStr; 228 dbgStr += (lpdidod->dwData & 0x80)? _T(" pressed ") : _T(" released "); 229 tmpStr.Format(_T(". Age: %d ms"), GetTickCount() - lpdidod->dwTimeStamp);230 dbgStr += tmpStr;231 dbgStr += _T("/n");232 OutputDebugString(dbgStr); 233 }234 }235 else if(hRes == DIERR_INPUTLOST)236 {237 ReacquireInput(); 238 hRes = S_FALSE;239 } 240 }241 return hRes;242 }243 244 245 246 CDInputKeyboard()247 {248 hMainWindow = NULL;249 lpDirectInput = NULL;250 lpdiKeyboard = NULL;251 KeyboardAcquired = 0;252 KeyboardFound = 0;253 m_KeyboInstance_Array.RemoveAll();254 }255 256 virtual ~CDInputKeyboard()257 {258 if(lpdiKeyboard)259 {260 lpdiKeyboard->Unacquire();261 lpdiKeyboard->Release();262 lpdiKeyboard = NULL;263 }264 265 if(lpDirectInput)266 {267 lpDirectInput->Release();268 lpDirectInput = NULL;269 }270 271 RemoveGUID();272 }273 274 275 };