BsWin32Window.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include "Win32/BsWin32Window.h"
  2. #include "Win32/BsWin32Platform.h"
  3. namespace BansheeEngine
  4. {
  5. struct Win32Window::Pimpl
  6. {
  7. HWND hWnd = nullptr;
  8. INT32 left = 0;
  9. INT32 top = 0;
  10. UINT32 width = 0;
  11. UINT32 height = 0;
  12. bool isExternal = false;
  13. };
  14. Win32Window::Win32Window(const WINDOW_DESC& desc)
  15. {
  16. m = bs_new<Pimpl>();
  17. HMONITOR hMonitor = desc.monitor;
  18. if (!desc.external)
  19. {
  20. DWORD dwStyle = WS_CLIPCHILDREN;
  21. if (!desc.hidden)
  22. dwStyle |= WS_VISIBLE;
  23. DWORD dwStyleEx = 0;
  24. RECT rc;
  25. MONITORINFO monitorInfo;
  26. INT32 left = desc.left;
  27. INT32 top = desc.top;
  28. // If we didn't specified the adapter index, or if we didn't find it
  29. if (hMonitor == nullptr)
  30. {
  31. POINT windowAnchorPoint;
  32. // Fill in anchor point.
  33. windowAnchorPoint.x = left;
  34. windowAnchorPoint.y = top;
  35. // Get the nearest monitor to this window.
  36. hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTOPRIMARY);
  37. }
  38. // Get the target monitor info
  39. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  40. monitorInfo.cbSize = sizeof(MONITORINFO);
  41. GetMonitorInfo(hMonitor, &monitorInfo);
  42. UINT32 width = desc.width;
  43. UINT32 height = desc.height;
  44. // No specified top left -> Center the window in the middle of the monitor
  45. if (left == -1 || top == -1)
  46. {
  47. int screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  48. int screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  49. // clamp window dimensions to screen size
  50. int outerw = (int(width) < screenw) ? int(width) : screenw;
  51. int outerh = (int(height) < screenh) ? int(height) : screenh;
  52. if (left == -1)
  53. left = monitorInfo.rcWork.left + (screenw - outerw) / 2;
  54. else if (hMonitor != nullptr)
  55. left += monitorInfo.rcWork.left;
  56. if (top == -1)
  57. top = monitorInfo.rcWork.top + (screenh - outerh) / 2;
  58. else if (hMonitor != nullptr)
  59. top += monitorInfo.rcWork.top;
  60. }
  61. else if (hMonitor != nullptr)
  62. {
  63. left += monitorInfo.rcWork.left;
  64. top += monitorInfo.rcWork.top;
  65. }
  66. if (!desc.fullscreen)
  67. {
  68. if (desc.parent)
  69. {
  70. if (desc.toolWindow)
  71. dwStyleEx = WS_EX_TOOLWINDOW;
  72. else
  73. dwStyle |= WS_CHILD;
  74. }
  75. if (!desc.parent || desc.toolWindow)
  76. {
  77. if (desc.border == WindowBorder::None)
  78. dwStyle |= WS_POPUP;
  79. else if (desc.border == WindowBorder::Fixed)
  80. dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  81. WS_SYSMENU | WS_MINIMIZEBOX;
  82. else
  83. dwStyle |= WS_OVERLAPPEDWINDOW;
  84. }
  85. if (!desc.outerDimensions)
  86. {
  87. // Calculate window dimensions required to get the requested client area
  88. SetRect(&rc, 0, 0, width, height);
  89. AdjustWindowRect(&rc, dwStyle, false);
  90. width = rc.right - rc.left;
  91. height = rc.bottom - rc.top;
  92. // Clamp width and height to the desktop dimensions
  93. int screenw = GetSystemMetrics(SM_CXSCREEN);
  94. int screenh = GetSystemMetrics(SM_CYSCREEN);
  95. if ((int)width > screenw)
  96. width = screenw;
  97. if ((int)height > screenh)
  98. height = screenh;
  99. if (left < 0)
  100. left = (screenw - width) / 2;
  101. if (top < 0)
  102. top = (screenh - height) / 2;
  103. }
  104. }
  105. else
  106. {
  107. dwStyle |= WS_POPUP;
  108. top = 0;
  109. left = 0;
  110. }
  111. UINT classStyle = 0;
  112. if (desc.enableDoubleClick)
  113. classStyle |= CS_DBLCLKS;
  114. HINSTANCE hInst = NULL;
  115. // Register the window class
  116. WNDCLASS wc = { classStyle, Win32Platform::_win32WndProc, 0, 0, hInst,
  117. LoadIcon(nullptr, IDI_APPLICATION), LoadCursor(nullptr, IDC_ARROW),
  118. (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "Win32Wnd" };
  119. RegisterClass(&wc);
  120. // Create main window
  121. m->hWnd = CreateWindowEx(dwStyleEx, "Win32Wnd", desc.title.c_str(), dwStyle,
  122. left, top, width, height, desc.parent, nullptr, hInst, this);
  123. m->isExternal = false;
  124. }
  125. else
  126. {
  127. m->hWnd = desc.external;
  128. m->isExternal = true;
  129. }
  130. RECT rc;
  131. GetWindowRect(m->hWnd, &rc);
  132. m->top = rc.top;
  133. m->left = rc.left;
  134. GetClientRect(m->hWnd, &rc);
  135. m->width = rc.right;
  136. m->height = rc.bottom;
  137. }
  138. Win32Window::~Win32Window()
  139. {
  140. if (m->hWnd && !m->isExternal)
  141. DestroyWindow(m->hWnd);
  142. bs_delete(m);
  143. }
  144. void Win32Window::move(INT32 top, INT32 left)
  145. {
  146. if (m->hWnd)
  147. {
  148. m->top = top;
  149. m->left = left;
  150. SetWindowPos(m->hWnd, nullptr, left, top, m->width, m->height, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  151. }
  152. }
  153. void Win32Window::resize(UINT32 width, UINT32 height)
  154. {
  155. if (m->hWnd)
  156. {
  157. RECT rc = { m->top, m->left, width, height };
  158. AdjustWindowRect(&rc, GetWindowLong(m->hWnd, GWL_STYLE), false);
  159. width = rc.right - rc.left;
  160. height = rc.bottom - rc.top;
  161. m->width = width;
  162. m->height = height;
  163. SetWindowPos(m->hWnd, nullptr, m->left, m->top, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  164. }
  165. }
  166. void Win32Window::setActive(bool state)
  167. {
  168. if (m->hWnd)
  169. {
  170. if (state)
  171. ShowWindow(m->hWnd, SW_RESTORE);
  172. else
  173. ShowWindow(m->hWnd, SW_SHOWMINNOACTIVE);
  174. }
  175. }
  176. void Win32Window::setHidden(bool hidden)
  177. {
  178. if (hidden)
  179. ShowWindow(m->hWnd, SW_HIDE);
  180. else
  181. ShowWindow(m->hWnd, SW_SHOWNORMAL);
  182. }
  183. void Win32Window::minimize()
  184. {
  185. if (m->hWnd)
  186. SendMessage(m->hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  187. }
  188. void Win32Window::maximize()
  189. {
  190. if (m->hWnd)
  191. SendMessage(m->hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  192. }
  193. void Win32Window::restore()
  194. {
  195. if (m->hWnd)
  196. SendMessage(m->hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  197. }
  198. void Win32Window::_windowMovedOrResized()
  199. {
  200. if (!m->hWnd || IsIconic(m->hWnd))
  201. return;
  202. RECT rc;
  203. GetWindowRect(m->hWnd, &rc);
  204. m->top = rc.top;
  205. m->left = rc.left;
  206. GetClientRect(m->hWnd, &rc);
  207. m->width = rc.right - rc.left;
  208. m->height = rc.bottom - rc.top;
  209. }
  210. Vector2I Win32Window::screenToWindowPos(const Vector2I& screenPos) const
  211. {
  212. POINT pos;
  213. pos.x = screenPos.x;
  214. pos.y = screenPos.y;
  215. ScreenToClient(m->hWnd, &pos);
  216. return Vector2I(pos.x, pos.y);
  217. }
  218. Vector2I Win32Window::windowToScreenPos(const Vector2I& windowPos) const
  219. {
  220. POINT pos;
  221. pos.x = windowPos.x;
  222. pos.y = windowPos.y;
  223. ClientToScreen(m->hWnd, &pos);
  224. return Vector2I(pos.x, pos.y);
  225. }
  226. }