Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpWin32Window.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Windows 32 display's window class
32 */
33
34#include <iostream>
35#include <visp3/core/vpConfig.h>
36#include <visp3/gui/vpWin32API.h>
37
38#if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_D3D9))
39
40#define MAX_SEM_COUNT 2147483647
41
42#ifndef DOXYGEN_SHOULD_SKIP_THIS
43
44#include <visp3/gui/vpWin32Window.h>
45
47
48// Should be already defined ...
49#ifndef GET_X_LPARAM
50#define GET_X_LPARAM(lp) (static_cast<int>(static_cast<short>(LOWORD(lp))))
51#endif
52
53#ifndef GET_Y_LPARAM
54#define GET_Y_LPARAM(lp) (static_cast<int>(static_cast<short>(HIWORD(lp))))
55#endif
56
57// declares the window as thread local
58// allows multiple displays
59#ifdef __MINGW32__
60__thread vpWin32Window *window;
61#else
62__declspec(thread) vpWin32Window *window;
63#endif
64
65bool vpWin32Window::registered = false;
69LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
70{
71 // the first time this callback is executed, put the window in initialized
72 // state
73 if (window != nullptr) {
74 if (!window->isInitialized()) {
75 window->initialized = true;
76 vpReleaseSemaphore(window->semaInit, 1, nullptr);
77 }
78 }
79 switch (message) {
80 case vpWM_DISPLAY:
81 // redraw the whole window
82 InvalidateRect(window->getHWnd(), nullptr, TRUE);
83 UpdateWindow(window->getHWnd());
84 break;
85
86 case vpWM_DISPLAY_ROI: {
87 RECT rect;
88
89 rect.left = LOWORD(wParam);
90 rect.right = HIWORD(wParam);
91
92 rect.top = LOWORD(lParam);
93 rect.bottom = HIWORD(lParam);
94
95 InvalidateRect(window->getHWnd(), &rect, TRUE);
96 UpdateWindow(window->getHWnd());
97 } break;
98
99 case WM_LBUTTONDOWN: {
100 window->clickX = GET_X_LPARAM(lParam);
101 window->clickY = GET_Y_LPARAM(lParam);
102
103 window->clickButton = vpMouseButton::button1;
104 vpReleaseSemaphore(window->semaClick, 1, nullptr);
105 } break;
106
107 case WM_MBUTTONDOWN: {
108 window->clickX = GET_X_LPARAM(lParam);
109 window->clickY = GET_Y_LPARAM(lParam);
110
111 window->clickButton = vpMouseButton::button2;
112 vpReleaseSemaphore(window->semaClick, 1, nullptr);
113 } break;
114
115 case WM_RBUTTONDOWN: {
116 window->clickX = GET_X_LPARAM(lParam);
117 window->clickY = GET_Y_LPARAM(lParam);
118
119 window->clickButton = vpMouseButton::button3;
120 vpReleaseSemaphore(window->semaClick, 1, nullptr);
121 } break;
122
123 case WM_LBUTTONUP: {
124 window->clickXUp = GET_X_LPARAM(lParam);
125 window->clickYUp = GET_Y_LPARAM(lParam);
126
127 window->clickButtonUp = vpMouseButton::button1;
128 vpReleaseSemaphore(window->semaClickUp, 1, nullptr);
129 } break;
130
131 case WM_MBUTTONUP: {
132 window->clickXUp = GET_X_LPARAM(lParam);
133 window->clickYUp = GET_Y_LPARAM(lParam);
134
135 window->clickButtonUp = vpMouseButton::button2;
136 vpReleaseSemaphore(window->semaClickUp, 1, nullptr);
137 } break;
138
139 case WM_RBUTTONUP: {
140 window->clickXUp = GET_X_LPARAM(lParam);
141 window->clickYUp = GET_Y_LPARAM(lParam);
142
143 window->clickButtonUp = vpMouseButton::button3;
144 vpReleaseSemaphore(window->semaClickUp, 1, nullptr);
145 } break;
146 case WM_MOUSEMOVE: {
147 window->coordX = GET_X_LPARAM(lParam);
148 window->coordY = GET_Y_LPARAM(lParam);
149 vpReleaseSemaphore(window->semaMove, 1, nullptr);
150 } break;
151
152 case WM_SYSKEYDOWN:
153 // case WM_SYSKEYUP:
154 case WM_KEYDOWN:
155 // case WM_KEYUP:
156 {
157 GetKeyNameText((LONG)lParam, window->lpString,
158 10); // 10 is the size of lpString
159 // window->key = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
160 vpReleaseSemaphore(window->semaKey, 1, nullptr);
161 break;
162 }
163
164 case WM_COMMAND:
165
166 break;
167
168 // we must prevent the window from erasing the background each time a
169 // repaint is needed
170 case WM_ERASEBKGND:
171 return (LRESULT)1;
172
173 case WM_PAINT:
174 // render the display
175 window->renderer->render();
176 break;
177
178 case vpWM_CLOSEDISPLAY:
179 // cleanup code here, if needed
180 // destroys the window
181 DestroyWindow(hWnd);
182 break;
183
184 case WM_DESTROY:
185 PostQuitMessage(0);
186 break;
187 default:
188 return DefWindowProc(hWnd, message, wParam, lParam);
189 }
190 return 0;
191}
192
196vpWin32Window::vpWin32Window(vpWin32Renderer *rend) : initialized(false)
197{
198 renderer = rend;
199
200 // registered is static member class and is initialized at the beginning of
201 // this file (registered = false)
202
203 // creates the semaphores
204 semaInit = CreateSemaphore(nullptr, 0, 1, nullptr);
205 semaClick = CreateSemaphore(nullptr, 0, MAX_SEM_COUNT, nullptr);
206 semaClickUp = CreateSemaphore(nullptr, 0, MAX_SEM_COUNT, nullptr);
207 semaKey = CreateSemaphore(nullptr, 0, MAX_SEM_COUNT, nullptr);
208 semaMove = CreateSemaphore(nullptr, 0, MAX_SEM_COUNT, nullptr);
209}
210
214vpWin32Window::vpWin32Window(const vpWin32Window &window)
215{
216 *this = window;
217}
218
222vpWin32Window &vpWin32Window::operator=(const vpWin32Window &window)
223{
224 hInst = window.hInst;
225 hWnd = window.hWnd;
226 initialized = window.initialized;
227 semaInit = window.semaInit;
228 semaClick = window.semaClick;
229 semaClickUp = window.semaClickUp;
230 semaKey = window.semaKey;
231 semaMove = window.semaMove;
232 clickX = window.clickX;
233 clickXUp = window.clickXUp;
234 clickY = window.clickY;
235 clickYUp = window.clickYUp;
236 coordX = window.coordX;
237 coordY = window.coordY;
238 clickButton = window.clickButton;
239 clickButtonUp = window.clickButtonUp;
240 registered = window.registered;
241 renderer = window.renderer;
242 return *this;
243}
244
248vpWin32Window::~vpWin32Window()
249{
250 delete renderer;
251 CloseHandle(semaInit);
252 CloseHandle(semaClick);
253 CloseHandle(semaClickUp);
254 CloseHandle(semaKey);
255 CloseHandle(semaMove);
256}
257
268void vpWin32Window::initWindow(const char *title, int posx, int posy, unsigned int w, unsigned int h)
269{
270 // the window's style
271 DWORD style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
272 const char g_szClassName[] = "ViSPWindowClass";
273
274 RECT rect;
275 rect.left = 0;
276 rect.right = static_cast<int>(w);
277 rect.top = 0;
278 rect.bottom = static_cast<int>(h);
279
280 // now we register the window's class
281 WNDCLASSEX wcex;
282
283 wcex.cbSize = sizeof(WNDCLASSEX);
284
285 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
286 wcex.lpfnWndProc = (WNDPROC)WndProc;
287 wcex.cbClsExtra = 0;
288 wcex.cbWndExtra = 0;
289 wcex.hInstance = hInst;
290 wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
291 wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
292 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
293 wcex.lpszMenuName = nullptr;
294 wcex.lpszClassName = g_szClassName;
295 wcex.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
296
297 RegisterClassEx(&wcex);
298
299 AdjustWindowRectEx(&rect, style, false, style);
300 // std::cout << "win client size (orig)(w,h): " << rect.left << " " <<
301 // rect.top << " " << rect.right << " " << rect.bottom << std::endl;
302
303 // creates the window
304 hWnd = CreateWindowEx(WS_EX_APPWINDOW, g_szClassName, title, style, posx, posy, rect.right - rect.left,
305 rect.bottom - rect.top, nullptr, nullptr, hInst, nullptr);
306 if (hWnd == nullptr) {
307 DWORD err = GetLastError();
308 std::cout << "err CreateWindowEx=" << err << std::endl;
309 throw vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create the window!");
310 }
311 SetWindowPos(hWnd, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);
312
313 // needed if we want to access it from the callback method (message handler)
314 window = this;
315
316 // initialize the renderer
317 renderer->init(hWnd, w, h);
318
319 // displays the window
320 ShowWindow(hWnd, SW_SHOWDEFAULT);
321 // ShowWindow(hWnd, SW_SHOW);
322 UpdateWindow(hWnd);
323
324 MSG msg;
325
326 // starts the message loop
327 while (true) {
328 BOOL val = GetMessage(&msg, nullptr, 0, 0);
329 if (val == -1) {
330 std::cout << "GetMessage error:" << GetLastError() << std::endl;
331 break;
332 }
333 else if (val == 0) {
334 break;
335 }
336 else {
337 if (!TranslateAccelerator(msg.hwnd, nullptr, &msg)) {
338 TranslateMessage(&msg);
339 DispatchMessage(&msg);
340 }
341 }
342 }
343}
344
345END_VISP_NAMESPACE
346
347#endif
348#elif !defined(VISP_BUILD_SHARED_LIBS)
349// Work around to avoid warning: libvisp_gui.a(vpWin32Window.cpp.o) has no symbols
350void dummy_vpWin32Window() { }
351#endif
Error that can be emitted by the vpDisplay class and its derivatives.
@ cannotOpenWindowError
Unable to open display window.