You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MonitorInfo.cxx 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <tchar.h>
  22. #include <rfb_win32/MonitorInfo.h>
  23. #include <rfb_win32/Win32Util.h>
  24. #include <rdr/Exception.h>
  25. #include <rfb/LogWriter.h>
  26. #ifndef min
  27. #define min(a,b) ((a)<(b)?(a):(b))
  28. #endif
  29. #ifndef max
  30. #define max(a,b) ((a)>(b)?(a):(b))
  31. #endif
  32. using namespace rfb;
  33. using namespace win32;
  34. static LogWriter vlog("MonitorInfo");
  35. static void fillMonitorInfo(HMONITOR monitor, MONITORINFOEXA* mi) {
  36. vlog.debug("monitor=%p", monitor);
  37. memset(mi, 0, sizeof(MONITORINFOEXA));
  38. mi->cbSize = sizeof(MONITORINFOEXA);
  39. if (!GetMonitorInfo(monitor, mi))
  40. throw rdr::SystemException("failed to GetMonitorInfo", GetLastError());
  41. vlog.debug("monitor is %ld,%ld-%ld,%ld", mi->rcMonitor.left, mi->rcMonitor.top, mi->rcMonitor.right, mi->rcMonitor.bottom);
  42. vlog.debug("work area is %ld,%ld-%ld,%ld", mi->rcWork.left, mi->rcWork.top, mi->rcWork.right, mi->rcWork.bottom);
  43. vlog.debug("device is \"%s\"", mi->szDevice);
  44. }
  45. MonitorInfo::MonitorInfo(HWND window) {
  46. cbSize = sizeof(MonitorInfo);
  47. szDevice[0] = 0;
  48. HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
  49. if (!monitor)
  50. throw rdr::SystemException("failed to get monitor", GetLastError());
  51. fillMonitorInfo(monitor, this);
  52. }
  53. MonitorInfo::MonitorInfo(const RECT& r) {
  54. cbSize = sizeof(MonitorInfo);
  55. szDevice[0] = 0;
  56. HMONITOR monitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
  57. if (!monitor)
  58. throw rdr::SystemException("failed to get monitor", GetLastError());
  59. fillMonitorInfo(monitor, this);
  60. }
  61. struct monitorByNameData {
  62. MONITORINFOEXA* info;
  63. const char* monitorName;
  64. };
  65. static BOOL CALLBACK monitorByNameEnumProc(HMONITOR monitor,
  66. HDC /*dc*/,
  67. LPRECT /*pos*/,
  68. LPARAM d) {
  69. monitorByNameData* data = (monitorByNameData*)d;
  70. memset(data->info, 0, sizeof(MONITORINFOEXA));
  71. data->info->cbSize = sizeof(MONITORINFOEXA);
  72. if (GetMonitorInfo(monitor, data->info)) {
  73. if (stricmp(data->monitorName, data->info->szDevice) == 0)
  74. return FALSE;
  75. }
  76. return TRUE;
  77. }
  78. MonitorInfo::MonitorInfo(const char* devName) {
  79. monitorByNameData data;
  80. data.info = this;
  81. data.monitorName = devName;
  82. EnumDisplayMonitors(0, 0, &monitorByNameEnumProc, (LPARAM)&data);
  83. }
  84. void MonitorInfo::moveTo(HWND handle) {
  85. vlog.debug("moveTo monitor=%s", szDevice);
  86. MonitorInfo mi(handle);
  87. if (strcmp(szDevice, mi.szDevice) != 0) {
  88. centerWindow(handle, rcWork);
  89. clipTo(handle);
  90. }
  91. }
  92. void MonitorInfo::clipTo(RECT* r) {
  93. vlog.debug("clipTo monitor=%s", szDevice);
  94. if (r->top < rcWork.top) {
  95. r->bottom += rcWork.top - r->top; r->top = rcWork.top;
  96. }
  97. if (r->left < rcWork.left) {
  98. r->right += rcWork.left - r->left; r->left = rcWork.left;
  99. }
  100. if (r->bottom > rcWork.bottom) {
  101. r->top += rcWork.bottom - r->bottom; r->bottom = rcWork.bottom;
  102. }
  103. if (r->right > rcWork.right) {
  104. r->left += rcWork.right - r->right; r->right = rcWork.right;
  105. }
  106. r->left = max(r->left, rcWork.left);
  107. r->right = min(r->right, rcWork.right);
  108. r->top = max(r->top, rcWork.top);
  109. r->bottom = min(r->bottom, rcWork.bottom);
  110. }
  111. void MonitorInfo::clipTo(HWND handle) {
  112. RECT r;
  113. GetWindowRect(handle, &r);
  114. clipTo(&r);
  115. SetWindowPos(handle, 0, r.left, r.top, r.right-r.left, r.bottom-r.top,
  116. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  117. }