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