Link to home
Start Free TrialLog in
Avatar of Greedy
Greedy

asked on

TTimer.OnTimer at Run Time

How do I assign a block of code to execute at run time for a dymanicly created TTimer's OnTimer event?

MyTimer := TTimer.Create(Self);
MyTimer.Interval := 1000;
MyTimer.OnTimer := ??

Avatar of Holger101497
Holger101497

You can directly assign any method to an "event handler" (OnXXX) as long as the method header matches the one that's needed for this type of event. You can easily find out which declaration you need by double-clicking the event in the object inspector (or by digging through the help files).

For the timer-control, it's
procedure something(parameter: TObject);


If you have a method
PROCEDURE MyForm.myTimerEvent(Sender:TObject);, you should be able to write

MyTimer.OnTimer=myTimerEvent;

Let me know if that helped and good luck! :-))
Here is how to do that!

private
      procedure MyTime(Sender : TObject);
{...}
procedure MyTime(Sender:TObject);\
begin
      //Stuff to do ontimer...
end;

//Where you create your timer
var
      Timer : TTimer;
begin
      Timer := TTimer.Create(self);
      Timer.OnTimer := MyTime;
      //other stuff
      Timer.Free;
end;

Regards,
Viktor Ivanov
err.... is that different from what I wrote? *?*
Avatar of Greedy

ASKER

Is there a way to do something like this

procedure TForm1.FormCreate(Sender: TObject);

  procedure MyTimerEvent(Sender: TObject);
  begin
    showmessage('good');
  end;

begin
  Timer1.OnTimer := MyTimerEvent;
end;

Greedy,

that doesn't work, since all event handler are defined as "blabla OF OBJECT". That means they must be defined in an object and cannot be local procedures, either.
If you don't like that object stuff, look at winAPI SetTimer/KillTimer. TTimer is just an encapsulation of these APIs.

Regards, Madshi.
Holger's response certainly looks correct to me.

Glen
Avatar of Greedy

ASKER

I Decided to do this instead - UpdateReviewStatus is instant...but I would like to know this...and yes I do know how to build multithreaded applications I just want somehting alittle less time consuming for me to write just to give a fancy UI...I rember once seeing a function that you can call and then call it again to find out how much time has passed since the last time you called it...now I want this new window to display for 2.6 sec...so I would like to call the GetElapsedTime routine after the show and before the UpdateReviewStatus and then after the UpdateReviewStatus I want to Sleep for 2600 - ElapsedTime...anyone rember how to do this?

          MyForm := TForm.CreateNew(Self);
          MyAnimate := TAnimate.Create(MyForm);
          MyAnimate.Parent := MyForm;
          MyAnimate.CommonAVI := aviCopyFile;
          MyAnimate.AutoSize := True;
          MyAnimate.Active := True;
          MyForm.Caption := 'Sending';
          MyForm.Height := MyAnimate.Height + 30;
          MyForm.Width := MyAnimate.Width + 10;
          MyForm.Position := poScreenCenter;
          MyForm.BorderIcons := [];
        // THIS IS WERE I START ELAPSED TIME
          MyForm.Show;
          UpdateReviewStatus(1);
          if (2600 - ValueFromElapsedTime) > 0 then
            Sleep(2600-ValueFromElapsedTime);
          MyAnimate.Enabled := False;
          MyForm.Close;
          MyForm.Release;


Avatar of Greedy

ASKER

His answer wasn't bad or even wrong...I'll probably ask him to answer it again...I just wanted to open it up to every body again because the question has kinda changed...I don't really like that a "proposed answer" sends it away from were most people look for questions to answer...after I get some input I will be able to determine what comments brought me to success.
I think you mean "GetLastTickCount".
To Holger:

Nope, my answer was was same as yours but I usually don't look at the comments and stuff, and just answer the question. Then I look at the comments, which is maybe a bad habit ;->

//Vik
Viktor,

that's really a bad habit. Because a lot of "experts" like me first write a comment (unless we're sure that it is really exactly the needed answer) and post a dummy answer only if we're asked to.
Perhaps you didn't see this in the past. But I remember poor John ("erajoj") being quite down/annoyed/depressed/whatever because you've just posted an answer that he wrote as a comment before you.
So you SHOULD read the comments before answering...

Nevertheless of course you're very welcome at EE.  :-)

Regards, Madshi.
The way you sound i have to feel guilty because of that, I usually skip comments when there are lots of them, and leave a comment. Then when I read the comments and see what;s going on I post an answer or rather stick to the comments.

btw- It would be the way you want it! No problem...

Regards,
Viktor Ivanov
Viktor,

didn't intend to make you feel guilty. Just wanted to encourage you reading the other's comments before writing a comment/an answer.

Regards, Madshi.
Viktor: I agree that that's bad habit, because those comments will in many cases be inappropriate - some questions seem to be clear but the author really meant something else or "modified/clarified" the questions in his comments - sometimes the question is almost answered and you start from the beginning!

Greedy: I don't think it's a good idea to reject a correct answer just because you want some additional input for a different question!
But anyhow: As far as I know, there is no useable "Sleep" method in Delphi. You'll need to do something like:

ti=GetTickCount;
WHILE (GetTickCount-ti<2600) DO ;

well, this is bad because it will block the application completely (no reaction to redraw prompts, mouse events etc.)
There are two methods that will allow Windows to handle messages. They are application.HandleMessages and Application.ProcessMessages. Take a look at the help file to decide which one suits you best. I recommend processMessages.

Your code would then look like this:
  MyForm.Show;
  UpdateReviewStatus(1);  //I have no idea what this does and if you need it
  ti=getTickCount; //gets the milliseconds since Windows was started
  WHILE (getTickCount-ti<2600) DO Application.ProcessMessages;
  MyAnimate.Enabled := False;
  MyForm.Close;

ti should be longint, getTickCount is defined in the unit "windows"

Let me know if that solves you (new) question...
Holger,

I agree with what you said...

Also I agree with your little source example. In my opinion ProcessMessages is the right choice. The disadvantage of it is that the cpu runs at 100% all the time. But HandleMessage (with 0% cpu) has another problem that is quite difficult: If there's no message to handle, HandleMessage hangs until a message comes. So the message box would stay open until you move the mouse into it or do something else that produces a message.
I'm using HandleMessage, but I had to work around this message problem...

Regards, Madshi.
Avatar of Greedy

ASKER

What the hell's up with you guys?  Holger I didn't reject your answer because it was correct and I had a diferent question. I regected your answer because it wasn't what would solve my problem...as you saw Madshi told me that I couldn't do it the way I wanted.  The GetTickCount is working...you see my users will sit there and stair at the little page go from one folder to the other, mesmorized by the rythmic motions.  Anyway, I like the fact that I'm waisting 2.6 seconds of their lives just so they get a fancy interface.  It also makes the program look like it's dooing much more than just setting one field in a database.  You (Holder) or Madshi can figure out who gets the valued (in your mind) points :) it'll be an A if your worried

Personaly I was figureing on someone telling me to create a new component derived from TForm with a TimeToDisplay property.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Holger101497
Holger101497

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hey Holger,

I didn't mean that YOUR answer doesn't work. I meant that Greedy's comment (exactly that before my first comment) doesn't work! I thought that was clear!!!

Regards, Madshi.
Avatar of Greedy

ASKER

Adjusted points to 100
Avatar of Greedy

ASKER

Adjusted points to 101
Avatar of Greedy

ASKER

Adjusted points to 102
Avatar of Greedy

ASKER

This is kinda fun :)
Avatar of Greedy

ASKER

Thanks alot that example works even better...I have it ejecting their CD every Random(1000) times now too. :)
Holger,

I'm not sure. Do you really think Greedy's comment (the one before my first comment) would have worked? I'm absolutely sure it would not because (1) it was not part of an object and (2) you can't use a local procedure as an event handler!

Regards, Madshi.
Madshi: Yep, you're correct. What I meant was that Greedy said he rejected the answer because you said it wouldn't work... well, whatever, this is getting more complicated than the question itself :-)

Greedy: *grin* - so you ARE dogbert, aren't you? (or at least you admire him). What does your program do anyway? (other than annoy its users?)
Avatar of Greedy

ASKER

It's a database program for tracking food stamp reviews for the government (I work for them) They have to send their reviews to technicians and then send them back...on a new record created by a reviewer I didn't have any "Do oyu really want to do this" messages comeing up so I wanted to show the user that something happened.  So I made the little form pop-up with a aviCopyFile TAnimate thingy...The reason I asked this question was based on a totaly wrong assumtion...I figured that the timer would not be able to destroy the TAnimate because it was alocated inside another procedure but then I remembered that if I destroy the form all the child components get destroyed too.
Now I'm trying to do this and have the new "wiggly window" respond to mouse clicks as the system would...each timer has an interval of 100. It isn't all that noticable at first but if they had to do data entry into that screen for 8 hrs it would make them so dizzy by the end of the day that the subliminal messages that are in my log out program would be even more effective :)  If you have any interest in helping out I'll post up another question.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Timer2: TTimer;
    Timer3: TTimer;
    Timer4: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure CreateParams( var Params: TCreateParams ); override;
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure Timer3Timer(Sender: TObject);
    procedure Timer4Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Top := 0;
  Left := 0;
  Width := GetSystemMetrics(SM_CXSCREEN);
  Height := GetSystemMetrics(SM_CYSCREEN);
  Timer1.Enabled := True;
  Timer2.Enabled := True;
  Timer3.Enabled := True;
  Timer4.Enabled := True;
end;

procedure TForm1.CreateParams( var Params: TCreateParams );
begin
  inherited CreateParams( Params );
  Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Form1.Left := Form1.Left + 1;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  Form1.Left := Form1.Left - 1;
end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin
  Form1.Top := Form1.Top + 1;
end;

procedure TForm1.Timer4Timer(Sender: TObject);
begin
  Form1.Top := Form1.Top - 1;
end;

end.