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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. #include <tchar.h>
  19. #include <rfb_win32/MonitorInfo.h>
  20. #include <rfb_win32/Win32Util.h>
  21. #include <rdr/Exception.h>
  22. #include <rfb/LogWriter.h>
  23. #ifndef min
  24. #define min(a,b) ((a)<(b)?(a):(b))
  25. #endif
  26. #ifndef max
  27. #define max(a,b) ((a)>(b)?(a):(b))
  28. #endif
  29. using namespace rfb;
  30. using namespace win32;
  31. static LogWriter vlog("MonitorInfo");
  32. static void fillMonitorInfo(HMONITOR monitor, MONITORINFOEXA* mi) {
  33. vlog.debug("monitor=%p", monitor);
  34. memset(mi, 0, sizeof(MONITORINFOEXA));
  35. mi->cbSize = sizeof(MONITORINFOEXA);
  36. if (!GetMonitorInfo(monitor, mi))
  37. throw rdr::SystemException("failed to GetMonitorInfo", GetLastError());
  38. vlog.debug("monitor is %ld,%ld-%ld,%ld", mi->rcMonitor.left, mi->rcMonitor.top, mi->rcMonitor.right, mi->rcMonitor.bottom);
  39. vlog.debug("work area is %ld,%ld-%ld,%ld", mi->rcWork.left, mi->rcWork.top, mi->rcWork.right, mi->rcWork.bottom);
  40. vlog.debug("device is \"%s\"", mi->szDevice);
  41. }
  42. MonitorInfo::MonitorInfo(HWND window) {
  43. cbSize = sizeof(MonitorInfo);
  44. szDevice[0] = 0;
  45. HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
  46. if (!monitor)
  47. throw rdr::SystemException("failed to get monitor", GetLastError());
  48. fillMonitorInfo(monitor, this);
  49. }
  50. MonitorInfo::MonitorInfo(const RECT& r) {
  51. cbSize = sizeof(MonitorInfo);
  52. szDevice[0] = 0;
  53. HMONITOR monitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
  54. if (!monitor)
  55. throw rdr::SystemException("failed to get monitor", GetLastError());
  56. fillMonitorInfo(monitor, this);
  57. }
  58. struct monitorByNameData {
  59. MONITORINFOEXA* info;
  60. const char* monitorName;
  61. };
  62. static BOOL CALLBACK monitorByNameEnumProc(HMONITOR monitor,
  63. HDC dc,
  64. LPRECT pos,
  65. LPARAM d) {
  66. monitorByNameData* data = (monitorByNameData*)d;
  67. memset(data->info, 0, sizeof(MONITORINFOEXA));
  68. data->info->cbSize = sizeof(MONITORINFOEXA);
  69. if (GetMonitorInfo(monitor, data->info)) {
  70. if (stricmp(data->monitorName, data->info->szDevice) == 0)
  71. return FALSE;
  72. }
  73. return TRUE;
  74. }
  75. MonitorInfo::MonitorInfo(const char* devName) {
  76. monitorByNameData data;
  77. data.info = this;
  78. data.monitorName = devName;
  79. EnumDisplayMonitors(0, 0, &monitorByNameEnumProc, (LPARAM)&data);
  80. }
  81. void MonitorInfo::moveTo(HWND handle) {
  82. vlog.debug("moveTo monitor=%s", szDevice);
  83. MonitorInfo mi(handle);
  84. if (strcmp(szDevice, mi.szDevice) != 0) {
  85. centerWindow(handle, rcWork);
  86. clipTo(handle);
  87. }
  88. }
  89. void MonitorInfo::clipTo(RECT* r) {
  90. vlog.debug("clipTo monitor=%s", szDevice);
  91. if (r->top < rcWork.top) {
  92. r->bottom += rcWork.top - r->top; r->top = rcWork.top;
  93. }
  94. if (r->left < rcWork.left) {
  95. r->right += rcWork.left - r->left; r->left = rcWork.left;
  96. }
  97. if (r->bottom > rcWork.bottom) {
  98. r->top += rcWork.bottom - r->bottom; r->bottom = rcWork.bottom;
  99. }
  100. if (r->right > rcWork.right) {
  101. r->left += rcWork.right - r->right; r->right = rcWork.right;
  102. }
  103. r->left = max(r->left, rcWork.left);
  104. r->right = min(r->right, rcWork.right);
  105. r->top = max(r->top, rcWork.top);
  106. r->bottom = min(r->bottom, rcWork.bottom);
  107. }
  108. void MonitorInfo::clipTo(HWND handle) {
  109. RECT r;
  110. GetWindowRect(handle, &r);
  111. clipTo(&r);
  112. SetWindowPos(handle, 0, r.left, r.top, r.right-r.left, r.bottom-r.top,
  113. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  114. }