application.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #if defined(Hiro_Application)
  2. namespace hiro {
  3. static auto Application_keyboardProc(HWND, UINT, WPARAM, LPARAM) -> bool;
  4. static auto Application_processDialogMessage(MSG&) -> void;
  5. static auto CALLBACK Window_windowProc(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
  6. auto pApplication::exit() -> void {
  7. quit();
  8. auto processID = GetCurrentProcessId();
  9. auto handle = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, true, processID);
  10. TerminateProcess(handle, 0);
  11. }
  12. auto pApplication::modal() -> bool {
  13. return state().modalCount > 0;
  14. }
  15. auto pApplication::run() -> void {
  16. while(!Application::state().quit) {
  17. if(Application::state().onMain) {
  18. //doMain() is responsible for sleeping the thread where practical
  19. Application::doMain();
  20. if(Application::state().quit) break;
  21. } else {
  22. //avoid consuming 100% CPU thread usage
  23. usleep(20 * 1000);
  24. }
  25. //called after doMain(), in case doMain() calls Application::quit()
  26. processEvents();
  27. }
  28. }
  29. auto pApplication::pendingEvents() -> bool {
  30. MSG msg;
  31. return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
  32. }
  33. auto pApplication::processEvents() -> void {
  34. while(pendingEvents()) {
  35. MSG msg;
  36. if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
  37. Application_processDialogMessage(msg);
  38. }
  39. }
  40. }
  41. auto Application_processDialogMessage(MSG& msg) -> void {
  42. if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP
  43. || msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) {
  44. if(Application_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam)) {
  45. DispatchMessage(&msg);
  46. return;
  47. }
  48. }
  49. if(!IsDialogMessage(GetForegroundWindow(), &msg)) {
  50. TranslateMessage(&msg);
  51. DispatchMessage(&msg);
  52. }
  53. }
  54. auto pApplication::quit() -> void {
  55. PostQuitMessage(0);
  56. }
  57. auto pApplication::setScreenSaver(bool screenSaver) -> void {
  58. }
  59. auto pApplication::initialize() -> void {
  60. CoInitialize(0);
  61. InitCommonControls();
  62. WNDCLASS wc{};
  63. #if defined(Hiro_Window)
  64. wc.cbClsExtra = 0;
  65. wc.cbWndExtra = 0;
  66. wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  67. wc.hCursor = LoadCursor(0, IDC_ARROW);
  68. wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
  69. wc.hInstance = GetModuleHandle(0);
  70. wc.lpfnWndProc = Window_windowProc;
  71. wc.lpszClassName = L"hiroWindow";
  72. wc.lpszMenuName = 0;
  73. wc.style = CS_HREDRAW | CS_VREDRAW;
  74. RegisterClass(&wc);
  75. #endif
  76. #if defined(Hiro_PopupMenu)
  77. wc.cbClsExtra = 0;
  78. wc.cbWndExtra = 0;
  79. wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  80. wc.hCursor = LoadCursor(0, IDC_ARROW);
  81. wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
  82. wc.hInstance = GetModuleHandle(0);
  83. wc.lpfnWndProc = Menu_windowProc;
  84. wc.lpszClassName = L"hiroPopupMenu";
  85. wc.lpszMenuName = 0;
  86. wc.style = CS_HREDRAW | CS_VREDRAW;
  87. RegisterClass(&wc);
  88. #endif
  89. #if defined(Hiro_Widget)
  90. wc.cbClsExtra = 0;
  91. wc.cbWndExtra = 0;
  92. wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  93. wc.hCursor = LoadCursor(0, IDC_ARROW);
  94. wc.hIcon = LoadIcon(0, IDI_APPLICATION);
  95. wc.hInstance = GetModuleHandle(0);
  96. wc.lpfnWndProc = ToolTip_windowProc;
  97. wc.lpszClassName = L"hiroToolTip";
  98. wc.lpszMenuName = 0;
  99. wc.style = CS_HREDRAW | CS_VREDRAW;
  100. RegisterClass(&wc);
  101. #endif
  102. #if defined(Hiro_Widget)
  103. wc.cbClsExtra = 0;
  104. wc.cbWndExtra = 0;
  105. wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  106. wc.hCursor = LoadCursor(0, IDC_ARROW);
  107. wc.hIcon = LoadIcon(0, IDI_APPLICATION);
  108. wc.hInstance = GetModuleHandle(0);
  109. wc.lpfnWndProc = Default_windowProc;
  110. wc.lpszClassName = L"hiroWidget";
  111. wc.lpszMenuName = 0;
  112. wc.style = CS_HREDRAW | CS_VREDRAW;
  113. RegisterClass(&wc);
  114. #endif
  115. pKeyboard::initialize();
  116. pWindow::initialize();
  117. }
  118. auto pApplication::state() -> State& {
  119. static State state;
  120. return state;
  121. }
  122. static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> bool {
  123. if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
  124. GUITHREADINFO info{sizeof(GUITHREADINFO)};
  125. GetGUIThreadInfo(GetCurrentThreadId(), &info);
  126. auto object = (mObject*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
  127. if(!object) return false;
  128. auto objectWindow = (mObject*)GetWindowLongPtr(GetAncestor(info.hwndFocus, GA_ROOT), GWLP_USERDATA);
  129. if(!objectWindow) return false;
  130. if(auto window = dynamic_cast<mWindow*>(objectWindow)) {
  131. if(auto self = window->self()) {
  132. if(!self->_modalityDisabled()) {
  133. if(auto code = pKeyboard::_translate(wparam, lparam)) {
  134. if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) {
  135. window->doKeyPress(code);
  136. }
  137. if(msg == WM_KEYUP || msg == WM_SYSKEYUP) {
  138. window->doKeyRelease(code);
  139. }
  140. }
  141. //TODO: does this really need to be hooked here?
  142. if(msg == WM_KEYDOWN && wparam == VK_ESCAPE && window->state.dismissable) {
  143. if(auto result = self->windowProc(self->hwnd, WM_CLOSE, wparam, lparam)) return result();
  144. }
  145. }
  146. }
  147. }
  148. if(auto window = object->parentWindow(true)) {
  149. if(auto self = window->self()) {
  150. if(self->_modalityDisabled()) return false;
  151. }
  152. }
  153. if(msg == WM_KEYDOWN) {
  154. //TODO: does this really need to be hooked here?
  155. #if defined(Hiro_Widget)
  156. if(auto widget = dynamic_cast<mWidget*>(object)) {
  157. if(auto self = widget->self()) {
  158. if(auto result = self->windowProc(self->hwnd, msg, wparam, lparam)) {
  159. return result();
  160. }
  161. }
  162. }
  163. #endif
  164. }
  165. return false;
  166. }
  167. }
  168. #endif