w32smsg.inc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. {
  2. System independent system interface for win32/win64
  3. Copyright (c) 2000 by Pierre Muller
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. Library General Public License for more details.
  10. You should have received a copy of the GNU Library General Public
  11. License along with this library; if not, write to the Free
  12. Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  13. MA 02110-1301, USA.
  14. }
  15. uses
  16. windows,dos,winevent;
  17. var
  18. ChangeSystemEvents : TCriticalSection;
  19. Const
  20. SystemEventActive : Boolean = false;
  21. procedure SystemEventHandler(var ir:INPUT_RECORD);
  22. var
  23. e : TSystemEvent;
  24. begin
  25. { WINDOW_BUFFER_SIZE_EVENT is triggered by buffer size changes
  26. but we are interested in console size changes, thus its handled below
  27. in PollSystemEvent }
  28. if (ir.EventType in [FOCUS_EVENT{,WINDOW_BUFFER_SIZE_EVENT}]) then
  29. begin
  30. EnterCriticalSection(ChangeSystemEvents);
  31. if (ir.EventType=FOCUS_EVENT) then
  32. begin
  33. if ir.Event.FocusEvent.bSetFocus then
  34. e.typ:=SysSetFocus
  35. else
  36. e.typ:=SysReleaseFocus;
  37. end
  38. else
  39. begin
  40. e.typ:=SysResize;
  41. e.x:=ir.Event.WindowBufferSizeEvent.dwSize.x;
  42. e.y:=ir.Event.WindowBufferSizeEvent.dwSize.y;
  43. end;
  44. PutSystemEvent(e);
  45. LeaveCriticalSection(ChangeSystemEvents);
  46. end;
  47. end;
  48. var
  49. Xsize, YSize : longint;
  50. function HandleConsoleCtrl(typ : dword) : BOOL; stdcall;
  51. var
  52. SE : TSystemEvent;
  53. begin
  54. HandleConsoleCtrl:=false;
  55. case typ of
  56. CTRL_CLOSE_EVENT,
  57. CTRL_LOGOFF_EVENT,
  58. CTRL_SHUTDOWN_EVENT :
  59. begin
  60. SE.typ:=SysClose;
  61. SE.CloseTyp:=typ;
  62. PutSystemEvent(SE);
  63. HandleConsoleCtrl:=true;
  64. end;
  65. end;
  66. end;
  67. procedure InitSystemMsg;
  68. var
  69. mode : dword;
  70. ConsoleScreenBufferInfo : Console_screen_buffer_info;
  71. begin
  72. if SystemEventActive then
  73. exit;
  74. // enable Window events
  75. GetConsoleMode(TextRec(Input).Handle,@mode);
  76. mode:=mode or ENABLE_WINDOW_INPUT;
  77. SetConsoleMode(TextRec(Input).Handle,mode);
  78. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  79. @ConsoleScreenBufferInfo);
  80. XSize:=ConsoleScreenBufferInfo.srWindow.right-ConsoleScreenBufferInfo.srWindow.left+1;
  81. YSize:=ConsoleScreenBufferInfo.srWindow.bottom-ConsoleScreenBufferInfo.srWindow.top+1;
  82. PendingSystemHead:=@PendingSystemEvent;
  83. PendingSystemTail:=@PendingSystemEvent;
  84. PendingSystemEvents:=0;
  85. FillChar(LastSystemEvent,sizeof(TSystemEvent),0);
  86. InitializeCriticalSection(ChangeSystemEvents);
  87. SetResizeEventHandler(@SystemEventHandler);
  88. SetFocusEventHandler(@SystemEventHandler);
  89. SetConsoleCtrlHandler(@HandleConsoleCtrl,true);
  90. SystemEventActive:=true;
  91. end;
  92. procedure DoneSystemMsg;
  93. var
  94. mode : dword;
  95. begin
  96. if not SystemEventActive then
  97. exit;
  98. // disable System events
  99. GetConsoleMode(TextRec(Input).Handle,@mode);
  100. mode:=mode and (not ENABLE_WINDOW_INPUT);
  101. SetConsoleMode(TextRec(Input).Handle,mode);
  102. SetResizeEventHandler(nil);
  103. SetFocusEventHandler(nil);
  104. DeleteCriticalSection(ChangeSystemEvents);
  105. SetConsoleCtrlHandler(@HandleConsoleCtrl,false);
  106. SystemEventActive:=false;
  107. end;
  108. procedure GetSystemEvent(var SystemEvent: TSystemEvent);
  109. var
  110. b : byte;
  111. begin
  112. repeat
  113. EnterCriticalSection(ChangeSystemEvents);
  114. b:=PendingSystemEvents;
  115. LeaveCriticalSection(ChangeSystemEvents);
  116. if b>0 then
  117. break
  118. else
  119. sleep(50);
  120. until false;
  121. EnterCriticalSection(ChangeSystemEvents);
  122. SystemEvent:=PendingSystemHead^;
  123. inc(PendingSystemHead);
  124. if longint(PendingSystemHead)=longint(@PendingSystemEvent)+sizeof(PendingSystemEvent) then
  125. PendingSystemHead:=@PendingSystemEvent;
  126. dec(PendingSystemEvents);
  127. LastSystemEvent:=SystemEvent;
  128. LeaveCriticalSection(ChangeSystemEvents);
  129. end;
  130. function PollSystemEvent(var SystemEvent: TSystemEvent):boolean;
  131. var
  132. ConsoleScreenBufferInfo : Console_screen_buffer_info;
  133. NewXSize, NewYSize : longint;
  134. begin
  135. EnterCriticalSection(ChangeSystemEvents);
  136. if PendingSystemEvents>0 then
  137. begin
  138. SystemEvent:=PendingSystemHead^;
  139. PollSystemEvent:=true;
  140. end
  141. else
  142. begin
  143. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  144. @ConsoleScreenBufferInfo);
  145. NewXSize:=ConsoleScreenBufferInfo.srWindow.right-ConsoleScreenBufferInfo.srWindow.left+1;
  146. NewYSize:=ConsoleScreenBufferInfo.srWindow.bottom-ConsoleScreenBufferInfo.srWindow.top+1;
  147. if (XSize<>NewXSize) or (YSize<>NewYSize) then
  148. begin
  149. SystemEvent.typ:=SysResize;
  150. SystemEvent.x:=NewXSize;
  151. SystemEvent.y:=NewYSize;
  152. PutSystemEvent(SystemEvent);
  153. XSize:=NewXSize;
  154. YSize:=NewYSize;
  155. PollSystemEvent:=true;
  156. end
  157. else
  158. PollSystemEvent:=false;
  159. end;
  160. LeaveCriticalSection(ChangeSystemEvents);
  161. end;