1 { Copyright (C) 2005 Bas Steendijk and Peter Green
\r
2 For conditions of distribution and use, see copyright notice in zlib_license.txt
\r
3 which is included in the package
\r
4 ----------------------------------------------------------------------------- }
\r
9 lcore compatible interface for windows
\r
16 //note: events after release are normal and are the apps responsibility to deal with safely
\r
20 classes,windows,mmsystem;
\r
25 tlcomponent = class(tcomponent)
\r
29 destructor destroy; override;
\r
32 tltimer=class(tlcomponent)
\r
35 procedure setenabled(newvalue : boolean);
\r
37 ontimer:tnotifyevent;
\r
38 initialevent:boolean;
\r
39 initialdone:boolean;
\r
42 interval:integer; {miliseconds, default 1000}
\r
44 property enabled:boolean read fenabled write setenabled;
\r
45 constructor create(aowner:tcomponent);override;
\r
46 destructor destroy;override;
\r
49 ttaskevent=procedure(wparam,lparam:longint) of object;
\r
51 tltask=class(tobject)
\r
53 handler : ttaskevent;
\r
58 constructor create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
61 procedure messageloop;
\r
62 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
63 procedure disconnecttasks(aobj:tobject);
\r
64 procedure exitmessageloop;
\r
65 procedure processmessages;
\r
68 onshutdown:procedure(s:ansistring);
\r
81 WINMSG_TASK=WM_USER;
\r
86 timesubstract:integer;
\r
87 firsttask,lasttask,currenttask:tltask;
\r
89 procedure tlcomponent.release;
\r
94 destructor tlcomponent.destroy;
\r
96 disconnecttasks(self);
\r
100 {------------------------------------------------------------------------------}
\r
102 procedure tltimer.setenabled(newvalue : boolean);
\r
104 fenabled := newvalue;
\r
106 initialdone := false;
\r
109 constructor tltimer.create;
\r
111 inherited create(AOwner);
\r
112 nexttimer := firsttimer;
\r
115 if assigned(nexttimer) then nexttimer.prevtimer := self;
\r
116 firsttimer := self;
\r
123 destructor tltimer.destroy;
\r
125 if prevtimer <> nil then begin
\r
126 prevtimer.nexttimer := nexttimer;
\r
128 firsttimer := nexttimer;
\r
130 if nexttimer <> nil then begin
\r
131 nexttimer.prevtimer := prevtimer;
\r
136 {------------------------------------------------------------------------------}
\r
138 function wcore_timehandler:integer;
\r
143 currenttimer,temptimer:tltimer;
\r
145 if not assigned(firsttimer) then begin
\r
150 tvnow := timegettime;
\r
151 if (tvnow and ((-1) shl rollover_bits)) <> timesubstract then begin
\r
152 currenttimer := firsttimer;
\r
153 while assigned(currenttimer) do begin
\r
154 dec(currenttimer.nextts,(1 shl rollover_bits));
\r
155 currenttimer := currenttimer.nexttimer;
\r
157 timesubstract := tvnow and ((-1) shl rollover_bits);
\r
159 tvnow := tvnow and ((1 shl rollover_bits)-1);
\r
161 currenttimer := firsttimer;
\r
162 while assigned(currenttimer) do begin
\r
163 if tvnow >= currenttimer.nextts then begin
\r
164 if assigned(currenttimer.ontimer) then begin
\r
165 if currenttimer.enabled then begin
\r
166 if currenttimer.initialevent or currenttimer.initialdone then currenttimer.ontimer(currenttimer);
\r
167 currenttimer.initialdone := true;
\r
170 currenttimer.nextts := tvnow+currenttimer.interval;
\r
172 temptimer := currenttimer;
\r
173 currenttimer := currenttimer.nexttimer;
\r
174 if temptimer.released then temptimer.free;
\r
178 currenttimer := firsttimer;
\r
179 while assigned(currenttimer) do begin
\r
180 if currenttimer.nextts < tv then tv := currenttimer.nextts;
\r
181 currenttimer := currenttimer.nexttimer;
\r
183 result := tv-tvnow;
\r
184 if result < 15 then result := 15;
\r
187 {------------------------------------------------------------------------------}
\r
189 constructor tltask.create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
192 handler := ahandler;
\r
196 {nexttask := firsttask;
\r
197 firsttask := self;}
\r
198 if assigned(lasttask) then begin
\r
199 lasttask.nexttask := self;
\r
202 postmessage(hwndwcore,WINMSG_TASK,0,0);
\r
205 //ahandler(wparam,lparam);
\r
208 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
210 tltask.create(ahandler,aobj,awparam,alparam);
\r
213 procedure disconnecttasks(aobj:tobject);
\r
215 currenttasklocal : tltask ;
\r
218 for counter := 0 to 1 do begin
\r
219 if counter = 0 then begin
\r
220 currenttasklocal := firsttask; //main list of tasks
\r
222 currenttasklocal := currenttask; //needed in case called from a task
\r
224 // note i don't bother to sestroy the links here as that will happen when
\r
225 // the list of tasks is processed anyway
\r
226 while assigned(currenttasklocal) do begin
\r
227 if currenttasklocal.obj = aobj then begin
\r
228 currenttasklocal.obj := nil;
\r
229 currenttasklocal.handler := nil;
\r
231 currenttasklocal := currenttasklocal.nexttask;
\r
240 if firsttask = nil then exit;
\r
242 currenttask := firsttask;
\r
245 while assigned(currenttask) do begin
\r
246 if assigned(currenttask.handler) then currenttask.handler(currenttask.wparam,currenttask.lparam);
\r
247 temptask := currenttask;
\r
248 currenttask := currenttask.nexttask;
\r
251 currenttask := nil;
\r
254 {------------------------------------------------------------------------------}
\r
256 procedure exitmessageloop;
\r
258 postmessage(hwndwcore,WM_QUIT,0,0);
\r
261 {$ifdef threadtimer}
\r
264 const timerid_wcore=$1000;
\r
267 function MyWindowProc(
\r
271 alParam : LPARAM): Integer; stdcall;
\r
276 Result := 0; // This means we handled the message
\r
278 {MsgRec.hwnd := ahWnd;}
\r
279 MsgRec.wParam := awParam;
\r
280 MsgRec.lParam := alParam;
\r
284 {$ifndef threadtimer}
\r
286 if msgrec.wparam = timerid_wcore then begin
\r
287 a := wcore_timehandler;
\r
288 killtimer(hwndwcore,timerid_wcore);
\r
289 settimer(hwndwcore,timerid_wcore,a,nil);
\r
294 {WINMSG_TASK:dotasks;}
\r
303 Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
\r
309 MyWindowClass : TWndClass = (style : 0;
\r
310 lpfnWndProc : @MyWindowProc;
\r
317 lpszMenuName : nil;
\r
318 lpszClassName : 'wcoreClass');
\r
320 procedure messageloop;
\r
325 if Windows.RegisterClass(MyWindowClass) = 0 then halt;
\r
326 //writeln('about to create wcore handle, hinstance=',hinstance);
\r
327 hwndwcore := CreateWindowEx(WS_EX_TOOLWINDOW,
\r
328 MyWindowClass.lpszClassName,
\r
329 '', { Window name }
\r
330 WS_POPUP, { Window Style }
\r
332 0, 0, { Width, Height }
\r
335 HInstance, { hInstance }
\r
336 nil); { CreateParam }
\r
338 if hwndwcore = 0 then halt;
\r
340 {$ifdef threadtimer}
\r
343 if settimer(hwndwcore,timerid_wcore,15,nil) = 0 then halt;
\r
347 while GetMessage(MsgRec, 0, 0, 0) do begin
\r
348 TranslateMessage(MsgRec);
\r
349 DispatchMessage(MsgRec);
\r
350 {if not peekmessage(msgrec,0,0,0,PM_NOREMOVE) then onidle}
\r
353 if hWndwcore <> 0 then begin
\r
354 DestroyWindow(hwndwcore);
\r
358 {$ifdef threadtimer}
\r
361 killtimer(hwndwcore,timerid_wcore);
\r
365 function ProcessMessage : Boolean;
\r
370 if PeekMessage(Msg, hwndwcore, 0, 0, PM_REMOVE) then begin
\r
372 DispatchMessage(Msg);
\r
376 procedure processmessages;
\r
378 while processmessage do;
\r