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
34 ontimer:tnotifyevent;
\r
35 initialevent:boolean;
\r
36 initialdone:boolean;
\r
39 interval:integer; {miliseconds, default 1000}
\r
42 constructor create(aowner:tcomponent);override;
\r
43 destructor destroy;override;
\r
46 ttaskevent=procedure(wparam,lparam:longint) of object;
\r
48 tltask=class(tobject)
\r
50 handler : ttaskevent;
\r
55 constructor create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
58 procedure messageloop;
\r
59 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
60 procedure disconnecttasks(aobj:tobject);
\r
61 procedure exitmessageloop;
\r
62 procedure processmessages;
\r
65 onshutdown:procedure(s:string);
\r
78 WINMSG_TASK=WM_USER;
\r
83 timesubstract:integer;
\r
84 firsttask,lasttask,currenttask:tltask;
\r
86 procedure tlcomponent.release;
\r
91 destructor tlcomponent.destroy;
\r
93 disconnecttasks(self);
\r
97 {------------------------------------------------------------------------------}
\r
99 constructor tltimer.create;
\r
101 inherited create(AOwner);
\r
102 nexttimer := firsttimer;
\r
105 if assigned(nexttimer) then nexttimer.prevtimer := self;
\r
106 firsttimer := self;
\r
113 destructor tltimer.destroy;
\r
115 if prevtimer <> nil then begin
\r
116 prevtimer.nexttimer := nexttimer;
\r
118 firsttimer := nexttimer;
\r
120 if nexttimer <> nil then begin
\r
121 nexttimer.prevtimer := prevtimer;
\r
126 {------------------------------------------------------------------------------}
\r
128 function wcore_timehandler:integer;
\r
133 currenttimer,temptimer:tltimer;
\r
135 if not assigned(firsttimer) then begin
\r
140 tvnow := timegettime;
\r
141 if (tvnow and ((-1) shl rollover_bits)) <> timesubstract then begin
\r
142 currenttimer := firsttimer;
\r
143 while assigned(currenttimer) do begin
\r
144 dec(currenttimer.nextts,(1 shl rollover_bits));
\r
145 currenttimer := currenttimer.nexttimer;
\r
147 timesubstract := tvnow and ((-1) shl rollover_bits);
\r
149 tvnow := tvnow and ((1 shl rollover_bits)-1);
\r
151 currenttimer := firsttimer;
\r
152 while assigned(currenttimer) do begin
\r
153 if tvnow >= currenttimer.nextts then begin
\r
154 if assigned(currenttimer.ontimer) then begin
\r
155 if currenttimer.enabled then begin
\r
156 if currenttimer.initialevent or currenttimer.initialdone then currenttimer.ontimer(currenttimer);
\r
157 currenttimer.initialdone := true;
\r
160 currenttimer.nextts := tvnow+currenttimer.interval;
\r
162 temptimer := currenttimer;
\r
163 currenttimer := currenttimer.nexttimer;
\r
164 if temptimer.released then temptimer.free;
\r
168 currenttimer := firsttimer;
\r
169 while assigned(currenttimer) do begin
\r
170 if currenttimer.nextts < tv then tv := currenttimer.nextts;
\r
171 currenttimer := currenttimer.nexttimer;
\r
173 result := tv-tvnow;
\r
174 if result < 15 then result := 15;
\r
177 {------------------------------------------------------------------------------}
\r
179 constructor tltask.create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
182 handler := ahandler;
\r
186 {nexttask := firsttask;
\r
187 firsttask := self;}
\r
188 if assigned(lasttask) then begin
\r
189 lasttask.nexttask := self;
\r
192 postmessage(hwndwcore,WINMSG_TASK,0,0);
\r
195 //ahandler(wparam,lparam);
\r
198 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
200 tltask.create(ahandler,aobj,awparam,alparam);
\r
203 procedure disconnecttasks(aobj:tobject);
\r
205 currenttasklocal : tltask ;
\r
208 for counter := 0 to 1 do begin
\r
209 if counter = 0 then begin
\r
210 currenttasklocal := firsttask; //main list of tasks
\r
212 currenttasklocal := currenttask; //needed in case called from a task
\r
214 // note i don't bother to sestroy the links here as that will happen when
\r
215 // the list of tasks is processed anyway
\r
216 while assigned(currenttasklocal) do begin
\r
217 if currenttasklocal.obj = aobj then begin
\r
218 currenttasklocal.obj := nil;
\r
219 currenttasklocal.handler := nil;
\r
221 currenttasklocal := currenttasklocal.nexttask;
\r
230 if firsttask = nil then exit;
\r
232 currenttask := firsttask;
\r
235 while assigned(currenttask) do begin
\r
236 if assigned(currenttask.handler) then currenttask.handler(currenttask.wparam,currenttask.lparam);
\r
237 temptask := currenttask;
\r
238 currenttask := currenttask.nexttask;
\r
241 currenttask := nil;
\r
244 {------------------------------------------------------------------------------}
\r
246 procedure exitmessageloop;
\r
248 postmessage(hwndwcore,WM_QUIT,0,0);
\r
251 {$ifdef threadtimer}
\r
254 const timerid_wcore=$1000;
\r
257 function MyWindowProc(
\r
261 alParam : LPARAM): Integer; stdcall;
\r
266 Result := 0; // This means we handled the message
\r
268 {MsgRec.hwnd := ahWnd;}
\r
269 MsgRec.wParam := awParam;
\r
270 MsgRec.lParam := alParam;
\r
274 {$ifndef threadtimer}
\r
276 if msgrec.wparam = timerid_wcore then begin
\r
277 a := wcore_timehandler;
\r
278 killtimer(hwndwcore,timerid_wcore);
\r
279 settimer(hwndwcore,timerid_wcore,a,nil);
\r
284 {WINMSG_TASK:dotasks;}
\r
293 Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
\r
299 MyWindowClass : TWndClass = (style : 0;
\r
300 lpfnWndProc : @MyWindowProc;
\r
307 lpszMenuName : nil;
\r
308 lpszClassName : 'wcoreClass');
\r
310 procedure messageloop;
\r
315 if Windows.RegisterClass(MyWindowClass) = 0 then halt;
\r
316 //writeln('about to create wcore handle, hinstance=',hinstance);
\r
317 hwndwcore := CreateWindowEx(WS_EX_TOOLWINDOW,
\r
318 MyWindowClass.lpszClassName,
\r
319 '', { Window name }
\r
320 WS_POPUP, { Window Style }
\r
322 0, 0, { Width, Height }
\r
325 HInstance, { hInstance }
\r
326 nil); { CreateParam }
\r
328 if hwndwcore = 0 then halt;
\r
330 {$ifdef threadtimer}
\r
333 if settimer(hwndwcore,timerid_wcore,15,nil) = 0 then halt;
\r
337 while GetMessage(MsgRec, 0, 0, 0) do begin
\r
338 TranslateMessage(MsgRec);
\r
339 DispatchMessage(MsgRec);
\r
340 {if not peekmessage(msgrec,0,0,0,PM_NOREMOVE) then onidle}
\r
343 if hWndwcore <> 0 then begin
\r
344 DestroyWindow(hwndwcore);
\r
348 {$ifdef threadtimer}
\r
351 killtimer(hwndwcore,timerid_wcore);
\r
355 function ProcessMessage : Boolean;
\r
360 if PeekMessage(Msg, hwndwcore, 0, 0, PM_REMOVE) then begin
\r
362 DispatchMessage(Msg);
\r
366 procedure processmessages;
\r
368 while processmessage do;
\r