| // DirectInputBufferedKeyboardTest.cpp : Defines the entry point for the application. |
| // |
| |
| #include "stdafx.h" |
| #include "DirectInputBufferedKeyboardTest.h" |
| #define DIRECTINPUT_VERSION 0x0800 |
| #include <dinput.h> |
| #include <wrl/client.h> |
| #include <exception> |
| #include <string> |
|
| #pragma comment(lib, "dxguid.lib") |
| #pragma comment(lib, "dinput8.lib") |
|
| #define MAX_LOADSTRING 100 |
| |
| void ThrowIfFailed(HRESULT hr) |
| { |
| if (FAILED(hr)) |
| { |
| throw std::exception(); |
| } |
| } |
| |
| // Global Variables: |
| HINSTANCE hInst; // current instance |
| HWND g_mainHWND; |
| Microsoft::WRL::ComPtr<IDirectInput8> dInput; |
| Microsoft::WRL::ComPtr<IDirectInputDevice8> dInputDeviceKeyboard; |
| |
| TCHAR szTitle[MAX_LOADSTRING]; // The title bar text |
| TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name |
| |
| // Forward declarations of functions included in this code module: |
| ATOM MyRegisterClass(HINSTANCE hInstance); |
| BOOL InitInstance(HINSTANCE, int); |
| LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); |
| INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); |
| |
| int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, |
| _In_opt_ HINSTANCE hPrevInstance, |
| _In_ LPTSTR lpCmdLine, |
| _In_ int nCmdShow) |
| { |
| UNREFERENCED_PARAMETER(hPrevInstance); |
| UNREFERENCED_PARAMETER(lpCmdLine); |
| |
| // TODO: Place code here. |
| MSG msg; |
| HACCEL hAccelTable; |
| |
| // Initialize global strings |
| LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); |
| LoadString(hInstance, IDC_DIRECTINPUTBUFFEREDKEYBOARDTEST, szWindowClass, MAX_LOADSTRING); |
| MyRegisterClass(hInstance); |
| |
| // Perform application initialization: |
| if (!InitInstance (hInstance, nCmdShow)) |
| { |
| return FALSE; |
| } |
| |
| hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DIRECTINPUTBUFFEREDKEYBOARDTEST)); |
| |
| ThrowIfFailed( |
| DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8W, &dInput, NULL) |
| ); |
| |
| ThrowIfFailed( |
| dInput->CreateDevice(GUID_SysKeyboard, &dInputDeviceKeyboard, NULL) |
| ); |
| |
| ThrowIfFailed( |
| dInputDeviceKeyboard->SetCooperativeLevel(g_mainHWND, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE) |
| ); |
| |
| ThrowIfFailed( |
| dInputDeviceKeyboard->SetDataFormat(&c_dfDIKeyboard) |
| ); |
| |
| DIPROPDWORD dipdw; |
| dipdw.diph.dwSize = sizeof(DIPROPDWORD); |
| dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); |
| dipdw.diph.dwObj = 0; |
| dipdw.diph.dwHow = DIPH_DEVICE; |
| dipdw.dwData = 10; |
| |
| ThrowIfFailed( |
| dInputDeviceKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) |
| ); |
| |
| ThrowIfFailed( |
| dInputDeviceKeyboard->Acquire() |
| ); |
| |
| // Main message loop: |
| while (GetMessage(&msg, NULL, 0, 0)) |
| { |
| if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) |
| { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| } |
| |
| ThrowIfFailed( |
| dInputDeviceKeyboard->Unacquire() |
| ); |
| |
| return (int) msg.wParam; |
| } |
| |
| |
| |
| // |
| // FUNCTION: MyRegisterClass() |
| // |
| // PURPOSE: Registers the window class. |
| // |
| ATOM MyRegisterClass(HINSTANCE hInstance) |
| { |
| WNDCLASSEX wcex; |
| |
| wcex.cbSize = sizeof(WNDCLASSEX); |
| |
| wcex.style = CS_HREDRAW | CS_VREDRAW; |
| wcex.lpfnWndProc = WndProc; |
| wcex.cbClsExtra = 0; |
| wcex.cbWndExtra = 0; |
| wcex.hInstance = hInstance; |
| wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DIRECTINPUTBUFFEREDKEYBOARDTEST)); |
| wcex.hCursor = LoadCursor(NULL, IDC_ARROW); |
| wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); |
| wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DIRECTINPUTBUFFEREDKEYBOARDTEST); |
| wcex.lpszClassName = szWindowClass; |
| wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); |
| |
| return RegisterClassEx(&wcex); |
| } |
| |
| // |
| // FUNCTION: InitInstance(HINSTANCE, int) |
| // |
| // PURPOSE: Saves instance handle and creates main window |
| // |
| // COMMENTS: |
| // |
| // In this function, we save the instance handle in a global variable and |
| // create and display the main program window. |
| // |
| BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) |
| { |
| HWND hWnd; |
| |
| hInst = hInstance; // Store instance handle in our global variable |
| |
| hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, |
| CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); |
| |
| if (!hWnd) |
| { |
| return FALSE; |
| } |
| |
| ShowWindow(hWnd, nCmdShow); |
| UpdateWindow(hWnd); |
| |
| g_mainHWND = hWnd; |
| |
| return TRUE; |
| } |
| |
| // |
| // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) |
| // |
| // PURPOSE: Processes messages for the main window. |
| // |
| // WM_COMMAND - process the application menu |
| // WM_PAINT - Paint the main window |
| // WM_DESTROY - post a quit message and return |
| // |
| // |
| LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| int wmId, wmEvent; |
| PAINTSTRUCT ps; |
| HDC hdc; |
| |
| static std::wstring diKeyPressAndReleaseMsgs; |
| |
| if (dInputDeviceKeyboard != nullptr) |
| { |
| DIDEVICEOBJECTDATA rgdod[10]; |
| DWORD dwItems = 10; |
| HRESULT hr; |
| hr = dInputDeviceKeyboard->GetDeviceData( |
| sizeof(DIDEVICEOBJECTDATA), |
| rgdod, |
| &dwItems, |
| 0); |
| |
| if (SUCCEEDED(hr)) |
| { |
| if (diKeyPressAndReleaseMsgs.length() > 1000) |
| { |
| diKeyPressAndReleaseMsgs.clear(); |
| } |
| for (DWORD i = 0; i < dwItems; ++i) |
| { |
| auto item = rgdod[i]; |
| diKeyPressAndReleaseMsgs.append(L" The following key was " |
| ).append((item.dwData & 0x80) ? L"pressed: " : L"released: " |
| ).append(std::to_wstring(item.dwOfs) |
| ).append(L".\n" |
| ); |
| |
| InvalidateRect(g_mainHWND, NULL, TRUE); |
| } |
| // dwItems = Number of elements read (could be zero). |
| if (hr == DI_BUFFEROVERFLOW) |
| { |
| // Buffer had overflowed. |
| OutputDebugString(L"Overflow - more than 10 items were pending.\n"); |
| } |
| } |
| else |
| { |
| ThrowIfFailed(hr); |
| } |
| } |
| |
| switch (message) |
| { |
| case WM_COMMAND: |
| wmId = LOWORD(wParam); |
| wmEvent = HIWORD(wParam); |
| // Parse the menu selections: |
| switch (wmId) |
| { |
| case IDM_ABOUT: |
| DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); |
| break; |
| case IDM_EXIT: |
| DestroyWindow(hWnd); |
| break; |
| default: |
| return DefWindowProc(hWnd, message, wParam, lParam); |
| } |
| break; |
| case WM_PAINT: |
| RECT rc; |
| SetRect(&rc, 10, 10, 500, 500); |
| hdc = BeginPaint(hWnd, &ps); |
| SetDCBrushColor(hdc, RGB(0,0,0)); |
| DrawText(hdc, diKeyPressAndReleaseMsgs.c_str(), |
| static_cast<int>(diKeyPressAndReleaseMsgs.length()), |
| &rc, |
| DT_LEFT | DT_WORDBREAK |
| ); |
| // TODO: Add any drawing code here... |
| EndPaint(hWnd, &ps); |
| break; |
| case WM_DESTROY: |
| PostQuitMessage(0); |
| break; |
| default: |
| return DefWindowProc(hWnd, message, wParam, lParam); |
| } |
| return 0; |
| } |
| |
| // Message handler for about box. |
| INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| UNREFERENCED_PARAMETER(lParam); |
| switch (message) |
| { |
| case WM_INITDIALOG: |
| return (INT_PTR)TRUE; |
| |
| case WM_COMMAND: |
| if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) |
| { |
| EndDialog(hDlg, LOWORD(wParam)); |
| return (INT_PTR)TRUE; |
| } |
| break; |
| } |
| return (INT_PTR)FALSE; |
| } |
| |