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; {miliseconds, 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
63 onshutdown:procedure(s:ansistring);
\r
76 WINMSG_TASK=WM_USER;
\r
81 timesubstract:integer;
\r
82 firsttask,lasttask,currenttask:tltask;
\r
84 procedure tlcomponent.release;
\r
89 destructor tlcomponent.destroy;
\r
91 disconnecttasks(self);
\r
95 {------------------------------------------------------------------------------}
\r
97 procedure tltimer.setenabled(newvalue : boolean);
\r
99 fenabled := newvalue;
\r
101 initialdone := false;
\r
104 constructor tltimer.create;
\r
106 inherited create(AOwner);
\r
107 nexttimer := firsttimer;
\r
110 if assigned(nexttimer) then nexttimer.prevtimer := self;
\r
111 firsttimer := self;
\r
118 destructor tltimer.destroy;
\r
120 if prevtimer <> nil then begin
\r
121 prevtimer.nexttimer := nexttimer;
\r
123 firsttimer := nexttimer;
\r
125 if nexttimer <> nil then begin
\r
126 nexttimer.prevtimer := prevtimer;
\r
131 {------------------------------------------------------------------------------}
\r
133 function wcore_timehandler:integer;
\r
138 currenttimer,temptimer:tltimer;
\r
140 if not assigned(firsttimer) then begin
\r
145 tvnow := timegettime;
\r
146 if (tvnow and ((-1) shl rollover_bits)) <> timesubstract then begin
\r
147 currenttimer := firsttimer;
\r
148 while assigned(currenttimer) do begin
\r
149 dec(currenttimer.nextts,(1 shl rollover_bits));
\r
150 currenttimer := currenttimer.nexttimer;
\r
152 timesubstract := tvnow and ((-1) shl rollover_bits);
\r
154 tvnow := tvnow and ((1 shl rollover_bits)-1);
\r
156 currenttimer := firsttimer;
\r
157 while assigned(currenttimer) do begin
\r
158 if tvnow >= currenttimer.nextts then begin
\r
159 if assigned(currenttimer.ontimer) then begin
\r
160 if currenttimer.enabled then begin
\r
161 if currenttimer.initialevent or currenttimer.initialdone then currenttimer.ontimer(currenttimer);
\r
162 currenttimer.initialdone := true;
\r
165 currenttimer.nextts := tvnow+currenttimer.interval;
\r
167 temptimer := currenttimer;
\r
168 currenttimer := currenttimer.nexttimer;
\r
169 if temptimer.released then temptimer.free;
\r
173 currenttimer := firsttimer;
\r
174 while assigned(currenttimer) do begin
\r
175 if currenttimer.nextts < tv then tv := currenttimer.nextts;
\r
176 currenttimer := currenttimer.nexttimer;
\r
178 result := tv-tvnow;
\r
179 if result < 15 then result := 15;
\r
182 {------------------------------------------------------------------------------}
\r
184 constructor tltask.create(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
187 handler := ahandler;
\r
191 {nexttask := firsttask;
\r
192 firsttask := self;}
\r
193 if assigned(lasttask) then begin
\r
194 lasttask.nexttask := self;
\r
197 postmessage(hwndwcore,WINMSG_TASK,0,0);
\r
200 //ahandler(wparam,lparam);
\r
203 procedure addtask(ahandler:ttaskevent;aobj:tobject;awparam,alparam:longint);
\r
205 tltask.create(ahandler,aobj,awparam,alparam);
\r
208 procedure disconnecttasks(aobj:tobject);
\r
210 currenttasklocal : tltask ;
\r
213 for counter := 0 to 1 do begin
\r
214 if counter = 0 then begin
\r
215 currenttasklocal := firsttask; //main list of tasks
\r
217 currenttasklocal := currenttask; //needed in case called from a task
\r
219 // note i don't bother to sestroy the links here as that will happen when
\r
220 // the list of tasks is processed anyway
\r
221 while assigned(currenttasklocal) do begin
\r
222 if currenttasklocal.obj = aobj then begin
\r
223 currenttasklocal.obj := nil;
\r
224 currenttasklocal.handler := nil;
\r
226 currenttasklocal := currenttasklocal.nexttask;
\r
235 if firsttask = nil then exit;
\r
237 currenttask := firsttask;
\r
240 while assigned(currenttask) do begin
\r
241 if assigned(currenttask.handler) then currenttask.handler(currenttask.wparam,currenttask.lparam);
\r
242 temptask := currenttask;
\r
243 currenttask := currenttask.nexttask;
\r
246 currenttask := nil;
\r
249 {------------------------------------------------------------------------------}
\r
251 procedure exitmessageloop;
\r
253 postmessage(hwndwcore,WM_QUIT,0,0);
\r
256 {$ifdef threadtimer}
\r
259 const timerid_wcore=$1000;
\r
262 function MyWindowProc(
\r
266 alParam : LPARAM): Integer; stdcall;
\r
271 Result := 0; // This means we handled the message
\r
273 {MsgRec.hwnd := ahWnd;}
\r
274 MsgRec.wParam := awParam;
\r
275 MsgRec.lParam := alParam;
\r
279 {$ifndef threadtimer}
\r
281 if msgrec.wparam = timerid_wcore then begin
\r
282 a := wcore_timehandler;
\r
283 killtimer(hwndwcore,timerid_wcore);
\r
284 settimer(hwndwcore,timerid_wcore,a,nil);
\r
289 {WINMSG_TASK:dotasks;}
\r
298 Result := DefWindowProc(ahWnd, auMsg, awParam, alParam)
\r
304 MyWindowClass : TWndClass = (style : 0;
\r
305 lpfnWndProc : @MyWindowProc;
\r
312 lpszMenuName : nil;
\r
313 lpszClassName : 'wcoreClass');
\r
315 procedure messageloop;
\r
320 if Windows.RegisterClass(MyWindowClass) = 0 then halt;
\r
321 //writeln('about to create wcore handle, hinstance=',hinstance);
\r
322 hwndwcore := CreateWindowEx(WS_EX_TOOLWINDOW,
\r
323 MyWindowClass.lpszClassName,
\r
324 '', { Window name }
\r
325 WS_POPUP, { Window Style }
\r
327 0, 0, { Width, Height }
\r
330 HInstance, { hInstance }
\r
331 nil); { CreateParam }
\r
333 if hwndwcore = 0 then halt;
\r
335 {$ifdef threadtimer}
\r
338 if settimer(hwndwcore,timerid_wcore,15,nil) = 0 then halt;
\r
342 while GetMessage(MsgRec, 0, 0, 0) do begin
\r
343 TranslateMessage(MsgRec);
\r
344 DispatchMessage(MsgRec);
\r
345 {if not peekmessage(msgrec,0,0,0,PM_NOREMOVE) then onidle}
\r
348 if hWndwcore <> 0 then begin
\r
349 DestroyWindow(hwndwcore);
\r
353 {$ifdef threadtimer}
\r
356 killtimer(hwndwcore,timerid_wcore);
\r
360 function ProcessMessage : Boolean;
\r
365 if PeekMessage(MsgRec, 0, 0, 0, PM_REMOVE) then begin
\r
367 TranslateMessage(MsgRec);
\r
368 DispatchMessage(MsgRec);
\r
372 procedure processmessages;
\r
374 while processmessage do;
\r