Solved

TTimer.OnTimer at Run Time

Posted on 1998-09-23
26
370 Views
Last Modified: 2010-04-06
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 := ??

0
Comment
Question by:Greedy
  • 10
  • 7
  • 5
  • +2
26 Comments
 
LVL 6

Expert Comment

by:Holger101497
ID: 1340676
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! :-))
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1340677
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
0
 
LVL 6

Expert Comment

by:Holger101497
ID: 1340678
err.... is that different from what I wrote? *?*
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340679
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;

0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340680
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.
0
 

Expert Comment

by:gdebiasa
ID: 1340681
Holger's response certainly looks correct to me.

Glen
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340682
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;


0
 
LVL 1

Author Comment

by:Greedy
ID: 1340683
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.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340684
I think you mean "GetLastTickCount".
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1340685
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
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340686
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.
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1340687
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
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340688
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.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 6

Expert Comment

by:Holger101497
ID: 1340689
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...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340690
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.
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340691
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
0
 
LVL 6

Accepted Solution

by:
Holger101497 earned 110 total points
ID: 1340692
Greedy: no offense - I'm not offended either - I'd just like to point out that the EE-guidelines clearly say that you shouldn't reject an answer unless it is unsatisfactory AND the expert who provided that answer cannot answer your additional questions regarding that answer.
Now if you take another look at your initial question, you'll agree that my answer was "the" correct answer and btw: Madshi was wrong telling you that it doesn't work. It's true that the procedure must me a method of an object, but "so what?"

I'm not overreacting (I'm not even mad), I'm just trying to explain: it happens quite often that an answer is rejected because it only answers the question 95% and somebody answers the remaining 5% and gets all the credit... This is not about points (like I really care about 300 points - can't buy a pizza for that. As you'll see in my profile, I also answer questions for 0-5 points), it's about fairness, that's all...

So much for that...

Now back to the question:
As I said, Madshi was (partly) wrong, it CAN be done the way you intended to do it and as a matter of fact, I think it's the better solution. Madshi was correct in pointing out that my last proposed solution uses the CPU 100%. Here's a solution that doesn't (~0% additional CPU time *g*). In Order to try it, you only need to put a button on a form and then replace the complete unit by this text:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen}
    mf:TForm;
    mt:TTimer;
  public
    { Public-Deklarationen}
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
VAR ti:longint;
begin
  (Sender AS TButton).Caption:='working';
  mf:=TForm.Create(Self);
  mf.Height:=100;
  mf.Width:=100;
  mf.Position := poScreenCenter;

  mt:=TTimer.Create(Self);
  mt.Interval:=5000;
  mt.OnTimer:=Timer1Timer;

  mf.Show;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if (mf<>NIL) THEN BEGIN mf.Close;mf.Destroy;mf:=NIL;END;
  if (mt<>NIL) AND (Sender=mt) THEN mt.Destroy; //one-way timer :-)
  Button1.Caption:='Done';
end;

end.

Some parts of it are not "perfectly clean", but it's the shortest way to make the point...
Another advantage of this solution is that you don't "really" waste 2.6 seconds in your program doing nothing - the program can continue doing something useful - unless you're Dogbert and WANT to waste time - in that case you'll probably also prefer the solution that uses 100% CPU because it makes your program look very busy *lol*

Let me know if you like this one better and ask additional questions about it if you want ;-))

Good luck!

P.S.: Please excuse the missing ":" in my variable=value *g* - I've been programming Java for the last couple of weeks :-))

P.P.S.: If you prefer a new component with a TimeToDisplay property, that wouldn' be much of a problem - just add the above code to the constructor... the problem is that a form cannot set pointers to NIL that refer to it. If the form destroys itself (don't even know if that's possible...), you'd end up with a couple of invalid references and some possibly unstable code...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340693
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.
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340694
Adjusted points to 100
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340695
Adjusted points to 101
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340696
Adjusted points to 102
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340697
This is kinda fun :)
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340698
Thanks alot that example works even better...I have it ejecting their CD every Random(1000) times now too. :)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1340699
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.
0
 
LVL 6

Expert Comment

by:Holger101497
ID: 1340700
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?)
0
 
LVL 1

Author Comment

by:Greedy
ID: 1340701
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.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now