// 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(); } };