Avionics
Dropship Simulator
Keyboard.cpp
Go to the documentation of this file.
1 
3 #include "Keyboard.h"
4 
5 namespace Devices
6 {
7  void Keyboard::BufferProc(bool bEnterKey)
8  {
9  for (UINT i = 0; i < keyboardConfig->buffers.size(); i++)
10  {
11  if (_strcmpi(buffer, keyboardConfig->buffers.at(i).input.c_str()) == 0 && bEnterKey == keyboardConfig->buffers.at(i).requireEnter)
12  {
13  bus->AppendCommands(&keyboardConfig->buffers.at(i).commands);
14  buffer[0] = 0;
15  }
16  }
17  }
18 
19  void Keyboard::Initialize(Logger* prmLogger, KeyboardConfig* prmKeyboardConfig, Bus* prmBus, LPDIRECTINPUT8 g_pDI)
20  {
21  logger = prmLogger;
22  bus = prmBus;
23  keyboardConfig = prmKeyboardConfig;
24 
25  HRESULT hr;
26 
27  logger->Log("Keyboard::Initialize Calling EnumDevices...", Logger::Info);
28  if (FAILED(hr = g_pDI->EnumDevices(DI8DEVCLASS_KEYBOARD, EnumKeyboardsCallback, this, DIEDFL_ATTACHEDONLY)))
29  {
30  logger->Log("Keyboard::Initialize EnumDevices failed!", Logger::Error, hr);
31  keyboardConfig->enable = false;
32  return;
33  }
34 
35  // Obtain an interface to the enumerated keyboard.
36  if (FAILED(hr = g_pDI->CreateDevice(keyboardConfig->serialno, &g_pKeyboard, NULL)))
37  {
38  logger->Log("Keyboard::Initialize CreateDevice failed!", Logger::Error, hr);
39  keyboardConfig->enable = false;
40  return;
41  }
42 
43  // Set the data format to "simple keyboard" - a predefined data format
44  // A data format specifies which controls on a device we are interested in,
45  // and how they should be reported. This tells DInput that we will be
46  // passing a DIKEYSTATE structure to IDirectInputDevice::GetDeviceState().
47  if (FAILED(hr = g_pKeyboard->SetDataFormat(&c_dfDIKeyboard)))
48  {
49  logger->Log("Keyboard::SetDataFormat failed!", Logger::Error, hr);
50  keyboardConfig->enable = false;
51  return;
52  }
53 
54  // Set the cooperative level to let DInput know how this device should
55  // interact with the system and with other DInput applications.
56  if (FAILED(hr = g_pKeyboard->SetCooperativeLevel(NULL, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
57  {
58  logger->Log("Keyboard::SetCooperativeLevel failed!", Logger::Error, hr);
59  keyboardConfig->enable = false;
60  return;
61  }
62 
63  if (FAILED(hr = g_pKeyboard->Acquire()))
64  {
65  logger->Log("Keyboard::Acquire failed!", Logger::Error, hr);
66  keyboardConfig->enable = false;
67  return;
68  }
69 
70  timeSinceLastKeypress = 0.0f;
71  buffer[0] = 0;
72  hkl = GetKeyboardLayout(0);
73 
74  ZeroMemory(oldKeyboardState, 256);
75 
76 #pragma region Startup Commands
77  Command command;
78  command.name = "SetNumLockState";
79  command.bvalue = true;
80  bus->commandStream.push_back(command);
81 #pragma endregion
82  }
83 
84  void Keyboard::FrameMove(float fElapsed)
85  {
86  HRESULT hr;
87 
88  memcpy(oldKeyboardState, keyboardState, 256);
89  if (std::find(hwnds.begin(), hwnds.end(), GetForegroundWindow()) != hwnds.end())
90  {
91  if (FAILED(hr = g_pKeyboard->GetDeviceState(256, keyboardState)))
92  {
93  logger->Log("Keyboard::FrameMove GetDeviceState failed!", Logger::Error, hr);
94  if (FAILED(hr = g_pKeyboard->Acquire()))
95  {
96  logger->Log("Keyboard::FrameMove Acquire failed!", Logger::Error, hr);
97  return;
98  }
99  if (FAILED(hr = g_pKeyboard->GetDeviceState(256, keyboardState)))
100  {
101  logger->Log("Keyboard::FrameMove GetDeviceState failed again!", Logger::Error, hr);
102  return;
103  }
104  }
105  }
106  else
107  {
108  ZeroMemory(keyboardState, 256);
109  }
110 
111  alt = (keyboardState[DIK_LMENU] & 0x80) || (keyboardState[DIK_RMENU] & 0x80);
112  ctrl = (keyboardState[DIK_LCONTROL] & 0x80) || (keyboardState[DIK_RCONTROL] & 0x80);
113  shift = (keyboardState[DIK_LSHIFT] & 0x80) || (keyboardState[DIK_RSHIFT] & 0x80);
114  for (UINT i = 0; i < 256; i++)
115  {
116  if (i == DIK_LMENU || i == DIK_RMENU)
117  {
118  continue; // handled above
119  }
120  if (i == DIK_LCONTROL || i == DIK_RCONTROL)
121  {
122  continue; // handled above
123  }
124  if (i == DIK_LSHIFT || i == DIK_RSHIFT)
125  {
126  continue; // handled above
127  }
128  if (i == DIK_CAPSLOCK)
129  {
130  continue; // ignored
131  }
132  if (i == DIK_NUMLOCK)
133  {
134  continue; // ignored
135  }
136 
137  if (keyboardState[i] & 0x80 && !(oldKeyboardState[i] & 0x80))
138  {
139  timeSinceLastKeypress = 0.0f;
140 
142  for (UINT j = 0; j < keyboardConfig->keys.size(); j++)
143  {
144  if (keyboardConfig->keys[j].input == i && !alt && !ctrl) // modifiers could be stored in configuration
145  {
146  char msg[99];
147  sprintf_s(msg, 99, "Keyboard::FrameMove Keypress %i adding commands!", i);
148  logger->Log(msg);
149  bus->AppendCommands(&keyboardConfig->keys[j].commands);
150  return;
151  }
152  }
153 
154  UINT vk = MapVirtualKeyEx(i, MAPVK_VSC_TO_VK, hkl);
155  if (!vk)
156  {
157  switch (i)
158  {
161  case 156:
162  vk = VK_RETURN;
163  break;
164  case 181:
165  vk = VK_DIVIDE;
166  break;
167  default:
168  char msg[99];
169  sprintf_s(msg, 99, "Keyboard::FrameMove Could not translate scancode %i into a VK", i);
170  logger->Log(msg, Logger::Warn);
171  return;
172  }
173  }
174 
175  // if we have a buffer then we check enter condition
176  if (keyboardConfig->endOfBufferKey == vk)
177  {
178  BufferProc(true);
179  buffer[0] = 0;
180  return;
181  }
182 
183  if (strlen(buffer) < sizeof(buffer) - 1)
184  {
185  if (vk == VK_BACK && strlen(buffer) > 0)
186  {
187  buffer[strlen(buffer) - 1] = 0;
188  }
189  else
190  {
192  char charBuffer[2] = {static_cast<char>(MapVirtualKeyEx(vk, MAPVK_VK_TO_CHAR, hkl)), 0};
193 
194  if (charBuffer[0])
195  {
196  strcat_s(buffer, sizeof(buffer), charBuffer);
197  BufferProc(false);
198  return;
199  }
200  }
201  }
202 
203  if (strlen(buffer) < sizeof(buffer) - 1)
204  {
205  // manual mapping
206  if (LOWORD(GetKeyState(VK_NUMLOCK)) != 0) // numlock is on
207  {
208  switch (vk)
209  {
210  case VK_PRIOR:
211  strcat_s(buffer, sizeof(buffer), "9");
212  BufferProc(false);
213  return;
214  case VK_UP:
215  strcat_s(buffer, sizeof(buffer), "8");
216  BufferProc(false);
217  return;
218  case VK_HOME:
219  strcat_s(buffer, sizeof(buffer), "7");
220  BufferProc(false);
221  return;
222  case VK_RIGHT:
223  strcat_s(buffer, sizeof(buffer), "6");
224  BufferProc(false);
225  return;
226  case VK_CLEAR:
227  strcat_s(buffer, sizeof(buffer), "5");
228  BufferProc(false);
229  return;
230  case VK_LEFT:
231  strcat_s(buffer, sizeof(buffer), "4");
232  BufferProc(false);
233  return;
234  case VK_NEXT:
235  strcat_s(buffer, sizeof(buffer), "3");
236  BufferProc(false);
237  return;
238  case VK_DOWN:
239  strcat_s(buffer, sizeof(buffer), "2");
240  BufferProc(false);
241  return;
242  case VK_END:
243  strcat_s(buffer, sizeof(buffer), "1");
244  BufferProc(false);
245  return;
246  case VK_INSERT:
247  strcat_s(buffer, sizeof(buffer), "0");
248  BufferProc(false);
249  return;
250  case VK_DELETE:
251  strcat_s(buffer, sizeof(buffer), ".");
252  BufferProc(false);
253  return;
254  }
255  }
256  }
257 
259  char boo[99];
260  sprintf_s(boo, 99, "Keyboard::FrameMove Unhandled SC %i (VK %02x) ctrl%i alt%i shift%i", i, vk, ctrl, alt, shift);
261  logger->Log(boo);
262  }
263  }
264 
265  timeSinceLastKeypress += fElapsed;
267  {
268  buffer[0] = 0;
269  }
270 
271  for (UINT i = 0; i < bus->commandStream.size(); i++)
272  {
273  Command command = bus->commandStream.at(i);
274  if (command.delay != 0.0f) continue;
275 
276  if (command.name == "SetNumLockState")
277  {
278  SetNumLock(command.bvalue);
279  bus->commandStream.erase(bus->commandStream.begin() + i);
280  }
281  }
282  }
283 
284  void Keyboard::SetNumLock(bool setState)
285  {
286  bool curState = LOWORD(GetKeyState(VK_NUMLOCK)) != 0;
287  if (curState != setState)
288  {
289  // Simulate a key press
290  keybd_event(VK_NUMLOCK, DIK_NUMLOCK, KEYEVENTF_EXTENDEDKEY | 0, 0);
291 
292  // Simulate a key release
293  keybd_event(VK_NUMLOCK, DIK_NUMLOCK, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
294  }
295  }
296 
297  //-----------------------------------------------------------------------------
298  // Name: EnumKeyboardsCallback()
299  // Desc: Called once for each enumerated keyboard. If we find one, create a
300  // device interface on it so we can play with it.
301  //-----------------------------------------------------------------------------
302  BOOL CALLBACK Keyboard::EnumKeyboardsCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext)
303  {
304  Keyboard* keyboard = static_cast<Keyboard*>(pContext);
305 
306  char msg[199];
307  sprintf_s(msg, 199, "Keyboard::EnumKeyboardsCallback {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
308  pdidInstance->guidInstance.Data1, pdidInstance->guidInstance.Data2, pdidInstance->guidInstance.Data3,
309  pdidInstance->guidInstance.Data4[0], pdidInstance->guidInstance.Data4[1], pdidInstance->guidInstance.Data4[2], pdidInstance->guidInstance.Data4[3],
310  pdidInstance->guidInstance.Data4[4], pdidInstance->guidInstance.Data4[5], pdidInstance->guidInstance.Data4[6], pdidInstance->guidInstance.Data4[7]);
311 
312  if (keyboard->keyboardConfig->serialno == GUID_NULL)
313  keyboard->keyboardConfig->serialno = pdidInstance->guidInstance;
314 
315  keyboard->logger->Log(msg);
316 
317  return DIENUM_CONTINUE;
318  }
319 
321  {
322  if (g_pKeyboard)
323  g_pKeyboard->Unacquire();
324 
325  // Release any DirectInput objects.
326  SAFE_RELEASE(g_pKeyboard);
327  }
328 }
LPDIRECTINPUTDEVICE8 g_pKeyboard
Definition: Keyboard.h:43
char buffer[10]
Definition: Keyboard.h:62
void BufferProc(bool bEnterKey)
Definition: Keyboard.cpp:7
unsigned char keyboardState[256]
contains state of keyboard
Definition: Keyboard.h:50
static BOOL CALLBACK EnumKeyboardsCallback(const DIDEVICEINSTANCE *pdidInstance, VOID *pContext)
Definition: Keyboard.cpp:302
std::vector< Command > commandStream
Definition: Bus.h:20
Definition: Logger.h:5
LPDIRECTINPUT8 g_pDI
Definition: Avionics.cpp:16
void AppendCommands(std::vector< Command > *commands)
Definition: Bus.cpp:41
okay, the portable keyboard numbers don&#39;t work like the outside keypad because the outside keypad is ...
Definition: Analog.cpp:3
void FrameMove(float fElapsed)
Definition: Keyboard.cpp:84
Definition: Bus.h:12
std::string name
command name
Definition: Command.h:11
static void SetNumLock(bool bState)
Definition: Keyboard.cpp:284
KeyboardConfig * keyboardConfig
Definition: Keyboard.h:59
Definition: Command.h:5
unsigned char oldKeyboardState[256]
contains previous state of keyboard
Definition: Keyboard.h:52
void Log(const char *msg, Level level=Info, int errorCode=0)
These have to be in this order.
Definition: Logger.cpp:16
bool bvalue
Definition: Command.h:23
std::vector< Key > keys
Definition: Keyboard.h:37
void Initialize(Logger *logger, KeyboardConfig *config, Bus *prmBus, LPDIRECTINPUT8 g_pDI)
Definition: Keyboard.cpp:19
Logger * logger
Definition: Keyboard.h:57
std::vector< Buffer > buffers
Definition: Keyboard.h:29
float delay
wait number of seconds before executing command
Definition: Command.h:8
std::vector< HWND > hwnds
Definition: Keyboard.h:68
float timeSinceLastKeypress
Definition: Keyboard.h:61
Devices::Keyboard keyboard
Definition: Avionics.cpp:27