4 lcore compatible interface for windows
\r
11 //note: events after release are normal and are the apps responsibility to deal with safely
\r
15 classes,windows,mmsystem;
\r
20 tlcomponent = class(tcomponent)
\r
24 destructor destroy; override;
\r
27 tltimer=class(tlcomponent)
\r
30 procedure setenabled(newvalue : boolean);
\r
32 ontimer:tnotifyevent;
\r
33 initialevent:boolean;
\r
34 initialdone:boolean;
\r
37 interval:integer; {milliseconds, default 1000}
\r
39 property enabled:boolean read fenabled write setenabled;
\r
40 constructor create(aowner:tcomponent);override;
\r
41 destructor destroy;override;
\r
44 ttaskevent=procedure(wparam,lparam:longint) of object;
\r
46 tltask=class(tobject)
\r
48 handler : ttaskevent;
\r
53 constructor create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
56 procedure messageloop;
\r
57 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
58 procedure disconnecttasks(aobj:tobject);
\r
59 procedure exitmessageloop;
\r
60 procedure processmessages;
\r
61 procedure wcoreinit;
\r
64 onshutdown:procedure(s:ansistring);
\r
77 WINMSG_TASK=WM_USER;
\r
82 timesubtract:integer;
\r
83 firsttask,lasttask,currenttask:tltask;
\r
85 procedure tlcomponent.release;
\r
90 destructor tlcomponent.destroy;
\r
92 disconnecttasks(self);
\r
96 {------------------------------------------------------------------------------}
\r
98 procedure tltimer.setenabled(newvalue : boolean);
\r
100 fenabled := newvalue;
\r
102 initialdone := false;
\r
105 constructor tltimer.create;
\r
107 inherited create(AOwner);
\r
108 nexttimer := firsttimer;
\r
111 if assigned(nexttimer) then nexttimer.prevtimer := self;
\r
112 firsttimer := self;
\r
119 destructor tltimer.destroy;
\r
121 if prevtimer <> nil then begin
\r
122 prevtimer.nexttimer := nexttimer;
\r
124 firsttimer := nexttimer;
\r
126 if nexttimer <> nil then begin
\r
127 nexttimer.prevtimer := prevtimer;
\r
132 {------------------------------------------------------------------------------}
\r
134 function wcore_timehandler:integer;
\r
139 currenttimer,temptimer:tltimer;
\r
141 if not assigned(firsttimer) then begin
\r
146 tvnow := timegettime;
\r
147 if (tvnow and ((-1) shl rollover_bits)) <> timesubtract then begin
\r
148 currenttimer := firsttimer;
\r
149 while assigned(currenttimer) do begin
\r
150 dec(currenttimer.nextts,(1 shl rollover_bits));
\r
151 currenttimer := currenttimer.nexttimer;
\r
153 timesubtract := tvnow and ((-1) shl rollover_bits);
\r
155 tvnow := tvnow and ((1 shl rollover_bits)-1);
\r
157 currenttimer := firsttimer;
\r
158 while assigned(currenttimer) do begin
\r
159 if tvnow >= currenttimer.nextts then begin
\r
160 if assigned(currenttimer.ontimer) then begin
\r
161 if currenttimer.enabled then begin
\r
162 if currenttimer.initialevent or currenttimer.initialdone then currenttimer.ontimer(currenttimer);
\r
163 currenttimer.initialdone := true;
\r
166 currenttimer.nextts := tvnow+currenttimer.interval;
\r
168 temptimer := currenttimer;
\r
169 currenttimer := currenttimer.nexttimer;
\r
170 if temptimer.released then temptimer.free;
\r
174 currenttimer := firsttimer;
\r
175 while assigned(currenttimer) do begin
\r
176 if currenttimer.nextts < tv then tv := currenttimer.nextts;
\r
177 currenttimer := currenttimer.nexttimer;
\r
179 result := tv-tvnow;
\r
180 if result < 15 then result := 15;
\r
183 {------------------------------------------------------------------------------}
\r
185 constructor tltask.create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
188 handler := ahandler;
\r
192 {nexttask := firsttask;
\r
193 firsttask := self;}
\r
194 if assigned(lasttask) then begin
\r
195 lasttask.nexttask := self;
\r
198 postmessage(hwndwcore,WINMSG_TASK,0,0);
\r
201 //ahandler(wparam,lparam);
\r
204 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
206 tltask.create(ahandler,aobj,awparam,alparam);
\r
209 procedure disconnecttasks(aobj:tobject);
\r
211 currenttasklocal : tltask ;
\r
214 for counter := 0 to 1 do begin
\r
215 if counter = 0 then begin
\r
216 currenttasklocal := firsttask; //main list of tasks
\r
218 currenttasklocal := currenttask; //needed in case called from a task
\r
220 // note i don't bother to destroy the links here as that will happen when
\r
221 // the list of tasks is processed anyway
\r
222 while assigned(currenttasklocal) do begin
\r
223 if currenttasklocal.obj = aobj then begin
\r
224 currenttasklocal.obj := nil;
\r
225 currenttasklocal.handler := nil;
\r
227 currenttasklocal := currenttasklocal.nexttask;
\r
236 if firsttask = nil then exit;
\r
238 currenttask := firsttask;
\r
241 while assigned(currenttask) do begin
\r
242 if assigned(currenttask.handler) then currenttask.handler(currenttask.wparam,currenttask.lparam);
\r
243 temptask := currenttask;
\r
244 currenttask := currenttask.nexttask;
\r
247 currenttask := nil;
\r
250 {------------------------------------------------------------------------------}
\r
252 procedure exitmessageloop;
\r
254 postmessage(hwndwcore,WM_QUIT,0,0);
\r
257 {$ifdef threadtimer}
\r
260 const timerid_wcore=$1000;
\r
263 function MyWindowProc(
\r
267 alParam : LPARAM): Integer; stdcall;
\r
272 Result := 0; // This means we handled the message
\r
274 {MsgRec.hwnd := ahWnd;}
\r
275 MsgRec.wParam := awParam;
\r
276 MsgRec.lParam := alParam;
\r
280 {$ifndef threadtimer}
\r
282 if msgrec.wparam = timerid_wcore then begin
\r
283 a := wcore_timehandler;
\r
284 killtimer(hwndwcore,timerid_wcore);
\r
285 settimer(hwndwcore,timerid_wcore,a,nil);
\r
290 {WINMSG_TASK:dotasks;}
\r
299 Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
\r
305 MyWindowClass : TWndClass = (style : 0;
\r
306 lpfnWndProc : @MyWindowProc;
\r
313 lpszMenuName : nil;
\r
314 lpszClassName : 'wcoreClass');
\r
316 procedure wcoreinit;
\r
318 if Windows.RegisterClass(MyWindowClass) = 0 then halt;
\r
319 //writeln('about to create wcore handle, hinstance=',hinstance);
\r
320 hwndwcore := CreateWindowEx(WS_EX_TOOLWINDOW,
\r
321 MyWindowClass.lpszClassName,
\r
322 '', { Window name }
\r
323 WS_POPUP, { Window Style }
\r
325 0, 0, { Width, Height }
\r
328 HInstance, { hInstance }
\r
329 nil); { CreateParam }
\r
331 if hwndwcore = 0 then halt;
\r
333 {$ifdef threadtimer}
\r
336 if settimer(hwndwcore,timerid_wcore,15,nil) = 0 then halt;
\r
342 procedure messageloop;
\r
348 while GetMessage(MsgRec, 0, 0, 0) do begin
\r
349 TranslateMessage(MsgRec);
\r
350 DispatchMessage(MsgRec);
\r
351 {if not peekmessage(msgrec,0,0,0,PM_NOREMOVE) then onidle}
\r
354 if hWndwcore <> 0 then begin
\r
355 DestroyWindow(hwndwcore);
\r
359 {$ifdef threadtimer}
\r
362 killtimer(hwndwcore,timerid_wcore);
\r
366 function ProcessMessage : Boolean;
\r
371 if PeekMessage(MsgRec, 0, 0, 0, PM_REMOVE) then begin
\r
373 TranslateMessage(MsgRec);
\r
374 DispatchMessage(MsgRec);
\r
378 procedure processmessages;
\r
380 while processmessage do;
\r