Lugdunum  0.1.0
WindowImplWin32.cpp
Go to the documentation of this file.
1 #include <cstdlib>
4 
5 namespace lug {
6 namespace Window {
7 namespace priv {
8 
9 uint8_t WindowImpl::_windowCount = 0;
10 WindowImpl* WindowImpl::_fullscreenWindow = nullptr;
11 
12 WindowImpl::WindowImpl(Window* win) : _parent{win} {}
13 
15  // Destroy the custom icon, if any
16  if (_icon) {
17  DestroyIcon(_icon);
18  }
19 
20  if (!_callback) {
21  // Destroy the window
22  if (_handle) {
23  DestroyWindow(_handle);
24  }
25 
26  // Decrement the window count
27  _windowCount--;
28 
29  // Unregister window class if we were the last window
30  if (_windowCount == 0) {
31  UnregisterClassW(className, GetModuleHandleW(nullptr));
32  }
33  } else {
34  // The window is external: remove the hook on its message callback
35  SetWindowLongPtrW(_handle, GWLP_WNDPROC, _callback);
36  }
37 }
38 
39 bool WindowImpl::init(const Window::InitInfo& initInfo) {
40 
41  // Register the window class at first call
42  if (_windowCount == 0) {
43  _hinstance = GetModuleHandleW(nullptr);
44  registerWindow();
45  }
46 
47  // Compute position and size
48  HDC screenDC = GetDC(nullptr);
49  const uint16_t left = static_cast<uint16_t>(GetDeviceCaps(screenDC, HORZRES) - initInfo.width) / 2;
50  const uint16_t top = static_cast<uint16_t>(GetDeviceCaps(screenDC, VERTRES) - initInfo.height) / 2;
51  ReleaseDC(nullptr, screenDC);
52 
53  // Choose the window style according to the Style parameter
54  DWORD win32Style = WS_VISIBLE;
55 
56  if (initInfo.style == Style::None) {
57  win32Style |= WS_POPUP;
58  } else {
59  if ((initInfo.style & Style::Titlebar) == Style::Titlebar) {
60  win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
61  }
62 
63  if ((initInfo.style & Style::Resize) == Style::Resize) {
64  win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
65  }
66 
67  if ((initInfo.style & Style::Close) == Style::Close) {
68  win32Style |= WS_SYSMENU;
69  }
70  }
71 
72  _fullscreen = (initInfo.style & Style::Fullscreen) == Style::Fullscreen ? true : false;
73  // In windowed mode, adjust width and height so that the window will have the requested client area
74  RECT rectangle = { 0, 0, initInfo.width, initInfo.height };
75 
76  if (!_fullscreen) {
77  AdjustWindowRect(&rectangle, win32Style, false);
78  }
79 
80 #pragma warning(push)
81 #pragma warning(disable : 4996)
82  std::vector<wchar_t> realTitle(initInfo.title.length() + 1); // Convert a const char * to a wchar_t
83  mbstowcs(&realTitle[0], initInfo.title.c_str(), initInfo.title.length() + 1);
84 #pragma warning(pop)
85 
86  _handle = CreateWindowW(
87  className,
88  &realTitle[0],
89  win32Style,
90  left,
91  top,
92  rectangle.right - rectangle.left,
93  rectangle.bottom - rectangle.top,
94  nullptr,
95  nullptr,
96  GetModuleHandleW(nullptr),
97  this);
98 
99  // Switch to full-screen if requested
100  if (_fullscreen) {
101  if (!activateFullscreen()) {
102  LUG_LOG.error("WindowImpl::Win32::Init Can't activate full-screen");
103  }
104  }
105 
106  setMouseCursorVisible(true);
107 
108  // Increment window count
109  _windowCount++;
110  return true;
111 }
112 
113 void WindowImpl::close() {
114  // Restore the previous video mode (in case we were running in fullscreen)
115  if (_fullscreenWindow == this) {
116  ChangeDisplaySettingsW(nullptr, 0);
117  _fullscreenWindow = nullptr;
118  }
119 
120  // No longer capture the cursor
121  ReleaseCapture();
122 }
123 
124 static Keyboard::Key vkToLugKey(WPARAM key) {
125  switch (key) {
126  case VK_F1:
127  return Keyboard::Key::F1; // The F1 key
128  case VK_F2:
129  return Keyboard::Key::F2; // The F2 key
130  case VK_F3:
131  return Keyboard::Key::F3; // The F3 key
132  case VK_F4:
133  return Keyboard::Key::F4; // The F4 key
134  case VK_F5:
135  return Keyboard::Key::F5; // The F5 key
136  case VK_F6:
137  return Keyboard::Key::F6; // The F6 key
138  case VK_F7:
139  return Keyboard::Key::F7; // The F7 key
140  case VK_F8:
141  return Keyboard::Key::F8; // The F8 key
142  case VK_F9:
143  return Keyboard::Key::F9; // The F9 key
144  case VK_F10:
145  return Keyboard::Key::F10; // The F10 key
146  case VK_F11:
147  return Keyboard::Key::F11; // The F11 key
148  case VK_F12:
149  return Keyboard::Key::F12; // The F12 key
150  case VK_F13:
151  return Keyboard::Key::F13; // The F13 key
152  case VK_F14:
153  return Keyboard::Key::F14; // The F14 key
154  case VK_F15:
155  return Keyboard::Key::F15; // The F15 key
156 
157  case 'A':
158  return Keyboard::Key::A; // The A key
159  case 'B':
160  return Keyboard::Key::B; // The B key
161  case 'C':
162  return Keyboard::Key::C; // The C key
163  case 'D':
164  return Keyboard::Key::D; // The D key
165  case 'E':
166  return Keyboard::Key::E; // The E key
167  case 'F':
168  return Keyboard::Key::F; // The F key
169  case 'G':
170  return Keyboard::Key::G; // The G key
171  case 'H':
172  return Keyboard::Key::H; // The H key
173  case 'I':
174  return Keyboard::Key::I; // The I key
175  case 'J':
176  return Keyboard::Key::J; // The J key
177  case 'K':
178  return Keyboard::Key::K; // The K key
179  case 'L':
180  return Keyboard::Key::L; // The L key
181  case 'M':
182  return Keyboard::Key::M; // The M key
183  case 'N':
184  return Keyboard::Key::N; // The N key
185  case 'O':
186  return Keyboard::Key::O; // The O key
187  case 'P':
188  return Keyboard::Key::P; // The P key
189  case 'Q':
190  return Keyboard::Key::Q; // The Q key
191  case 'R':
192  return Keyboard::Key::R; // The R key
193  case 'S':
194  return Keyboard::Key::S; // The S key
195  case 'T':
196  return Keyboard::Key::T; // The T key
197  case 'U':
198  return Keyboard::Key::U; // The U key
199  case 'V':
200  return Keyboard::Key::V; // The V key
201  case 'W':
202  return Keyboard::Key::W; // The W key
203  case 'X':
204  return Keyboard::Key::X; // The X key
205  case 'Y':
206  return Keyboard::Key::Y; // The Y key
207  case 'Z':
208  return Keyboard::Key::Z; // The Z key
209 
210  case '0':
211  return Keyboard::Key::Num0; // The 0 key
212  case '1':
213  return Keyboard::Key::Num1; // The 1 key
214  case '2':
215  return Keyboard::Key::Num2; // The 2 key
216  case '3':
217  return Keyboard::Key::Num3; // The 3 key
218  case '4':
219  return Keyboard::Key::Num4; // The 4 key
220  case '5':
221  return Keyboard::Key::Num5; // The 5 key
222  case '6':
223  return Keyboard::Key::Num6; // The 6 key
224  case '7':
225  return Keyboard::Key::Num7; // The 7 key
226  case '8':
227  return Keyboard::Key::Num8; // The 8 key
228  case '9':
229  return Keyboard::Key::Num9; // The 9 key
230 
231  case VK_ESCAPE:
232  return Keyboard::Key::Escape; // The Escape key
233 
234  case VK_LCONTROL:
235  return Keyboard::Key::LControl; // The left Control key
236  case VK_LSHIFT:
237  return Keyboard::Key::LShift; // The left Shift key
238  case VK_LMENU:
239  return Keyboard::Key::LAlt; // The left Alt key
240  case VK_LWIN:
241  return Keyboard::Key::LSystem; // The left OS specific key: window (Windows and Linux), apple (MacOS X), ...
242 
243  case VK_RCONTROL:
244  return Keyboard::Key::RControl; // The right Control key
245  case VK_RSHIFT:
246  return Keyboard::Key::RShift; // The right Shift key
247  case VK_RMENU:
248  return Keyboard::Key::RAlt; // The right Alt key
249  case VK_RWIN:
250  return Keyboard::Key::RSystem; // The right OS specific key: window (Windows and Linux), apple (MacOS X), ...
251 
252  case VK_APPS:
253  return Keyboard::Key::Menu; // The Menu key
254  case VK_OEM_4:
255  return Keyboard::Key::LBracket; // The [ key
256  case VK_OEM_6:
257  return Keyboard::Key::RBracket; // The ] key
258  case VK_OEM_1:
259  return Keyboard::Key::SemiColon; // The , key
260  case VK_OEM_COMMA:
261  return Keyboard::Key::Comma; // The , key
262  case VK_OEM_PERIOD:
263  return Keyboard::Key::Period; // The . key
264  case VK_OEM_7:
265  return Keyboard::Key::Quote; // The ' key
266  case VK_OEM_2:
267  return Keyboard::Key::Slash; // The / key
268  case VK_OEM_5:
269  return Keyboard::Key::BackSlash; // The \ key
270  case VK_OEM_3:
271  return Keyboard::Key::Tilde; // The ~ key
272  case VK_OEM_PLUS:
273  return Keyboard::Key::Equal; // The = key
274  case VK_OEM_MINUS:
275  return Keyboard::Key::Dash; // The - key
276  case VK_SPACE:
277  return Keyboard::Key::Space; // The Space key
278  case VK_RETURN:
279  return Keyboard::Key::Return; // The Return key
280 
281  case VK_ADD:
282  return Keyboard::Key::Add; // The + key
283  case VK_SUBTRACT:
284  return Keyboard::Key::Subtract; // The - key
285  case VK_MULTIPLY:
286  return Keyboard::Key::Multiply; // The * key
287  case VK_DIVIDE:
288  return Keyboard::Key::Divide; // The / key
289 
290  case VK_NUMPAD0:
291  return Keyboard::Key::Numpad0; // The numpad 0 key
292  case VK_NUMPAD1:
293  return Keyboard::Key::Numpad1; // The numpad 1 key
294  case VK_NUMPAD2:
295  return Keyboard::Key::Numpad2; // The numpad 2 key
296  case VK_NUMPAD3:
297  return Keyboard::Key::Numpad3; // The numpad 3 key
298  case VK_NUMPAD4:
299  return Keyboard::Key::Numpad4; // The numpad 4 key
300  case VK_NUMPAD5:
301  return Keyboard::Key::Numpad5; // The numpad 5 key
302  case VK_NUMPAD6:
303  return Keyboard::Key::Numpad6; // The numpad 6 key
304  case VK_NUMPAD7:
305  return Keyboard::Key::Numpad7; // The numpad 7 key
306  case VK_NUMPAD8:
307  return Keyboard::Key::Numpad8; // The numpad 8 key
308  case VK_NUMPAD9:
309  return Keyboard::Key::Numpad9; // The numpad 9 key
310 
311  case VK_BACK:
312  return Keyboard::Key::BackSpace; // The Backspace key
313  case VK_TAB:
314  return Keyboard::Key::Tab; // The Tabulation key
315  case VK_PRIOR:
316  return Keyboard::Key::PageUp; // The Page up key
317  case VK_NEXT:
318  return Keyboard::Key::PageDown; // The Page down key
319  case VK_END:
320  return Keyboard::Key::End; // The End key
321  case VK_HOME:
322  return Keyboard::Key::Home; // The Home key
323  case VK_INSERT:
324  return Keyboard::Key::Insert; // The Insert key
325  case VK_DELETE:
326  return Keyboard::Key::Delete; // The Delete key
327 
328  case VK_LEFT:
329  return Keyboard::Key::Left; // Left arrow
330  case VK_RIGHT:
331  return Keyboard::Key::Right; // Right arrow
332  case VK_UP:
333  return Keyboard::Key::Up; // Up arrow
334  case VK_DOWN:
335  return Keyboard::Key::Down; // Down arrow
336 
337  case VK_PAUSE:
338  return Keyboard::Key::Pause; // The Pause key
339  default:
340  return Keyboard::Key::Unknown;
341  }
342 }
343 
344 bool WindowImpl::pollEvent(Event& event) {
345  // We process the window events only if we own it
346  if (!_callback) {
347  MSG message;
348 
349  while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE)) {
350  TranslateMessage(&message);
351  DispatchMessageW(&message);
352  }
353  }
354 
355  if (!_events.empty()) {
356  event = _events.front();
357  _events.pop();
358  return true;
359  }
360 
361  return false;
362 }
363 
364 void WindowImpl::setKeyRepeat(bool state) {
365  _keyRepeat = state;
366 }
367 
368 void WindowImpl::setMouseCursorVisible(bool visible) {
369  _cursor = visible ? LoadCursor(nullptr, IDC_ARROW) : NULL;
370  SetCursor(_cursor);
371 }
372 
373 void WindowImpl::setMousePos(const Math::Vec2i& mousePosition) {
374  POINT mouseScreenPosition{mousePosition.x(), mousePosition.y()};
375  ClientToScreen(_handle, &mouseScreenPosition);
376  SetCursorPos(mouseScreenPosition.x, mouseScreenPosition.y);
377 }
378 
379 HWND WindowImpl::getHandle() const {
380  return _handle;
381 }
382 
383 HINSTANCE WindowImpl::getHinstance() const {
384  return _hinstance;
385 }
386 
387 void WindowImpl::processWindowEvents(UINT message, WPARAM wParam, LPARAM lParam) {
388  Event e;
389 
390  switch (message) {
391  case WM_SIZE:
393 
394  // The handle is not set on first call (window not yet created)
395  if (!_handle) {
396  return;
397  }
398 
399  RECT rect;
400 
401  if (GetClientRect(_handle, &rect)) {
402  _parent->_mode.width = static_cast<uint16_t>(rect.right - rect.left);
403  _parent->_mode.height = static_cast<uint16_t>(rect.bottom - rect.top);
404 
405  if (!_parent->_mode.width || !_parent->_mode.height) {
406  return;
407  }
408  } else {
409  LUG_LOG.error("WindowImpl::Win32::processWindowEvents Can't get window rect");
410  }
411  break;
412 
413  case WM_CLOSE:
415  break;
416 
417  case WM_DESTROY:
419  break;
420 
421  case WM_SETCURSOR:
422  // The mouse has moved, if the cursor is in our window we must refresh the cursor
423  if (LOWORD(lParam) == HTCLIENT)
424  SetCursor(_cursor);
425  break;
426 
427  case WM_KEYDOWN:
428  case WM_SYSKEYDOWN:
429  if (_keyRepeat || ((HIWORD(lParam) & KF_REPEAT) == 0)) {
431  configKeyEvent(e.key, wParam, lParam);
432  } else {
433  return;
434  }
435  break;
436 
437  case WM_KEYUP:
438  case WM_SYSKEYUP:
440  configKeyEvent(e.key, wParam, lParam);
441  break;
442 
443  case WM_CHAR:
444  if (_keyRepeat || ((lParam & (1 << 30)) == 0)) {
446  e.character.val = static_cast<wchar_t>(wParam);
447  } else {
448  return;
449  }
450  break;
451 
452  case WM_RBUTTONDOWN:
453  case WM_LBUTTONDOWN:
454  case WM_MBUTTONDOWN:
455  case WM_XBUTTONDOWN:
457  configMouseEvent(e.mouse, wParam, lParam);
458  configMouseButtonEvent(e.mouse, message, wParam, lParam);
459  break;
460 
461  case WM_RBUTTONUP:
462  case WM_LBUTTONUP:
463  case WM_MBUTTONUP:
464  case WM_XBUTTONUP:
466  configMouseEvent(e.mouse, wParam, lParam);
467  configMouseButtonEvent(e.mouse, message, wParam, lParam);
468  break;
469 
470  case WM_MOUSEMOVE:
473  configMouseEvent(e.mouse, wParam, lParam);
474  // NOTE: As long as we don't receive WM_MOUSELEAVE then the following code will never be called
475  if (_mouseIsIn == false) {
476  _mouseIsIn = true;
478  _parent->_mouseState[Mouse::Button::Left] = GetKeyState(VK_LBUTTON) & (1 << 15);
479  _parent->_mouseState[Mouse::Button::Middle] = GetKeyState(VK_MBUTTON) & (1 << 15);
480  _parent->_mouseState[Mouse::Button::Right] = GetKeyState(VK_RBUTTON) & (1 << 15);
481  }
482  break;
483 
484  // TODO: We need to use TrackMouseEvent to receive this event
485  case WM_MOUSELEAVE:
488  configMouseEvent(e.mouse, wParam, lParam);
489  _mouseIsIn = false;
490  break;
491 
492  case WM_MOUSEWHEEL:
493  case WM_MOUSEHWHEEL:
495  configMouseEvent(e.mouse, wParam, lParam);
496  configMouseWheelEvent(e.mouse, message, wParam);
497  break;
498 
499  default:
500  return;
501  }
502 
503  _events.push(std::move(e));
504 }
505 
507  // Register the window class with windows
508  WNDCLASSW windowClass = {};
509 
510  windowClass.style = 0;
511  windowClass.lpfnWndProc = &WindowImpl::onEvent;
512  windowClass.cbClsExtra = 0;
513  windowClass.cbWndExtra = 0;
514  windowClass.hInstance = _hinstance;
515  windowClass.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
516  windowClass.hCursor = NULL;
517  windowClass.hbrBackground = 0;
518  windowClass.lpszMenuName = nullptr;
519  windowClass.lpszClassName = className;
520 
521  if (!RegisterClassW(&windowClass)) {
522  MessageBox(nullptr, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
523  }
524 }
525 
527  DEVMODEW devMode{};
528 
529  devMode.dmSize = sizeof(devMode);
530  devMode.dmPelsWidth = _parent->_mode.width; // Selected Screen Width
531  devMode.dmPelsHeight = _parent->_mode.height; // Selected Screen Height
532  devMode.dmBitsPerPel = 32; // Selected Bits Per Pixel
533  devMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
534 
535  // Apply full-screen mode
536  if (ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
537  // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
538  if (MessageBox(nullptr, "Full-screen mode has failed to be initialized. Use Windowed Mode Instead?", "Warning", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) {
539  _fullscreen = false;
540  return false;
541  } else {
542  // Pop Up A Message Box Letting User Know The Program Is Closing.
543  MessageBox(nullptr, "Program Will Now Close.", "ERROR", MB_OK | MB_ICONSTOP);
544  return false;
545  }
546  }
547 
548  // Make the window flags compatible with full-screen mode
549  SetWindowLongW(_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
550  SetWindowLongW(_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
551 
552  // Resize the window so that it fits the entire screen
553  SetWindowPos(_handle, HWND_TOP, 0, 0, _parent->_mode.width, _parent->_mode.height, SWP_FRAMECHANGED);
554  ShowWindow(_handle, SW_SHOW);
555 
556  // Set "this" as the current fullscreen window
557  _fullscreenWindow = this;
558  return true;
559 }
560 
561 Keyboard::Key WindowImpl::getKeyCode(WPARAM wParam, LPARAM lParam) {
562  WPARAM new_vk = wParam;
563  // @see https://msdn.microsoft.com/en-us/library/ms646267%28v=vs.85%29.aspx#_win32_Keystroke_Message_Flags
564  UINT scancode = (lParam & 0x00ff0000) >> 16;
565  int extended = (lParam & 0x01000000) != 0;
566 
567  switch (wParam) {
568  case VK_SHIFT:
569  new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
570  break;
571  case VK_CONTROL:
572  new_vk = extended ? VK_RCONTROL : VK_LCONTROL;
573  break;
574  case VK_MENU:
575  new_vk = extended ? VK_RMENU : VK_LMENU;
576  break;
577  default:
578  // Not a key we map from generic to left/right specialized, just return it.
579  break;
580  }
581 
582  return vkToLugKey(new_vk);
583 }
584 
585 void WindowImpl::configKeyEvent(KeyEvent& key, WPARAM wParam, LPARAM lParam) {
586  key.code = getKeyCode(wParam, lParam);
587  key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
588  key.ctrl = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
589  key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
590  key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
591 }
592 
593 void WindowImpl::configMouseButtonEvent(MouseEvent& key, UINT message, WPARAM wParam, LPARAM lParam) {
594  switch (message) {
595  case WM_RBUTTONUP:
596  case WM_RBUTTONDOWN:
598  break;
599  case WM_LBUTTONUP:
600  case WM_LBUTTONDOWN:
602  break;
603  case WM_MBUTTONUP:
604  case WM_MBUTTONDOWN:
606  break;
607  case WM_XBUTTONUP:
608  case WM_XBUTTONDOWN:
609  key.code = HIWORD(wParam) == XBUTTON1 ? Mouse::Button::XButton1 : Mouse::Button::XButton2;
610  break;
611  default:
613  break;
614  }
615 
616  key.coord.x = static_cast<int32_t>(LOWORD(lParam));
617  key.coord.y = static_cast<int32_t>(HIWORD(lParam));
618 }
619 
620 void WindowImpl::configMouseEvent(MouseEvent & mouse, WPARAM wParam, LPARAM lParam) {
621  mouse.ctrl = false;
622  mouse.shift = false;
623  mouse.left = false;
624  mouse.middle = false;
625  mouse.right = false;
626  mouse.x1 = false;
627  mouse.x2 = false;
628 
629  getMouseCoord(mouse, lParam);
630  getMouseEventModifier(mouse, wParam);
631 }
632 
633 void WindowImpl::getMouseEventModifier(MouseEvent & mouse, WPARAM wParam) {
634  int keyModifier = GET_KEYSTATE_WPARAM(wParam);
635 
636  if (keyModifier & MK_CONTROL) {
637  mouse.ctrl = true;
638  }
639 
640  if (keyModifier & MK_SHIFT) {
641  mouse.shift = true;
642  }
643 
644  if (keyModifier & MK_LBUTTON) {
645  mouse.left = true;
646  }
647 
648  if (keyModifier & MK_MBUTTON) {
649  mouse.middle = true;
650  }
651 
652  if (keyModifier & MK_RBUTTON) {
653  mouse.right = true;
654  }
655 
656  if (keyModifier & MK_XBUTTON1) {
657  mouse.x1 = true;
658  }
659 
660  if (keyModifier & MK_XBUTTON2) {
661  mouse.x2 = true;
662  }
663 }
664 
665 void WindowImpl::getMouseCoord(MouseEvent & mouse, LPARAM lParam) {
666  mouse.coord.x = static_cast<int32_t>(LOWORD(lParam));
667  mouse.coord.y = static_cast<int32_t>(HIWORD(lParam));
668 }
669 
670 void WindowImpl::configMouseWheelEvent(MouseEvent & mouse, UINT message, WPARAM wParam)
671 {
672  double xOffset = 0.0;
673  double yOffset = 0.0;
674 
675  if (message == WM_MOUSEWHEEL) {
676  xOffset = GET_WHEEL_DELTA_WPARAM(wParam);
677  } else if (message == WM_MOUSEHWHEEL) {
678  yOffset = GET_WHEEL_DELTA_WPARAM(wParam);
679  }
680  mouse.scrollOffset.xOffset = xOffset;
681  mouse.scrollOffset.yOffset = yOffset;
682 }
683 
684 LRESULT CALLBACK WindowImpl::onEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
685  // Associate handle and Window instance when the creation message is received
686  if (message == WM_CREATE) {
687  // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow)
688  LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams;
689 
690  // Set as the "user data" parameter of the window
691  SetWindowLongPtrW(handle, GWLP_USERDATA, window);
692  }
693 
694  // Get the WindowImpl instance corresponding to the window handle
695  WindowImpl* window = handle ? reinterpret_cast<WindowImpl*>(GetWindowLongPtr(handle, GWLP_USERDATA)) : nullptr;
696 
697  // Forward the event to the appropriate function
698  if (window) {
699  window->processWindowEvents(message, wParam, lParam);
700 
701  if (window->_callback) {
702  return CallWindowProcW(reinterpret_cast<WNDPROC>(window->_callback), handle, message, wParam, lParam);
703  }
704  }
705 
706  // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window
707  if (message == WM_CLOSE) {
708  return 0;
709  }
710 
711  // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus
712  if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU)) {
713  return 0;
714  }
715 
716  return DefWindowProcW(handle, message, wParam, lParam);
717 }
718 
719 } // priv
720 } // Window
721 } // lug
Represents an event.
Definition: Event.hpp:89
Represents a keyboard event.
Definition: Event.hpp:17
bool left
True if left mouse button was pressed, False otherwise.
Definition: Event.hpp:46
::lug::Window::Style style
Definition: Window.hpp:65
void processWindowEvents(UINT message, WPARAM wParam, LPARAM lParam)
Keyboard::Key getKeyCode(WPARAM wParam, LPARAM lParam)
static LRESULT CALLBACK onEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
bool init(const Window::InitInfo &initInfo)
Key
Abstraction of keyboard keys.
Definition: Keyboard.hpp:23
void setMousePos(const Math::Vec2i &mousePosition)
bool middle
True if middle mouse button was pressed, False otherwise.
Definition: Event.hpp:48
Type type
The type of the event.
Definition: Event.hpp:110
MouseWheelRotated event.
void setMouseCursorVisible(bool visible)
struct lug::Window::MouseEvent::@27 coord
The mouse coordinate if the event was triggered by movement.
Keyboard::Key code
The key that triggered the event.
Definition: Event.hpp:18
static lug::Window::priv::WindowImpl * _fullscreenWindow
bool ctrl
True if ctrl was pressed, False otherwise.
Definition: Event.hpp:44
Mouse::Button code
The button that triggered the event.
Definition: Event.hpp:31
struct lug::Window::MouseEvent::@25::@28 scrollOffset
The distance in x and y that the scroll wheel has traveled.
bool ctrl
True if ctrl was pressed, False otherwise.
Definition: Event.hpp:20
void configKeyEvent(KeyEvent &key, WPARAM wParam, LPARAM lParam)
Mouse left window event.
bool shift
True if shift was pressed, False otherwise.
Definition: Event.hpp:45
bool alt
True if alt was pressed, False otherwise.
Definition: Event.hpp:19
LONG_PTR _callback
Stores the original event callback function of the control.
T e()
Definition: Constant.inl:82
Mouse entered window event.
Window destroy event.
void configMouseWheelEvent(MouseEvent &mouse, UINT message, WPARAM wParam)
bool x2
True if extra 2 mouse button was pressed, False otherwise.
Definition: Event.hpp:50
bool pollEvent(lug::Window::Event &event)
Represents a mouse event.
Definition: Event.hpp:28
bool x1
True if extra 1 mouse button was pressed, False otherwise.
Definition: Event.hpp:49
void getMouseEventModifier(MouseEvent &mouse, WPARAM wParam)
static Keyboard::Key vkToLugKey(WPARAM key)
CharEvent character
A CharEvent.
Definition: Event.hpp:117
void configMouseButtonEvent(MouseEvent &mouse, UINT message, WPARAM wParam, LPARAM lParam)
#define LUG_LOG
Definition: Logger.hpp:73
KeyEvent key
A KeyEvent.
Definition: Event.hpp:116
bool right
True if right mouse button was pressed, False otherwise.
Definition: Event.hpp:47
void getMouseCoord(MouseEvent &mouse, LPARAM lParam)
wchar_t val
Raw value of the character pressed (with accents, etc.)
Definition: Event.hpp:83
bool shift
True if shift was pressed, False otherwise.
Definition: Event.hpp:21
bool system
True if system was pressed, False otherwise.
Definition: Event.hpp:22
MouseEvent mouse
A MouseEvent.
Definition: Event.hpp:118
void configMouseEvent(MouseEvent &mouse, WPARAM wParam, LPARAM lParam)