1 // DInputKeyboard.h: interface for the CDInputKeyboard class. 2 // 3 ////////////////////////////////////////////////////////////////////// 4 5 #pragma once 6 7 #define DIRECTINPUT_VERSION 0x800 8 #include <afxtempl.h> 9 #include <dinput.h> 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 <CPtrArray, LPDIDEVICEINSTANCE> 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 device 118 if(lpDirectInput->CreateDevice(KeyboardGUID, &lpdiKeyboard, NULL) != DI_OK ) //GUID_SysKeyboard 119 { 120 OutputDebugString( _T("Failed to create keyboard device./n") ); 121 Unacquire(); 122 return FALSE; 123 } 124 125 // set kbd cooperative level 126 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 format 134 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 size 142 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 keyboard 156 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 keyboard 170 if(lpdiKeyboard != NULL) 171 { 172 lpdiKeyboard->Acquire(); 173 } 174 else 175 { 176 // keyboard device has not been created. 177 return FALSE; 178 } 179 // if we get here, we are acquired again 180 KeyboardAcquired = TRUE; 181 182 return TRUE; 183 } // ReacquireInputDevices() 184 185 BOOL PollKeyboard(void) //Reads the keyboard state 186 { 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; // success 200 } 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 };