Prev: Compiled If...Then does not work like in ide!
Next: Runtime Error 429 "ActiveX Component can't create object" SOLVED
From: Karl E. Peterson on 30 Jun 2010 17:25 on 6/30/2010, Bob Butler supposed : > "Karl E. Peterson" <karl(a)exmvps.org> wrote... >> Brain freeze here, I guess. >> >> I need a simple one-shot timer (non form-based). I was thinking, just use >> SetTimer, then call KillTimer in the callback. But, KillTimer fails in the >> callback. LastDllError=0. > > works for me; You made me re-examine a few things, including where I was calling KillTimer. I had been syncing the callback in a BAS module, then redirecting to a class, and doing a few other things as well. Anyway, it turned out I was using the wrong handle in the first parameter. <groan> It's working now! :-) Thanks... Karl -- ..NET: It's About Trust! http://vfred.mvps.org
From: Karl E. Peterson on 30 Jun 2010 17:29 Nobody wrote : > You probably didn't use the return value of SetTimer, but I could be > mistaken. Here is an example to try. Post the code in Module1, and remove > Form1 from a new project. Appreciated! I did get it working, and you're *almost* right. I was using the wrong window handle. (I had to use an hWnd, even though I was using TimerProc, because of the complicated plumbing going on. I need to pass an ObjPtr to the callback using that second parameter.) Thanks... Karl -- ..NET: It's About Trust! http://vfred.mvps.org
From: Nobody on 30 Jun 2010 17:31 "Karl E. Peterson" <karl(a)exmvps.org> wrote in message news:i0gc5o$61i$1(a)news.eternal-september.org... > Yeah, but what I got going is already complex enough, that more flags > would just really make it all quite bizarre. And, I will want to reuse > the timer for a later one-shot. I could just leave it running, but > ideally it oughta be a very short interval on (at least) the first > callback. Another idea is to use PostMessage to post a custom message(like WM_APP+1) to Form1 to process the delayed task, but this requires a form or control and subclassing, but the delay is as small as it gets. I have done both methods in the past. Also, to keep the code neat, you may want to use Enum to tell the TimerProc what to do. Example: Public Enum enumTimerWhatToDo enumTimerDoTask1 enumTimerDoTask2 enumTimerDoTask3 End Enum Public TimerWhatToDo As enumTimerWhatToDo ' Returns True when successful, False when busy Public Function StartDelayedTask(ByVal WhatToDo As enumTimerWhatToDo) As Boolean If TimerID = 0 Then TimerWhatToDo = WhatToDo TimerID = SetTimer(0, 0, 10, AddressOf TimerProc) StartDelayedTask = True ' Success End If End Function Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, _ ByVal idEvent As Long, ByVal dwTime As Long) KillTimer 0, TimerID TimerID = 0 ' Done. End Sub
From: Karl E. Peterson on 30 Jun 2010 17:42 Nobody submitted this idea : > "Karl E. Peterson" <karl(a)exmvps.org> wrote... >> Yeah, but what I got going is already complex enough, that more flags would >> just really make it all quite bizarre. And, I will want to reuse the timer >> for a later one-shot. I could just leave it running, but ideally it oughta >> be a very short interval on (at least) the first callback. > > Another idea is to use PostMessage to post a custom message(like WM_APP+1) to > Form1 to process the delayed task, but this requires a form or control and > subclassing, but the delay is as small as it gets. Not a bad thought, actually. I'd had it myself. The hook is there, but not yet set at the time I need to go async. Rather, the hook is set in reaction to the callback. Hence the dilemma. > Also, to keep the code neat, you may want to use Enum to tell the TimerProc > what to do. Example: > > Public Enum enumTimerWhatToDo > enumTimerDoTask1 > enumTimerDoTask2 > enumTimerDoTask3 > End Enum > Public TimerWhatToDo As enumTimerWhatToDo > > ' Returns True when successful, False when busy > Public Function StartDelayedTask(ByVal WhatToDo As enumTimerWhatToDo) As > Boolean > If TimerID = 0 Then > TimerWhatToDo = WhatToDo > TimerID = SetTimer(0, 0, 10, AddressOf TimerProc) > StartDelayedTask = True ' Success > End If > End Function > > Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, _ > ByVal idEvent As Long, ByVal dwTime As Long) > > KillTimer 0, TimerID > TimerID = 0 ' Done. > End Sub Just to throw all that into a twist, the callback needs to be routed into a class. So I'm using the idEvent parameter to pass ObjPtr(Me) to the TimerProc, where it can be automagically reconstituted as the appropriate object and it's callback method can then be called. At any rate, I got it going now! :-) -- ..NET: It's About Trust! http://vfred.mvps.org
From: Bob Butler on 30 Jun 2010 18:07
"Karl E. Peterson" <karl(a)exmvps.org> wrote in message news:i0gcnp$a4v$1(a)news.eternal-september.org... > on 6/30/2010, Bob Butler supposed : >> "Karl E. Peterson" <karl(a)exmvps.org> wrote... >>> Brain freeze here, I guess. >>> >>> I need a simple one-shot timer (non form-based). I was thinking, just >>> use SetTimer, then call KillTimer in the callback. But, KillTimer fails >>> in the callback. LastDllError=0. >> >> works for me; > > You made me re-examine a few things, including where I was calling > KillTimer. I had been syncing the callback in a BAS module, then > redirecting to a class, and doing a few other things as well. Anyway, it > turned out I was using the wrong handle in the first parameter. <groan> > It's working now! :-) > > Thanks... Karl Me 1 Karl 49531 |