entry_windows.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Copyright 2011-2012 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <bx/bx.h>
  6. #if BX_PLATFORM_WINDOWS
  7. #include <bgfxplatform.h>
  8. #include <bx/uint32_t.h>
  9. #include <bx/thread.h>
  10. #include "entry.h"
  11. #include "dbg.h"
  12. #define DEFAULT_WIDTH 1280
  13. #define DEFAULT_HEIGHT 720
  14. extern int _main_(int _argc, char** _argv);
  15. namespace entry
  16. {
  17. struct MainThreadEntry
  18. {
  19. int m_argc;
  20. char** m_argv;
  21. static int32_t threadFunc(void* _userData)
  22. {
  23. MainThreadEntry* self = (MainThreadEntry*)_userData;
  24. return _main_(self->m_argc, self->m_argv);
  25. }
  26. };
  27. struct Context
  28. {
  29. Context()
  30. : m_frame(true)
  31. , m_exit(false)
  32. {
  33. }
  34. int32_t main(int _argc, char** _argv)
  35. {
  36. HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL);
  37. WNDCLASSEX wnd;
  38. memset(&wnd, 0, sizeof(wnd) );
  39. wnd.cbSize = sizeof(wnd);
  40. wnd.lpfnWndProc = DefWindowProc;
  41. wnd.hInstance = instance;
  42. wnd.hIcon = LoadIcon(instance, IDI_APPLICATION);
  43. wnd.hCursor = LoadCursor(instance, IDC_ARROW);
  44. wnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  45. wnd.lpszClassName = "bgfx_letterbox";
  46. wnd.hIconSm = LoadIcon(instance, IDI_APPLICATION);
  47. RegisterClassExA(&wnd);
  48. memset(&wnd, 0, sizeof(wnd) );
  49. wnd.cbSize = sizeof(wnd);
  50. wnd.style = CS_HREDRAW | CS_VREDRAW;
  51. wnd.lpfnWndProc = wndProc;
  52. wnd.hInstance = instance;
  53. wnd.hIcon = LoadIcon(instance, IDI_APPLICATION);
  54. wnd.hCursor = LoadCursor(instance, IDC_ARROW);
  55. wnd.lpszClassName = "bgfx";
  56. wnd.hIconSm = LoadIcon(instance, IDI_APPLICATION);
  57. RegisterClassExA(&wnd);
  58. HWND hwnd = CreateWindowA("bgfx_letterbox"
  59. , "BGFX"
  60. , WS_POPUP|WS_SYSMENU
  61. , -32000
  62. , -32000
  63. , 0
  64. , 0
  65. , NULL
  66. , NULL
  67. , instance
  68. , 0
  69. );
  70. m_hwnd = CreateWindowA("bgfx"
  71. , "BGFX"
  72. , WS_OVERLAPPEDWINDOW|WS_VISIBLE
  73. , 0
  74. , 0
  75. , DEFAULT_WIDTH
  76. , DEFAULT_HEIGHT
  77. , hwnd
  78. , NULL
  79. , instance
  80. , 0
  81. );
  82. bgfx::setHwnd(m_hwnd);
  83. adjust(DEFAULT_WIDTH, DEFAULT_HEIGHT, true);
  84. MainThreadEntry mte;
  85. mte.m_argc = _argc;
  86. mte.m_argv = _argv;
  87. bx::Thread thread;
  88. thread.init(mte.threadFunc, &mte);
  89. MSG msg;
  90. msg.message = WM_NULL;
  91. while (!m_exit)
  92. {
  93. WaitMessage();
  94. while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) )
  95. {
  96. TranslateMessage(&msg);
  97. DispatchMessage(&msg);
  98. }
  99. }
  100. thread.shutdown();
  101. return 0;
  102. }
  103. LRESULT process(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  104. {
  105. switch (_id)
  106. {
  107. case WM_CLOSE:
  108. TerminateProcess(GetCurrentProcess(), 0);
  109. break;
  110. case WM_SIZING:
  111. {
  112. RECT clientRect;
  113. GetClientRect(_hwnd, &clientRect);
  114. uint32_t width = clientRect.right-clientRect.left;
  115. uint32_t height = clientRect.bottom-clientRect.top;
  116. RECT& rect = *(RECT*)_lparam;
  117. uint32_t frameWidth = rect.right-rect.left - width;
  118. uint32_t frameHeight = rect.bottom-rect.top - height;
  119. switch (_wparam)
  120. {
  121. case WMSZ_LEFT:
  122. case WMSZ_RIGHT:
  123. {
  124. float aspectRatio = 1.0f/m_aspectRatio;
  125. width = bx::uint32_max(DEFAULT_WIDTH/4, width);
  126. height = uint32_t(float(width)*aspectRatio);
  127. }
  128. break;
  129. default:
  130. {
  131. float aspectRatio = m_aspectRatio;
  132. height = bx::uint32_max(DEFAULT_HEIGHT/4, height);
  133. width = uint32_t(float(height)*aspectRatio);
  134. }
  135. break;
  136. }
  137. rect.right = rect.left + width + frameWidth;
  138. rect.bottom = rect.top + height + frameHeight;
  139. SetWindowPos(_hwnd
  140. , HWND_TOP
  141. , rect.left
  142. , rect.top
  143. , (rect.right-rect.left)
  144. , (rect.bottom-rect.top)
  145. , SWP_SHOWWINDOW
  146. );
  147. }
  148. return 0;
  149. case WM_SYSCOMMAND:
  150. switch (_wparam)
  151. {
  152. case SC_MINIMIZE:
  153. case SC_RESTORE:
  154. {
  155. HWND parent = GetWindow(_hwnd, GW_OWNER);
  156. if (NULL != parent)
  157. {
  158. PostMessage(parent, _id, _wparam, _lparam);
  159. }
  160. }
  161. }
  162. break;
  163. case WM_KEYDOWN:
  164. case WM_SYSKEYDOWN:
  165. if ((WM_KEYDOWN == _id && VK_F11 == _wparam)
  166. || (WM_SYSKEYDOWN == _id && VK_RETURN == _wparam) )
  167. {
  168. toggleWindowFrame();
  169. }
  170. break;
  171. default:
  172. break;
  173. }
  174. return DefWindowProc(_hwnd, _id, _wparam, _lparam);
  175. }
  176. void adjust(uint32_t _width, uint32_t _height, bool _windowFrame)
  177. {
  178. m_width = _width;
  179. m_height = _height;
  180. m_aspectRatio = float(_width)/float(_height);
  181. ShowWindow(m_hwnd, SW_SHOWNORMAL);
  182. RECT rect;
  183. RECT newrect = {0, 0, (LONG)_width, (LONG)_height};
  184. DWORD style = WS_POPUP|WS_SYSMENU;
  185. if (m_frame)
  186. {
  187. GetWindowRect(m_hwnd, &m_rect);
  188. m_style = GetWindowLong(m_hwnd, GWL_STYLE);
  189. }
  190. if (_windowFrame)
  191. {
  192. rect = m_rect;
  193. style = m_style;
  194. }
  195. else
  196. {
  197. #if defined(__MINGW32__)
  198. rect = m_rect;
  199. style = m_style;
  200. #else
  201. HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
  202. MONITORINFO mi;
  203. mi.cbSize = sizeof(mi);
  204. GetMonitorInfo(monitor, &mi);
  205. newrect = mi.rcMonitor;
  206. rect = mi.rcMonitor;
  207. #endif // !defined(__MINGW__)
  208. }
  209. SetWindowLong(m_hwnd, GWL_STYLE, style);
  210. AdjustWindowRect(&newrect, style, FALSE);
  211. UpdateWindow(m_hwnd);
  212. if (rect.left == -32000
  213. || rect.top == -32000)
  214. {
  215. rect.left = 0;
  216. rect.top = 0;
  217. }
  218. int32_t left = rect.left;
  219. int32_t top = rect.top;
  220. int32_t width = (newrect.right-newrect.left);
  221. int32_t height = (newrect.bottom-newrect.top);
  222. if (!_windowFrame)
  223. {
  224. float aspectRatio = 1.0f/m_aspectRatio;
  225. width = bx::uint32_max(DEFAULT_WIDTH/4, width);
  226. height = uint32_t(float(width)*aspectRatio);
  227. left = newrect.left+(newrect.right-newrect.left-width)/2;
  228. top = newrect.top+(newrect.bottom-newrect.top-height)/2;
  229. }
  230. HWND parent = GetWindow(m_hwnd, GW_OWNER);
  231. if (NULL != parent)
  232. {
  233. if (_windowFrame)
  234. {
  235. SetWindowPos(parent
  236. , HWND_TOP
  237. , -32000
  238. , -32000
  239. , 0
  240. , 0
  241. , SWP_SHOWWINDOW
  242. );
  243. }
  244. else
  245. {
  246. SetWindowPos(parent
  247. , HWND_TOP
  248. , newrect.left
  249. , newrect.top
  250. , newrect.right-newrect.left
  251. , newrect.bottom-newrect.top
  252. , SWP_SHOWWINDOW
  253. );
  254. }
  255. }
  256. SetWindowPos(m_hwnd
  257. , HWND_TOP
  258. , left
  259. , top
  260. , width
  261. , height
  262. , SWP_SHOWWINDOW
  263. );
  264. ShowWindow(m_hwnd, SW_RESTORE);
  265. m_frame = _windowFrame;
  266. }
  267. static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam);
  268. void toggleWindowFrame()
  269. {
  270. adjust(m_width, m_height, !m_frame);
  271. }
  272. HWND m_hwnd;
  273. RECT m_rect;
  274. DWORD m_style;
  275. uint32_t m_width;
  276. uint32_t m_height;
  277. float m_aspectRatio;
  278. bool m_frame;
  279. bool m_exit;
  280. };
  281. static Context s_ctx;
  282. LRESULT CALLBACK Context::wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  283. {
  284. return s_ctx.process(_hwnd, _id, _wparam, _lparam);
  285. }
  286. Event::Enum poll()
  287. {
  288. return Event::Nop;
  289. }
  290. } // namespace entry
  291. int main(int _argc, char** _argv)
  292. {
  293. using namespace entry;
  294. return s_ctx.main(_argc, _argv);
  295. }
  296. #endif // BX_PLATFORM_WINDOWS