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 };