Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpDisplayWin32.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 base class
33  *
34  * Authors:
35  * Bruno Renier
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpConfig.h>
40 #if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_D3D9))
41 
42 #include <string>
43 #include <visp3/core/vpDisplayException.h>
44 #include <visp3/gui/vpDisplayWin32.h>
45 
46 const int vpDisplayWin32::MAX_INIT_DELAY = 5000;
47 
52 void vpCreateWindow(threadParam *param)
53 {
54  // char* title = param->title;
55  (param->vpDisp)->window.initWindow(param->title.c_str(), param->x, param->y, param->w, param->h);
56  delete param;
57 }
58 
62 vpDisplayWin32::vpDisplayWin32(vpWin32Renderer *rend) : iStatus(false), window(rend) {}
63 
68 
79 void vpDisplayWin32::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
80 {
81  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
82  vpERROR_TRACE("Image not initialized ");
83  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
84  }
85 
87  init(I.getWidth(), I.getHeight(), x, y, title);
88  window.renderer->setWidth(I.getWidth() / m_scale);
89  window.renderer->setHeight(I.getHeight() / m_scale);
90  window.renderer->setImg(I);
91 
92  I.display = this;
93 }
94 
103 void vpDisplayWin32::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
104 {
105  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
106  vpERROR_TRACE("Image not initialized ");
107  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
108  }
109 
111  init(I.getWidth(), I.getHeight(), x, y, title);
112  window.renderer->setWidth(I.getWidth() / m_scale);
113  window.renderer->setHeight(I.getHeight() / m_scale);
114  window.renderer->setImg(I);
115 
116  I.display = this;
117 }
118 
127 void vpDisplayWin32::init(unsigned int width, unsigned int height, int x, int y, const std::string &title)
128 {
129  if (!title.empty())
130  m_title = title;
131  else
132  m_title = std::string(" ");
133 
134  if (x != -1)
135  m_windowXPosition = x;
136  if (y != -1)
137  m_windowYPosition = y;
138 
139  // we prepare the window's thread creation
140  setScale(m_scaleType, width, height);
141  threadParam *param = new threadParam;
142  param->x = m_windowXPosition;
143  param->y = m_windowYPosition;
144  param->w = width / m_scale;
145  param->h = height / m_scale;
146  param->vpDisp = this;
147  param->title = this->m_title;
148 
149  // creates the window in a separate thread
150  hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)vpCreateWindow, param, 0, &threadId);
151 
152  // the initialization worked
153  iStatus = (hThread != (HANDLE)NULL);
154 
156 }
157 
163 {
164  // if the window is not initialized yet
165  if (!window.isInitialized()) {
166  // wait
167  if (WAIT_OBJECT_0 != WaitForSingleObject(window.semaInit, MAX_INIT_DELAY))
168  throw(vpDisplayException(vpDisplayException::notInitializedError, "Window not initialized"));
169  // problem : the window is not initialized
170  }
171 }
172 
185 {
186  // waits if the window is not initialized
187  waitForInit();
188 
189  // sets the image to render
190  window.renderer->setImg(I);
191  // sends a message to the window
192  // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
193 }
194 
212 void vpDisplayWin32::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int width,
213  unsigned int height)
214 {
215  // waits if the window is not initialized
216  waitForInit();
217 
218  // sets the image to render
219  window.renderer->setImgROI(I, iP, width, height);
220  // sends a message to the window
221  // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
222 }
223 
236 {
237  // wait if the window is not initialized
238  waitForInit();
239 
240  // sets the image to render
241  window.renderer->setImg(I);
242  // sends a message to the window
243  // PostMessage(window.getHWnd(), vpWM_DISPLAY, 0,0);
244 }
245 
263 void vpDisplayWin32::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int width,
264  unsigned int height)
265 {
266  // waits if the window is not initialized
267  waitForInit();
268 
269  // sets the image to render
270  window.renderer->setImgROI(I, iP, width, height);
271  // sends a message to the window
272  // PostMessage(window.getHWnd(),vpWM_DISPLAY,0,0);
273 }
274 
290 bool vpDisplayWin32::getClick(bool blocking)
291 {
292  // wait if the window is not initialized
293  waitForInit();
294  bool ret = false;
295  // sends a message to the window
296  // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
297 
298  // waits for a button to be pressed
299  if (blocking) {
300  WaitForSingleObject(window.semaClick, 0);
301  WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
302  WaitForSingleObject(window.semaClick, INFINITE);
303  ret = true;
304  } else {
305  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
306  }
307 
308  return ret;
309 }
310 
327 bool vpDisplayWin32::getClick(vpImagePoint &ip, bool blocking)
328 {
329  // wait if the window is not initialized
330  waitForInit();
331 
332  bool ret = false;
333  double u, v;
334  // tells the window there has been a getclick demand
335  // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
336  // waits for a click
337  if (blocking) {
338  WaitForSingleObject(window.semaClick, 0);
339  WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
340  WaitForSingleObject(window.semaClick, INFINITE);
341  ret = true;
342  } else {
343  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
344  }
345 
346  u = window.clickX;
347  v = window.clickY;
348  ip.set_u(u * m_scale);
349  ip.set_v(v * m_scale);
350 
351  return ret;
352 }
353 
373 {
374  // wait if the window is not initialized
375  waitForInit();
376  bool ret = false;
377  double u, v;
378  // tells the window there has been a getclickup demand
379  // PostMessage(window.getHWnd(), vpWM_GETCLICK, 0,0);
380  // waits for a click
381  if (blocking) {
382  WaitForSingleObject(window.semaClick, 0);
383  WaitForSingleObject(window.semaClickUp, 0); // to erase previous events
384  WaitForSingleObject(window.semaClick, INFINITE);
385  ret = true;
386  } else
387  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClick, 0));
388 
389  u = window.clickX;
390  v = window.clickY;
391  ip.set_u(u * m_scale);
392  ip.set_v(v * m_scale);
393  button = window.clickButton;
394 
395  return ret;
396 }
397 
421 {
422  // wait if the window is not initialized
423  waitForInit();
424  bool ret = false;
425  double u, v;
426  // tells the window there has been a getclickup demand
427  // PostMessage(window.getHWnd(), vpWM_GETCLICKUP, 0,0);
428 
429  // waits for a click release
430  if (blocking) {
431  WaitForSingleObject(window.semaClickUp, 0);
432  WaitForSingleObject(window.semaClick, 0); // to erase previous events
433  WaitForSingleObject(window.semaClickUp, INFINITE);
434  ret = true;
435  } else
436  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaClickUp, 0));
437 
438  u = window.clickXUp;
439  v = window.clickYUp;
440  ip.set_u(u * m_scale);
441  ip.set_v(v * m_scale);
442  button = window.clickButtonUp;
443 
444  return ret;
445 }
446 
463 {
464  // wait if the window is not initialized
465  waitForInit();
466 
467  bool ret = false;
468  // waits for a keyboard event
469  if (blocking) {
470  WaitForSingleObject(window.semaKey, 0); // key down
471  WaitForSingleObject(window.semaKey, 0); // key up
472  WaitForSingleObject(window.semaKey, INFINITE);
473  ret = true;
474  } else
475  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaKey, 0));
476 
477  return ret;
478 }
498 bool vpDisplayWin32::getKeyboardEvent(std::string &key, bool blocking)
499 {
500  // wait if the window is not initialized
501  waitForInit();
502 
503  bool ret = false;
504  // waits for a keyboard event
505  if (blocking) {
506  WaitForSingleObject(window.semaKey, 0); // key down
507  WaitForSingleObject(window.semaKey, 0); // key up
508  WaitForSingleObject(window.semaKey, INFINITE);
509  ret = true;
510  } else {
511  ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaKey, 0));
512  }
513  // printf("key: %ud\n", window.key);
514  std::stringstream ss;
515  ss << window.lpString;
516  key = ss.str();
517 
518  return ret;
519 }
531 {
532  // wait if the window is not initialized
533  waitForInit();
534 
535  bool ret = (WAIT_OBJECT_0 == WaitForSingleObject(window.semaMove, 0));
536  if (ret) {
537  double u, v;
538  // tells the window there has been a getclick demand
539  // PostMessage(window.getHWnd(), vpWM_GETPOINTERMOTIONEVENT, 0,0);
540 
541  u = window.coordX;
542  v = window.coordY;
543  ip.set_u(u * m_scale);
544  ip.set_v(v * m_scale);
545  }
546 
547  return ret;
548 }
549 
561 {
562  // wait if the window is not initialized
563  waitForInit();
564 
565  bool ret = true;
566  double u, v;
567  // tells the window there has been a getclick demand
568  // PostMessage(window.getHWnd(), vpWM_GETPOINTERMOTIONEVENT, 0,0);
569 
570  u = window.coordX;
571  v = window.coordY;
572  ip.set_u(u * m_scale);
573  ip.set_v(v * m_scale);
574 
575  return ret;
576 }
577 
585 void vpDisplayWin32::setWindowPosition(int winx, int winy)
586 {
587  // wait if the window is not initialized
588  waitForInit();
589 
590  // cahange the window position only
591  SetWindowPos(window.hWnd, HWND_TOP, winx, winy, 0, 0,
592  SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
593 }
594 
600 void vpDisplayWin32::setTitle(const std::string &windowtitle)
601 {
602  // wait if the window is not initialized
603  waitForInit();
604  SetWindowText(window.hWnd, windowtitle.c_str());
605 }
606 
612 void vpDisplayWin32::setFont(const std::string & /* fontname */) { vpERROR_TRACE("Not yet implemented"); }
613 
620 {
621  // waits if the window is not initialized
622  waitForInit();
623 
624  // sends a message to the window
625  PostMessage(window.getHWnd(), vpWM_DISPLAY, 0, 0);
626 }
627 
633 void vpDisplayWin32::flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
634 {
635  // waits if the window is not initialized
636  waitForInit();
637  /*
638  Under windows, flushing an ROI takes more time than
639  flushing the whole image.
640  Therefore, we update the maximum area even when asked to update a region.
641  */
642  WORD left = (WORD)iP.get_u();
643  WORD right = (WORD)(iP.get_u() + width - 1);
644 
645  WORD top = (WORD)iP.get_v();
646  WORD bottom = (WORD)(iP.get_v() + height - 1);
647 
648  // sends a message to the window
649  WPARAM wp = MAKEWPARAM(left, right);
650  LPARAM lp = MAKELPARAM(top, bottom);
651 
652  PostMessage(window.getHWnd(), vpWM_DISPLAY_ROI, wp, lp);
653 }
654 
661 void vpDisplayWin32::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
662 {
663  // wait if the window is not initialized
664  waitForInit();
665  if (thickness == 1) {
666  window.renderer->setPixel(ip, color);
667  } else {
668  window.renderer->drawRect(ip, thickness * m_scale, thickness * m_scale, color, true, 1);
669  }
670 }
671 
678 void vpDisplayWin32::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
679  unsigned int thickness)
680 {
681  // wait if the window is not initialized
682  waitForInit();
683  window.renderer->drawLine(ip1, ip2, color, thickness);
684 }
685 
695 void vpDisplayWin32::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
696  unsigned int thickness)
697 {
698  // wait if the window is not initialized
699  waitForInit();
700  window.renderer->drawLine(ip1, ip2, color, thickness, PS_DASHDOT);
701 }
702 
716 void vpDisplayWin32::displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height,
717  const vpColor &color, bool fill, unsigned int thickness)
718 {
719  // wait if the window is not initialized
720  waitForInit();
721  window.renderer->drawRect(topLeft, width, height, color, fill, thickness);
722 }
723 
736 void vpDisplayWin32::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight,
737  const vpColor &color, bool fill, unsigned int thickness)
738 {
739  // wait if the window is not initialized
740  waitForInit();
741  unsigned int width = static_cast<unsigned int>(bottomRight.get_j() - topLeft.get_j());
742  unsigned int height = static_cast<unsigned int>(bottomRight.get_i() - topLeft.get_i());
743  window.renderer->drawRect(topLeft, width, height, color, fill, thickness);
744 }
745 
757 void vpDisplayWin32::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
758 {
759  // wait if the window is not initialized
760  waitForInit();
761  vpImagePoint topLeft;
762  topLeft.set_i(rectangle.getTop());
763  topLeft.set_j(rectangle.getLeft());
764  window.renderer->drawRect(topLeft, static_cast<unsigned int>(rectangle.getWidth()),
765  static_cast<unsigned int>(rectangle.getHeight()), color, fill, thickness);
766 }
767 
777 void vpDisplayWin32::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
778  unsigned int thickness)
779 {
780  // wait if the window is not initialized
781  waitForInit();
782  window.renderer->drawCircle(center, radius, color, fill, thickness);
783 }
784 
791 void vpDisplayWin32::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
792 {
793  // wait if the window is not initialized
794  waitForInit();
795  window.renderer->drawText(ip, text, color);
796 }
797 
805 void vpDisplayWin32::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color,
806  unsigned int thickness)
807 {
808  // wait if the window is not initialized
809  waitForInit();
810  window.renderer->drawCross(ip, size, color, thickness);
811 }
812 
820 void vpDisplayWin32::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
821  unsigned int w, unsigned int h, unsigned int thickness)
822 
823 {
824  // wait if the window is not initialized
825  waitForInit();
826  window.renderer->drawArrow(ip1, ip2, color, w, h, thickness);
827 }
828 
834 {
835  // wait if the window is not initialized
836  waitForInit();
837  window.renderer->clear(color);
838 }
839 
845 {
847  waitForInit();
848  PostMessage(window.getHWnd(), vpWM_CLOSEDISPLAY, 0, 0);
849  // if the destructor is called for a reason different than a
850  // problem in the thread creation
851  if (iStatus) {
852  // waits for the thread to end
853  WaitForSingleObject(hThread, INFINITE);
854  CloseHandle(hThread);
855  }
857  window.initialized = false;
858  }
859 }
860 
866 {
867  // wait if the window is not initialized
868  waitForInit();
869  window.renderer->getImage(I);
870 }
871 
876 void vpDisplayWin32::getScreenSize(unsigned int &w, unsigned int &h)
877 {
878  w = GetSystemMetrics(SM_CXSCREEN);
879  h = GetSystemMetrics(SM_CYSCREEN);
880 }
881 
886 {
887  unsigned int width, height;
888  getScreenSize(width, height);
889  return width;
890 }
891 
896 {
897  unsigned int width, height;
898  getScreenSize(width, height);
899  return height;
900 }
901 #elif !defined(VISP_BUILD_SHARED_LIBS)
902 // Work arround to avoid warning: libvisp_core.a(vpDisplayWin32.cpp.o) has no
903 // symbols
904 void dummy_vpDisplayWin32(){};
905 #endif
void getScreenSize(unsigned int &width, unsigned int &height)
vpDisplay * display
Definition: vpImage.h:144
static const int MAX_INIT_DELAY
Maximum delay for window initialization.
DWORD threadId
Id of the window&#39;s thread.
double get_i() const
Definition: vpImagePoint.h:203
double getTop() const
Definition: vpRect.h:193
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
int m_windowYPosition
display position
Definition: vpDisplay.h:214
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
void setFont(const std::string &fontname)
Set the font used to display text.
virtual ~vpDisplayWin32()
bool getClick(bool blocking=true)
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
flush the Win32 buffer It&#39;s necessary to use this function to see the results of any drawing ...
void set_u(double u)
Definition: vpImagePoint.h:225
#define vpERROR_TRACE
Definition: vpDebug.h:393
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
unsigned int getScreenWidth()
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:210
bool iStatus
Initialization status.
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
bool getKeyboardEvent(bool blocking=true)
void setTitle(const std::string &windowtitle)
vpDisplayWin32(vpWin32Renderer *rend=NULL)
vpWin32Window window
The window.
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
double get_u() const
Definition: vpImagePoint.h:262
void displayImage(const vpImage< vpRGBa > &I)
int m_windowXPosition
display position
Definition: vpDisplay.h:212
double getWidth() const
Definition: vpRect.h:228
void set_i(double ii)
Definition: vpImagePoint.h:166
unsigned int m_scale
Definition: vpDisplay.h:218
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
double get_j() const
Definition: vpImagePoint.h:214
vpScaleType m_scaleType
Definition: vpDisplay.h:219
std::string m_title
Definition: vpDisplay.h:217
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
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)
double getLeft() const
Definition: vpRect.h:174
unsigned int getScreenHeight()
friend void vpCreateWindow(threadParam *param)
Function used to launch the window in a thread.
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
void set_j(double jj)
Definition: vpImagePoint.h:177
bool getPointerMotionEvent(vpImagePoint &ip)
Error that can be emited by the vpDisplay class and its derivates.
void set_v(double v)
Definition: vpImagePoint.h:236
unsigned int getHeight() const
Definition: vpImage.h:188
HANDLE hThread
Handle of the window&#39;s thread.
double getHeight() const
Definition: vpRect.h:167
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
Defines a rectangle in the plane.
Definition: vpRect.h:79
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
void clearDisplay(const vpColor &color=vpColor::white)
void flushDisplay()
flush the Win32 buffer It&#39;s necessary to use this function to see the results of any drawing ...
void setWindowPosition(int winx, int winy)
unsigned int getWidth() const
Definition: vpImage.h:246
bool getPointerPosition(vpImagePoint &ip)
double get_v() const
Definition: vpImagePoint.h:273
void getImage(vpImage< vpRGBa > &I)