PDA

Ver la Versión Completa : Timer en consola


b2k
20-07-2007, 08:14:22
Hola a todos, pues estoy creando una aplicacion en delphi, modo consola y necesito saber como usara algo similar al Timer de delphi pero en modo consola.

Saldudos

dec
20-07-2007, 11:48:49
Hola,

No sé hasta qué punto he entendido las indicaciones del maestro Seoane o tengo que darles un buen repaso, pero, esto es lo que hay...


program ConsoleTimer;

{$APPTYPE CONSOLE}

uses
Windows,
Messages,
SysUtils,
ExtCtrls;

type
TDummy = class(TObject)
procedure TimerInterval(Sender: TObject);
end;

var
Dummy: TDummy;
Timer: TTimer;
Terminar: Boolean;

{ TDummy }

procedure TDummy.TimerInterval(Sender: TObject);
begin
WriteLn(TimeToStr(Time)+' - Trigger TimeInterval');
end;

{ ConsoleTimer }

procedure ProcessMessages;
var
Msg: TMsg;
begin
while PeekMessage(Msg,0,0,0,PM_REMOVE) do
begin
if Msg.Message = WM_QUIT then
begin
Terminar:= TRUE;
break;
end else begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;

begin
Terminar := false;
Dummy := TDummy.Create();
Timer := TTimer.Create(nil);
Timer.OnTimer := Dummy.TimerInterval;
Timer.Interval := 2000;
try
while not Terminar do
begin
// Aqui haz lo que quieras

ProcessMessages();
if not Terminar then
Sleep(10);
end;
finally
Timer.Free();
Dummy.Free();
end;
end.



Revisa este hilo (http://www.clubdelphi.com/foros/showthread.php?t=43359) y este otro (http://www.clubdelphi.com/foros/showthread.php?t=43780).

seoane
20-07-2007, 11:52:33
Prueba con esto:

program Ejemplo;

{$APPTYPE CONSOLE}

uses Windows, Messages, SysUtils;

var
Terminar: Boolean;

procedure ProcessMessages;
var
Msg: TMsg;
begin
while PeekMessage(Msg,0,0,0,PM_REMOVE) do
begin
if Msg.Message = WM_QUIT then
begin
Terminar:= TRUE;
break;
end else
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;

function HandlerRoutine(dwCtrlType: DWORD): BOOL; stdcall;
begin
Result:= TRUE;
case dwCtrlType of
CTRL_C_EVENT:
Terminar:= TRUE;
CTRL_CLOSE_EVENT:
Terminar:= TRUE;
CTRL_LOGOFF_EVENT:
Terminar:= TRUE;
CTRL_SHUTDOWN_EVENT:
Terminar:= TRUE;
else
Result:= FALSE;
end;
end;

procedure TimerProc(Wnd: HWnd; Msg, TimerID, SysTime: Longint); stdcall;
begin
Windows.Beep(500,100);
end;

begin
Terminar:= FALSE;
if SetConsoleCtrlHandler(@HandlerRoutine,TRUE) then
begin
Writeln('Pulsa Ctrl+C para salir ...');
// Aqui iniciamos el Timer
SetTimer(0,0,1000,@TimerProc);
while not Terminar do
begin
// Aqui haz lo que quieras
ProcessMessages;
if not Terminar then
Sleep(10);
end;
end;
end.

seoane
20-07-2007, 11:53:33
:D Caramba, otra vez me pisan la respuesta.

dec
20-07-2007, 11:54:57
Hola,

No; son respuestas distintas, por lo que veo. :)

Una pregunta Seoane, ¿sería preciso usar el "SetConsoleCtrlHandler" en el código que yo he propuesto, o, como pienso, basta con usar "ProcessMessage"? No tengo muy claras estas cosas, la verdad, incluso mi código es un fusilamiento que he hecho al tuyo. :D :D

PD. Para qué nos vamos a engañar... yo probé sin el "ProcessMessages", y, como ví que no funcionaba el "timer"... me acordé de uno de tu Hilos (que enlazo arriba). :)

PD2. Me parece, en todo caso, que tu solución es más elegante. Tampoco nos vamos a engañar en esto. :)

seoane
20-07-2007, 12:03:11
Una pregunta Seoane, ¿sería preciso usar el "SetConsoleCtrlHandler" en el código que yo he propuesto, o, como pienso, basta con usar "ProcessMessage"? No tengo muy claras estas cosas, la verdad, incluso mi código es un fusilamiento que he hecho al tuyo. :D :D

No, el SetConsoleCtrlHandle lo utilizo como una forma de salir de bucle. Si para la aplicación hay pensada otra forma de salir, que no sea cerrarla a lo bestia :p , no hace falta.


PD. Para qué nos vamos a engañar... yo probé sin el "ProcessMessages", y, como ví que no funcionaba el "timer"... me acordé de uno de tu Hilos (que enlazo arriba). :)

Exactamente, sin bucle de mensajes no funcionan los timers.


PD2. Me parece, en todo caso, que tu solución es más elegante. Tampoco nos vamos a engañar en esto. :)

Es muy similar, ya que al final el TTimer llama a la API SetTimer

dec
20-07-2007, 12:06:05
Hola,


Es muy similar, ya que al final el TTimer llama a la API SetTimer


Hombre, no me digas, ahí me veo yo usando una clase "dummy", la clase "TTimer", métodos, constructores, destructores... y llegas tú y con un "SetTimer" haces lo que se pide. :D :D :D :D

tefots
20-07-2007, 15:26:29
yo lo haria de otra forma que evita estar llamando a processmessages , es algo que no me gusta y trato de evitar :(.

con un thread a modo de timer ,y que te notifique cuando se cumpla el timer (Creo que las jvcl tienen un timer basado en thread) . en el execute del thread mira si ha pasado x tiempo desde la ultima vez y si es asi , resetea la variable tiempo y lo notifica en un evento, en la aplicación consola debes de capturar ese evento que genera el thread.

yo lo que hago es crearme una clase (en la unit de la consola) que reciba los eventos (aunque tambien podria crearte solo el evento).
TConsoleEvents=Class
Private
Public
Procedure OnTemporizador();
End;

y luego creas un objeto de tipo ConsoleEvents en la apl. consola
y asignas el evento del thread , al evento de la consola
Thread.Ontimer=ConsoleEvents.Ontemporizador.
luego en el evento de consoleevents hago lo que deseo hacer. (en el 1º ejemplo el tdummy hace lo mismo que el consoleevents que yo digo)

Procedure TConsoleEvents.OnTemporizador;
Begin
Writeln('Temporizador ');
End;

salud2.