msgloop.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/msgloop.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 2/05/02 1:17p $*
  29. * *
  30. * $Revision:: 2 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * Add_Accelerator -- Adds a keyboard accelerator to the message handler. *
  35. * Add_Modeless_Dialog -- Adds a modeless dialog box to the message handler. *
  36. * Remove_Accelerator -- Removes an accelerator from the message processor. *
  37. * Remove_Modeless_Dialog -- Removes the dialog box from the message tracking handler. *
  38. * Windows_Message_Handler -- Handles windows message. *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "always.h"
  41. #include "vector.h"
  42. #include "win.h"
  43. /*
  44. ** Tracks modeless dialog box messages by keeping a record of all active modeless dialog
  45. ** box handles and then determining if the windows message applies to the dialog box. If it
  46. ** does, then the default message handling should not be performed.
  47. */
  48. static DynamicVectorClass<HWND> _ModelessDialogs;
  49. /*
  50. ** Tracks windows accelerators with this structure.
  51. */
  52. struct AcceleratorTracker {
  53. AcceleratorTracker(HWND window = NULL, HACCEL accelerator = NULL) : Accelerator(accelerator), Window(window) {}
  54. int operator == (AcceleratorTracker const & acc) const {return(Accelerator == acc.Accelerator && Window == acc.Window);}
  55. int operator != (AcceleratorTracker const & acc) const {return(!(*this == acc));}
  56. HACCEL Accelerator;
  57. HWND Window;
  58. };
  59. static DynamicVectorClass<AcceleratorTracker> _Accelerators;
  60. /*
  61. ** In those cases where message intercept needs to occur but not for purposes
  62. ** of a modeless dialog box or a windows accelerator, then this is a function
  63. ** pointer to than message intercept handler.
  64. */
  65. bool (*Message_Intercept_Handler)(MSG &msg) = NULL;
  66. /***********************************************************************************************
  67. * Windows_Message_Handler -- Handles windows message. *
  68. * *
  69. * This routine will take all messages that have accumulated in the message queue and *
  70. * dispatch them to their respective recipients. When the message queue has been emptied, *
  71. * then this routine will return. By using this routine, it is possible to have the main *
  72. * program run in the main thread and yet still have it behave like a normal program as *
  73. * far as message handling is concerned. To achieve this, this routine must be called on *
  74. * a semi-frequent basis (a few times a second is plenty). *
  75. * *
  76. * INPUT: none *
  77. * *
  78. * OUTPUT: none *
  79. * *
  80. * WARNINGS: none *
  81. * *
  82. * HISTORY: *
  83. * 05/17/1997 JLB : Created. *
  84. *=============================================================================================*/
  85. void Windows_Message_Handler(void)
  86. {
  87. MSG msg;
  88. /*
  89. ** Process windows messages until the message queue is exhuasted.
  90. */
  91. while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
  92. if (!GetMessage( &msg, NULL, 0, 0 )) {
  93. return;
  94. }
  95. /*
  96. ** Pass the message through any loaded accelerators. If the message
  97. ** was processed by an accelerator, then it doesn't need to be
  98. ** processed by the normal message handling procedure.
  99. */
  100. bool processed = false;
  101. for (int aindex = 0; aindex < _Accelerators.Count(); aindex++) {
  102. if (_Accelerators[aindex].Window) {
  103. if (TranslateAccelerator(_Accelerators[aindex].Window, _Accelerators[aindex].Accelerator, &msg)) {
  104. processed = true;
  105. }
  106. }
  107. break;
  108. }
  109. if (processed) continue;
  110. /*
  111. ** Pass the windows message through any modeless dialogs that may
  112. ** be active. If one of the dialogs processes the message, then
  113. ** it must not be processed by the normal window message handler.
  114. */
  115. for (int index = 0; index < _ModelessDialogs.Count(); index++) {
  116. if (IsDialogMessage(_ModelessDialogs[index], &msg)) {
  117. processed = true;
  118. break;
  119. }
  120. }
  121. if (processed) continue;
  122. /*
  123. ** If the message was not handled by any normal intercept handlers, then
  124. ** submit the message to a custom message handler if one has been provided.
  125. */
  126. if (Message_Intercept_Handler != NULL) {
  127. processed = Message_Intercept_Handler(msg);
  128. }
  129. if (processed) continue;
  130. /*
  131. ** If the message makes it to this point, then it must be a normal message. Process
  132. ** it in the normal fashion. The message will appear in the window message handler
  133. ** for the window that it was directed to.
  134. */
  135. TranslateMessage(&msg);
  136. DispatchMessage(&msg);
  137. }
  138. }
  139. /***********************************************************************************************
  140. * Add_Modeless_Dialog -- Adds a modeless dialog box to the message handler. *
  141. * *
  142. * When a modeless dialog box becomes active, the messages processed by the main message *
  143. * handler must be handled different. This routine is used to inform the message handler *
  144. * that a dialog box is active and messages must be fed to it as appropriate. *
  145. * *
  146. * INPUT: dialog -- Handle to the modeless dialog box. *
  147. * *
  148. * OUTPUT: none *
  149. * *
  150. * WARNINGS: The modeless dialog box must be removed from the tracking system by calling *
  151. * Remove_Modeless_Dialog. Failure to do so when the dialog is destroyed will *
  152. * result in undefined behavior. *
  153. * *
  154. * HISTORY: *
  155. * 05/17/1997 JLB : Created. *
  156. *=============================================================================================*/
  157. void Add_Modeless_Dialog(HWND dialog)
  158. {
  159. _ModelessDialogs.Add(dialog);
  160. }
  161. /***********************************************************************************************
  162. * Remove_Modeless_Dialog -- Removes the dialog box from the message tracking handler. *
  163. * *
  164. * This routine must be called when a modeless dialog is being removed. *
  165. * *
  166. * INPUT: dialog -- Handle to the modeless dialog that was previously submitted to *
  167. * Add_Modeless_Dialog(). *
  168. * *
  169. * OUTPUT: none *
  170. * *
  171. * WARNINGS: Failure to call this routine will result in undefined behavior when the dialog *
  172. * is destroyed. *
  173. * *
  174. * HISTORY: *
  175. * 05/17/1997 JLB : Created. *
  176. *=============================================================================================*/
  177. void Remove_Modeless_Dialog(HWND dialog)
  178. {
  179. _ModelessDialogs.Delete(dialog);
  180. }
  181. /***********************************************************************************************
  182. * Add_Accelerator -- Adds a keyboard accelerator to the message handler. *
  183. * *
  184. * This routine will add a keyboard accelerator to the tracking process for the message *
  185. * handler. If the incoming message is processed by an accelerator, then the normal *
  186. * processing must be altered. By using this routine, the proper behavior of accelerators *
  187. * is maintained. *
  188. * *
  189. * INPUT: window -- The window that the accelerator belongs to. Each accelerator must be *
  190. * assigned to a window. *
  191. * *
  192. * accelerator -- The handler to the windows accelerator. *
  193. * *
  194. * OUTPUT: none *
  195. * *
  196. * WARNINGS: When the accelerator is no longer valid (or the controlling window as been *
  197. * destroyed), the Remove_Accelerator function must be called. *
  198. * *
  199. * HISTORY: *
  200. * 05/17/1997 JLB : Created. *
  201. *=============================================================================================*/
  202. void Add_Accelerator(HWND window, HACCEL accelerator)
  203. {
  204. _Accelerators.Add(AcceleratorTracker(window, accelerator));
  205. }
  206. /***********************************************************************************************
  207. * Remove_Accelerator -- Removes an accelerator from the message processor. *
  208. * *
  209. * This routine must be called when the accelerator or the window it was attached to has *
  210. * been destroyed. *
  211. * *
  212. * INPUT: accelerator -- The accelerator to remove from the tracking system. *
  213. * *
  214. * OUTPUT: none *
  215. * *
  216. * WARNINGS: This routine presumes that the accelerator will not be shared between windows. *
  217. * *
  218. * HISTORY: *
  219. * 05/17/1997 JLB : Created. *
  220. *=============================================================================================*/
  221. void Remove_Accelerator(HACCEL accelerator)
  222. {
  223. for (int index = 0; index < _Accelerators.Count(); index++) {
  224. if (_Accelerators[index].Accelerator == accelerator) {
  225. _Accelerators.Delete(index);
  226. break;
  227. }
  228. }
  229. }