Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpDisplayWin32.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 base class
32 */
33
34#include <visp3/core/vpConfig.h>
35#if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_D3D9))
36
37#include <string>
38#include <visp3/core/vpDisplayException.h>
39#include <visp3/gui/vpDisplayWin32.h>
40
42
43const int vpDisplayWin32::MAX_INIT_DELAY = 5000;
44
49void vpCreateWindow(threadParam *param)
50{
51 // char* title = param->title;
52 (param->vpDisp)->window.initWindow(param->title.c_str(), param->x, param->y, param->w, param->h);
53 delete param;
54}
55
59vpDisplayWin32::vpDisplayWin32(vpWin32Renderer *rend) : iStatus(false), window(rend) { }
60
61vpDisplayWin32::vpDisplayWin32(vpImage<vpRGBa> &I, int winx, int winy, const std::string &title)
62 : iStatus(false), window(nullptr)
63{
64 init(I, winx, winy, title);
65}
66
67vpDisplayWin32::vpDisplayWin32(vpImage<unsigned char> &I, int winx, int winy, const std::string &title)
68 : iStatus(false), window(nullptr)
69{
70 init(I, winx, winy, title);
71}
72
80
85
90{
91 hThread = display.hThread;
92 threadId = display.threadId;
93 iStatus = display.iStatus;
94 window = display.window;
95 roi = display.roi;
96
97 return *this;
98}
99
108void vpDisplayWin32::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
109{
110 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
111 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
112 }
113
114 setScale(m_scaleType, I.getWidth(), I.getHeight());
115 init(I.getWidth(), I.getHeight(), x, y, title);
116 window.renderer->setWidth(I.getWidth() / m_scale);
117 window.renderer->setHeight(I.getHeight() / m_scale);
118 window.renderer->setImg(I);
119
120 I.display = this;
121}
122
132void vpDisplayWin32::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
133{
134 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
135 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
136 }
137
138 setScale(m_scaleType, I.getWidth(), I.getHeight());
139 init(I.getWidth(), I.getHeight(), x, y, title);
140 window.renderer->setWidth(I.getWidth() / m_scale);
141 window.renderer->setHeight(I.getHeight() / m_scale);
142 window.renderer->setImg(I);
143
144 I.display = this;
145}
146
156void vpDisplayWin32::init(unsigned int width, unsigned int height, int x, int y, const std::string &title)
157{
158 if (!title.empty())
159 m_title = title;
160 else
161 m_title = std::string(" ");
162
163 if (x != -1)
165 if (y != -1)
167
168 // we prepare the window's thread creation
169 setScale(m_scaleType, width, height);
170 threadParam *param = new threadParam;
171 param->x = m_windowXPosition;
172 param->y = m_windowYPosition;
173 param->w = width / m_scale;
174 param->h = height / m_scale;
175 param->vpDisp = this;
176 param->title = this->m_title;
177
178 // creates the window in a separate thread
179 hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)vpCreateWindow, param, 0, &threadId);
180
181 // the initialization worked
182 iStatus = (hThread != static_cast<HANDLE>(nullptr));
183
185}
186
192{
193 // if the window is not initialized yet
194 if (!window.isInitialized()) {
195 // wait
196 if (WAIT_OBJECT_0 != WaitForSingleObject(window.semaInit, MAX_INIT_DELAY))
197 throw(vpDisplayException(vpDisplayException::notInitializedError, "Window not initialized"));
198 // problem : the window is not initialized
199 }
200}
201
214{
215 // waits if the window is not initialized
216 waitForInit();
217
218 // sets the image to render
219 window.renderer->setImg(I);
220 // sends a message to the window
221 // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
222}
223
241void vpDisplayWin32::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int width,
242 unsigned int height)
243{
244 // waits if the window is not initialized
245 waitForInit();
246
247 // sets the image to render
248 window.renderer->setImgROI(I, iP, width, height);
249 // sends a message to the window
250 // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
251}
252
265{
266 // wait if the window is not initialized
267 waitForInit();
268
269 // sets the image to render
270 window.renderer->setImg(I);
271 // sends a message to the window
272 // PostMessage(window.getHWnd(), vpWM_DISPLAY, 0,0);
273}
274
292void vpDisplayWin32::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int width,
293 unsigned int height)
294{
295 // waits if the window is not initialized
296 waitForInit();
297
298 // sets the image to render
299 window.renderer->setImgROI(I, iP, width, height);
300 // sends a message to the window
301 // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
302}
303
317bool vpDisplayWin32::getClick(bool blocking)
318{
319 // wait if the window is not initialized
320 waitForInit();
321 bool ret = false;
322 // sends a message to the window
323 // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
324
325 // waits for a button to be pressed
326 if (blocking) {
327 WaitForSingleObject(window.semaClick, 0);
328 WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
329 WaitForSingleObject(window.semaClick, INFINITE);
330 ret = true;
331 }
332 else {
333 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
334 }
335
336 return ret;
337}
338
354{
355 // wait if the window is not initialized
356 waitForInit();
357
358 bool ret = false;
359 double u, v;
360 // tells the window there has been a getclick demand
361 // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
362 // waits for a click
363 if (blocking) {
364 WaitForSingleObject(window.semaClick, 0);
365 WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
366 WaitForSingleObject(window.semaClick, INFINITE);
367 ret = true;
368 }
369 else {
370 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
371 }
372
373 u = window.clickX;
374 v = window.clickY;
375 ip.set_u(u * m_scale);
376 ip.set_v(v * m_scale);
377
378 return ret;
379}
380
399{
400 // wait if the window is not initialized
401 waitForInit();
402 bool ret = false;
403 double u, v;
404 // tells the window there has been a getclickup demand
405 // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
406 // waits for a click
407 if (blocking) {
408 WaitForSingleObject(window.semaClick, 0);
409 WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
410 WaitForSingleObject(window.semaClick, INFINITE);
411 ret = true;
412 }
413 else
414 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
415
416 u = window.clickX;
417 v = window.clickY;
418 ip.set_u(u * m_scale);
419 ip.set_v(v * m_scale);
420 button = window.clickButton;
421
422 return ret;
423}
424
446{
447 // wait if the window is not initialized
448 waitForInit();
449 bool ret = false;
450 double u, v;
451 // tells the window there has been a getclickup demand
452 // PostMessage(window.getHWnd(), vpWM_GETCLICKUP, 0,0);
453
454 // waits for a click release
455 if (blocking) {
456 WaitForSingleObject(window.semaClickUp, 0);
457 WaitForSingleObject(window.semaClick, 0); // to erase previous events
458 WaitForSingleObject(window.semaClickUp, INFINITE);
459 ret = true;
460 }
461 else
462 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClickUp, 0));
463
464 u = window.clickXUp;
465 v = window.clickYUp;
466 ip.set_u(u * m_scale);
467 ip.set_v(v * m_scale);
468 button = window.clickButtonUp;
469
470 return ret;
471}
472
487{
488 // wait if the window is not initialized
489 waitForInit();
490
491 bool ret = false;
492 // waits for a keyboard event
493 if (blocking) {
494 WaitForSingleObject(window.semaKey, 0); // key down
495 WaitForSingleObject(window.semaKey, 0); // key up
496 WaitForSingleObject(window.semaKey, INFINITE);
497 ret = true;
498 }
499 else {
500 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaKey, 0));
501 }
502
503 return ret;
504}
505
521bool vpDisplayWin32::getKeyboardEvent(std::string &key, bool blocking)
522{
523 // wait if the window is not initialized
524 waitForInit();
525
526 bool ret = false;
527 // waits for a keyboard event
528 if (blocking) {
529 WaitForSingleObject(window.semaKey, 0); // key down
530 WaitForSingleObject(window.semaKey, 0); // key up
531 WaitForSingleObject(window.semaKey, INFINITE);
532 ret = true;
533 }
534 else {
535 ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaKey, 0));
536 }
537 // printf("key: %ud\n", window.key);
538 std::stringstream ss;
539 ss << window.lpString;
540 key = ss.str();
541
542 return ret;
543}
544
554{
555 // wait if the window is not initialized
556 waitForInit();
557
558 bool ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaMove, 0));
559 if (ret) {
560 double u, v;
561 // tells the window there has been a getclick demand
562 // PostMessage(window.getHWnd(), vpWM_GETPOINTERMOTIONEVENT, 0,0);
563
564 u = window.coordX;
565 v = window.coordY;
566 ip.set_u(u * m_scale);
567 ip.set_v(v * m_scale);
568 }
569
570 return ret;
571}
572
583{
584 // wait if the window is not initialized
585 waitForInit();
586
587 bool ret = true;
588 double u, v;
589 // tells the window there has been a getclick demand
590 // PostMessage(window.getHWnd(), vpWM_GETPOINTERMOTIONEVENT, 0,0);
591
592 u = window.coordX;
593 v = window.coordY;
594 ip.set_u(u * m_scale);
595 ip.set_v(v * m_scale);
596
597 return ret;
598}
599
606void vpDisplayWin32::setWindowPosition(int winx, int winy)
607{
608 // wait if the window is not initialized
609 waitForInit();
610
611 // cahange the window position only
612 SetWindowPos(window.hWnd, HWND_TOP, winx, winy, 0, 0,
613 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
614}
615
621void vpDisplayWin32::setTitle(const std::string &windowtitle)
622{
623 // wait if the window is not initialized
624 waitForInit();
625 SetWindowText(window.hWnd, windowtitle.c_str());
626}
627
632
633void vpDisplayWin32::setFont(const std::string &fontname)
634{
635 // Not yet implemented
636 (void)fontname;
637}
638
645{
646 // waits if the window is not initialized
647 waitForInit();
648
649 // sends a message to the window
650 PostMessage(window.getHWnd(), vpWM_DISPLAY, 0, 0);
651}
652
658void vpDisplayWin32::flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
659{
660 // waits if the window is not initialized
661 waitForInit();
662 /*
663 Under windows, flushing an ROI takes more time than
664 flushing the whole image.
665 Therefore, we update the maximum area even when asked to update a region.
666 */
667 WORD left = static_cast<WORD>(iP.get_u());
668 WORD right = static_cast<WORD>(iP.get_u() + width - 1);
669
670 WORD top = static_cast<WORD>(iP.get_v());
671 WORD bottom = static_cast<WORD>(iP.get_v() + height - 1);
672
673 // sends a message to the window
674 WPARAM wp = MAKEWPARAM(left, right);
675 LPARAM lp = MAKELPARAM(top, bottom);
676
677 PostMessage(window.getHWnd(), vpWM_DISPLAY_ROI, wp, lp);
678}
679
686void vpDisplayWin32::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
687{
688 // wait if the window is not initialized
689 waitForInit();
690 if (thickness == 1) {
691 window.renderer->setPixel(ip, color);
692 }
693 else {
694 window.renderer->drawRect(ip, thickness * m_scale, thickness * m_scale, color, true, 1);
695 }
696}
697
705void vpDisplayWin32::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
706 unsigned int thickness)
707{
708 // wait if the window is not initialized
709 waitForInit();
710 window.renderer->drawLine(ip1, ip2, color, thickness);
711}
712
723void vpDisplayWin32::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
724 unsigned int thickness)
725{
726 // wait if the window is not initialized
727 waitForInit();
728 window.renderer->drawLine(ip1, ip2, color, thickness, PS_DASHDOT);
729}
730
744void vpDisplayWin32::displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height,
745 const vpColor &color, bool fill, unsigned int thickness)
746{
747 // wait if the window is not initialized
748 waitForInit();
749 window.renderer->drawRect(topLeft, width, height, color, fill, thickness);
750}
751
763void vpDisplayWin32::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight,
764 const vpColor &color, bool fill, unsigned int thickness)
765{
766 // wait if the window is not initialized
767 waitForInit();
768 unsigned int width = static_cast<unsigned int>(bottomRight.get_j() - topLeft.get_j());
769 unsigned int height = static_cast<unsigned int>(bottomRight.get_i() - topLeft.get_i());
770 window.renderer->drawRect(topLeft, width, height, color, fill, thickness);
771}
772
783void vpDisplayWin32::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
784{
785 // wait if the window is not initialized
786 waitForInit();
787 vpImagePoint topLeft;
788 topLeft.set_i(rectangle.getTop());
789 topLeft.set_j(rectangle.getLeft());
790 window.renderer->drawRect(topLeft, static_cast<unsigned int>(rectangle.getWidth()),
791 static_cast<unsigned int>(rectangle.getHeight()), color, fill, thickness);
792}
793
802void vpDisplayWin32::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
803 unsigned int thickness)
804{
805 // wait if the window is not initialized
806 waitForInit();
807 window.renderer->drawCircle(center, radius, color, fill, thickness);
808}
809
816void vpDisplayWin32::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
817{
818 // wait if the window is not initialized
819 waitForInit();
820 window.renderer->drawText(ip, text.c_str(), color);
821}
822
830void vpDisplayWin32::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color,
831 unsigned int thickness)
832{
833 // wait if the window is not initialized
834 waitForInit();
835 window.renderer->drawCross(ip, size, color, thickness);
836}
837
847void vpDisplayWin32::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
848 unsigned int w, unsigned int h, unsigned int thickness)
849
850{
851 // wait if the window is not initialized
852 waitForInit();
853 window.renderer->drawArrow(ip1, ip2, color, w, h, thickness);
854}
855
861{
862 // wait if the window is not initialized
863 waitForInit();
864 window.renderer->clear(color);
865}
866
872{
874 waitForInit();
875 PostMessage(window.getHWnd(), vpWM_CLOSEDISPLAY, 0, 0);
876 // if the destructor is called for a reason different than a
877 // problem in the thread creation
878 if (iStatus) {
879 // waits for the thread to end
880 WaitForSingleObject(hThread, INFINITE);
881 CloseHandle(hThread);
882 }
884 window.initialized = false;
885 }
886}
887
893{
894 // wait if the window is not initialized
895 waitForInit();
896 window.renderer->getImage(I);
897}
898
904void vpDisplayWin32::getScreenSize(unsigned int &w, unsigned int &h)
905{
906 w = static_cast<unsigned int>(GetSystemMetrics(SM_CXSCREEN));
907 h = static_cast<unsigned int>(GetSystemMetrics(SM_CYSCREEN));
908}
909
914{
915 unsigned int width, height;
916 getScreenSize(width, height);
917 return width;
918}
919
924{
925 unsigned int width, height;
926 getScreenSize(width, height);
927 return height;
928}
929
930END_VISP_NAMESPACE
931
932#elif !defined(VISP_BUILD_SHARED_LIBS)
933// Work around to avoid warning: libvisp_gui.a(vpDisplayWin32.cpp.o) has no symbols
934void dummy_vpDisplayWin32() { }
935#endif
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) VP_OVERRIDE
virtual ~vpDisplayWin32() VP_OVERRIDE
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1) VP_OVERRIDE
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") VP_OVERRIDE
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) VP_OVERRIDE
bool getClick(bool blocking=true) VP_OVERRIDE
DWORD threadId
Id of the window's thread.
vpWin32Window window
The window.
unsigned int getScreenWidth() VP_OVERRIDE
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void displayImage(const vpImage< vpRGBa > &I) VP_OVERRIDE
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getPointerPosition(vpImagePoint &ip) VP_OVERRIDE
void closeDisplay() VP_OVERRIDE
VP_EXPLICIT vpDisplayWin32(vpWin32Renderer *rend=nullptr)
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void setTitle(const std::string &windowtitle) VP_OVERRIDE
HANDLE hThread
Handle of the window's thread.
friend void vpCreateWindow(threadParam *param)
Function used to launch the window in a thread.
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
Flush the Win32 buffer.
bool iStatus
Initialization status.
void setWindowPosition(int winx, int winy) VP_OVERRIDE
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getPointerMotionEvent(vpImagePoint &ip) VP_OVERRIDE
void getScreenSize(unsigned int &width, unsigned int &height) VP_OVERRIDE
void getImage(vpImage< vpRGBa > &I) VP_OVERRIDE
void flushDisplay() VP_OVERRIDE
Flush the Win32 buffer.
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void setFont(const std::string &fontname) VP_OVERRIDE
Set the font used to display text.
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void clearDisplay(const vpColor &color=vpColor::white) VP_OVERRIDE
vpDisplayWin32 & operator=(const vpDisplayWin32 &display)
static const int MAX_INIT_DELAY
Maximum delay for window initialization.
bool getKeyboardEvent(bool blocking=true) VP_OVERRIDE
vpScaleType m_scaleType
Definition vpDisplay.h:931
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition vpDisplay.h:924
std::string m_title
Definition vpDisplay.h:929
int m_windowYPosition
display position
Definition vpDisplay.h:926
unsigned int m_scale
Definition vpDisplay.h:930
bool m_displayHasBeenInitialized
display has been initialized
Definition vpDisplay.h:922
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_j(double jj)
double get_j() const
void set_i(double ii)
double get_u() const
void set_u(double u)
void set_v(double v)
double get_i() const
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
Defines a rectangle in the plane.
Definition vpRect.h:79
double getWidth() const
Definition vpRect.h:227
double getLeft() const
Definition vpRect.h:173
double getHeight() const
Definition vpRect.h:166
double getTop() const
Definition vpRect.h:192