2
$Id: winevent.pp,v 1.3 2002/09/07 16:01:29 peter Exp $
3
This file is part of the Free Pascal run time library.
4
Copyright (c) 1999-2000 by Florian Klaempfl
5
member of the Free Pascal development team
7
Event Handling unit for setting Keyboard and Mouse Handlers
9
See the file COPYING.FPC, included in this distribution,
10
for details about the copyright.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
**********************************************************************}
21
We need this unit to implement keyboard and mouse,
22
because win32 uses only one message queue for mouse and key events
29
TEventProcedure = Procedure(var ir:INPUT_RECORD);
31
{ these procedures must be used to set the event handlers }
32
{ these doesn't do something, they signal only the }
33
{ the upper layer that an event occured, this event }
34
{ must be handled with Win32-API function by the upper }
36
Procedure SetMouseEventHandler(p : TEventProcedure);
37
Procedure SetKeyboardEventHandler(p : TEventProcedure);
38
Procedure SetFocusEventHandler(p : TEventProcedure);
39
Procedure SetMenuEventHandler(p : TEventProcedure);
40
Procedure SetResizeEventHandler(p : TEventProcedure);
41
Procedure SetUnknownEventHandler(p : TEventProcedure);
43
{ these procedures must be used to get the event handlers }
44
Function GetMouseEventHandler : TEventProcedure;
45
Function GetKeyboardEventHandler : TEventProcedure;
46
Function GetFocusEventHandler : TEventProcedure;
47
Function GetMenuEventHandler : TEventProcedure;
48
Function GetResizeEventHandler : TEventProcedure;
49
Function GetUnknownEventHandler : TEventProcedure;
54
{ these procedures are called if an event occurs }
55
MouseEventHandler : TEventProcedure = nil;
56
KeyboardEventHandler : TEventProcedure = nil;
57
FocusEventHandler : TEventProcedure = nil;
58
MenuEventHandler : TEventProcedure = nil;
59
ResizeEventHandler : TEventProcedure = nil;
60
UnknownEventHandler : TEventProcedure = nil;
62
{ if this counter is zero, the event handler thread is killed }
63
InstalledHandlers : Byte = 0;
66
HandlerChanging : TCriticalSection;
67
EventThreadHandle : Handle;
68
EventThreadID : DWord;
70
{ true, if the event handler should be stoped }
71
ExitEventHandleThread : boolean;
73
Function GetMouseEventHandler : TEventProcedure;
75
GetMouseEventHandler:=MouseEventHandler;
79
Function GetKeyboardEventHandler : TEventProcedure;
81
GetKeyboardEventHandler:=KeyboardEventHandler;
85
Function GetFocusEventHandler : TEventProcedure;
87
GetFocusEventHandler:=FocusEventHandler;
91
Function GetMenuEventHandler : TEventProcedure;
93
GetMenuEventHandler:=MenuEventHandler;
97
Function GetResizeEventHandler : TEventProcedure;
99
GetResizeEventHandler:=ResizeEventHandler;
103
Function GetUnknownEventHandler : TEventProcedure;
105
GetUnknownEventHandler:=UnknownEventHandler;
109
Function EventHandleThread(p : pointer) : DWord;StdCall;
113
ir : array[0..irsize-1] of TInputRecord;
116
while not(ExitEventHandleThread) do
118
{ wait for an event }
119
WaitForSingleObject(StdInputHandle,INFINITE);
120
{ guard this code, else it is doomed to crash, if the
121
thread is switched between the assigned test and
122
the call and the handler is removed
124
if not(ExitEventHandleThread) then
126
EnterCriticalSection(HandlerChanging);
127
{ read, but don't remove the event }
128
if ReadConsoleInput(StdInputHandle,ir[0],irsize,dwRead) then
134
case ir[i].EventType of
137
if assigned(KeyboardEventHandler) then
138
KeyboardEventHandler(ir[i]);
143
if assigned(MouseEventHandler) then
144
MouseEventHandler(ir[i]);
147
WINDOW_BUFFER_SIZE_EVENT:
149
if assigned(ResizeEventHandler) then
150
ResizeEventHandler(ir[i]);
155
if assigned(MenuEventHandler) then
156
MenuEventHandler(ir[i]);
161
if assigned(FocusEventHandler) then
162
FocusEventHandler(ir[i]);
167
if assigned(UnknownEventHandler) then
168
UnknownEventHandler(ir[i]);
174
LeaveCriticalSection(HandlerChanging);
177
EventHandleThread:=0;
180
Procedure NewEventHandlerInstalled(p,oldp : TEventProcedure);
186
oldcount:=InstalledHandlers;
187
if Pointer(oldp)<>nil then
188
dec(InstalledHandlers);
189
if Pointer(p)<>nil then
190
inc(InstalledHandlers);
191
{ start event handler thread }
192
if (oldcount=0) and (InstalledHandlers=1) then
194
ExitEventHandleThread:=false;
195
EventThreadHandle:=CreateThread(nil,0,@EventHandleThread,
196
nil,0,EventThreadID);
198
{ stop and destroy event handler thread }
199
else if (oldcount=1) and (InstalledHandlers=0) then
201
ExitEventHandleThread:=true;
202
{ create a dummy event and sent it to the thread, so
203
we can leave WaitForSingleObject }
204
ir.EventType:=KEY_EVENT;
205
{ mouse event can be disabled by mouse.inc code
207
so use a key event instead PM }
208
WriteConsoleInput(StdInputHandle,ir,1,written);
209
{ wait, til the thread is ready }
210
WaitForSingleObject(EventThreadHandle,INFINITE);
211
CloseHandle(EventThreadHandle);
216
Procedure SetMouseEventHandler(p : TEventProcedure);
218
oldp : TEventProcedure;
220
EnterCriticalSection(HandlerChanging);
221
oldp:=MouseEventHandler;
222
MouseEventHandler:=p;
223
NewEventHandlerInstalled(MouseEventHandler,oldp);
224
LeaveCriticalSection(HandlerChanging);
228
Procedure SetKeyboardEventHandler(p : TEventProcedure);
230
oldp : TEventProcedure;
232
EnterCriticalSection(HandlerChanging);
233
oldp:=KeyboardEventHandler;
234
KeyboardEventHandler:=p;
235
NewEventHandlerInstalled(KeyboardEventHandler,oldp);
236
LeaveCriticalSection(HandlerChanging);
240
Procedure SetFocusEventHandler(p : TEventProcedure);
242
oldp : TEventProcedure;
244
EnterCriticalSection(HandlerChanging);
245
oldp:=FocusEventHandler;
246
FocusEventHandler:=p;
247
NewEventHandlerInstalled(FocusEventHandler,oldp);
248
LeaveCriticalSection(HandlerChanging);
252
Procedure SetMenuEventHandler(p : TEventProcedure);
254
oldp : TEventProcedure;
256
EnterCriticalSection(HandlerChanging);
257
oldp:=MenuEventHandler;
259
NewEventHandlerInstalled(MenuEventHandler,oldp);
260
LeaveCriticalSection(HandlerChanging);
264
Procedure SetResizeEventHandler(p : TEventProcedure);
266
oldp : TEventProcedure;
268
EnterCriticalSection(HandlerChanging);
269
oldp:=ResizeEventHandler;
270
ResizeEventHandler:=p;
271
NewEventHandlerInstalled(ResizeEventHandler,oldp);
272
LeaveCriticalSection(HandlerChanging);
276
Procedure SetUnknownEventHandler(p : TEventProcedure);
278
oldp : TEventProcedure;
280
EnterCriticalSection(HandlerChanging);
281
oldp:=UnknownEventHandler;
282
UnknownEventHandler:=p;
283
NewEventHandlerInstalled(UnknownEventHandler,oldp);
284
LeaveCriticalSection(HandlerChanging);
289
InitializeCriticalSection(HandlerChanging);
292
{ Uninstall all handlers }
293
{ this stops also the event handler thread }
294
SetMouseEventHandler(nil);
295
SetKeyboardEventHandler(nil);
296
SetFocusEventHandler(nil);
297
SetMenuEventHandler(nil);
298
SetResizeEventHandler(nil);
299
SetUnknownEventHandler(nil);
300
{ delete the critical section object }
301
DeleteCriticalSection(HandlerChanging);
306
$Log: winevent.pp,v $
307
Revision 1.3 2002/09/07 16:01:29 peter
308
* old logs removed and tabs fixed