Mega Search
23.2 Million


Sign Up

Make a donation  
Re: TApplication.OnIdle Event only fires when a dialog box i  
News Group: embarcadero.public.cppbuilder.language.cpp

Curtis wrote:

> My application has drop down menus which open dialog boxes.  As soon
> as click on a menu, WM_ENTERIDLE is received but the OnIdle callback
> is not hit.

The OnIdle event is not related to the WM_ENTERIDLE message.

> When I open a dialog box, I no longer see the WM_ENTERIDLE messages
> but the OnIdle procedure is hit.

Exactly what kind of dialog box are you displaying?  This almost sounds like 
the dialog box is running a non-VCL message loop that is swallowing messages.

-- 
Remy Lebeau (TeamB)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 2:49 PM EST
From: Remy Lebeau (TeamB)
 
Re: TApplication.OnIdle Event only fires when a dialog box i  
News Group: embarcadero.public.cppbuilder.language.cpp
Curtis wrote:

> I did not not design this code and it used to work properly.
> Apparently, switching to a new version of C++ Builder has caused
> the change in behavior.

Based on your description, the only way the old code could have worked is 
if the dialog in question was doing something that (directly or indirectly) 
causing new messages to periodically arrive in the message queue, making 
the message loop toggle from idle to active to idle to active and so on, 
but the dialog in the new code is no longer doing that.  What kind of dialog 
is it?  What kind of controls does it use?  Maybe there was a UI change between 
versions that affects messaging.

> If I do nothing, no Windows messages are received.

Then the OnIdle event should be triggering almost immediately.

> If I do something (e.g. move the mouse), I get lots of appropriate
> messages.

Right.  And when all of those messages have been processed, and there are 
no more messages in the queue, the OnIdle event should trigger and the main 
message loop will block until the next message arrives.  Put a breakpoint 
inside of TApplication.HandleMessage() to verify that.

TApplication.Run() calls TApplication.HandleMessage() in a loop until the 
application is terminated.  TApplication.HandleMessage() calls TApplication.ProcessMessage(), 
which returns True or False to indicate whether a pending message was processed 
or not.  Once TApplication.ProcessMessage() returns False, TApplication.Idle() 
is called, which triggers the TApplication.OnIdle event handler, performs 
idle actions (TAction dispatching, TThread.Synchonize dispatching, etc) and 
finally calls WaitMessage() to wait for a new message to appear in the message 
queue, at which time flow goes back to TApplication.Run() and the loop repeats.

> When I stop, the messages stop but I never get the OnIdle event.

That should only be possible if the dialog (or anything else) is actively 
and regularly posting new messages to the message queue so TApplication never 
goes idle.

> I used the Windows SetTimer (which I believe TTimer is based on)

Correct.

> and everything works but it is too slow because the smallest period in 
10msec.

IIRC, the resolution of SetTimer() used to be like 50-60msec.  Maybe it is 
lower on newer OS versions?

> Can I set an interval or 1 or 2 milliseconds for TTimer?

You can set it, and Windows will accept it, but will not actually honor it 
because the timer resolution cannot go that low.  Multimedia timers have 
a better resolution than SetTimer(), but certainly not at 1ms intervals. 
 Windows simply does not run that fast.

> If I used CreateTimerQueueTimer(), it is fast enough but parts of my
> graph do not appear.  I know I am displaying it because if I minimize
> and re-open the window appears correctly.  If I use Refresh or Update,
> the display gets messed up entirely.

That suggests to me that either you are not drawing the graph correctly to 
being with, or more likely the timer callback is running in a different thread 
context than you are expecting.  Remember that UI access and UI drawing has 
to be done in the context of the main UI thread.  TTimer would run in the 
main thread, if created in the main thread.  CreateTimerQueueTimer() does 
not offer that same quarantee.

-- 
Remy Lebeau (TeamB)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 2:47 PM EST
From: Remy Lebeau (TeamB)
 
Re: TApplication.OnIdle Event only fires when a dialog box i  
News Group: embarcadero.public.cppbuilder.language.cpp
Another thing that seems odd to me.  My application has drop down menus which open dialog boxes.  As soon as click on a menu, WM_ENTERIDLE is received but the OnIdle callback is not hit.  When I open a dialog box, I no longer see the WM_ENTERIDLE messages but the OnIdle procedure is hit.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 2:41 PM EST
From: Curtis Lending
 
Re: TApplication.OnIdle Event only fires when a dialog box i  
News Group: embarcadero.public.cppbuilder.language.cpp
I did not not design this code and it used to work properly.  Apparently, switching to a new version of C++ Builder has caused the change in behavior.

> It is triggered whenever the message loop goes into an idle state when there 
> are no messages to process.  If you are NEVER getting the OnIdle event triggered, 
> that can only mean that the message queue is never idling, it always has 
> a pending message waiting when the message loop checks it.
If I do nothing, no Windows messages are received.  If I do something (e.g. move the mouse), I get lots of appropriate messages.  When I stop, the messages stop but I never get the OnIdle event.  

> If you want something done periodically, use a TTimer.
I have tried doing this with timers and it has failed for various reasons.  I used the Windows SetTimer (which I believe TTimer is based on) and everything works but it is too slow because the smallest period in 10msec.  Can I set an interval or 1 or 2 milliseconds for TTimer?  I could not find this in the documentation.

If I used CreateTimerQueueTimer(), it is fast enough but parts of my graph do not appear.  I know I am displaying it because if I minimize and re-open the window appears correctly.  If I use Refresh or Update, the display gets messed up entirely.

Curtis

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 1:35 PM EST
From: Curtis Lending
 
Re: TApplication.OnIdle Event only fires when a dialog box i  
News Group: embarcadero.public.cppbuilder.language.cpp
Curtis wrote:

> When a dialog box is open, the OnIdle handler gets called repeatedly
> (which is what I want).

It should not be.  The OnIdle event is triggered only when the main message 
loop checks the message queue for a pending message and does not see one. 
 The message loop then waits for a new message to arrive, processes it, checks 
for a new message, and if not found then triggers the OnIdle event and waits 
for a new message.  And so on.  The sole purpose of the OnIdle event is to 
let your code know when the message loop is entering an idling state when 
no messages are being processed.

If you want something done periodically, use a TTimer.

> If no dialog box is open, the handler is never called.

It is triggered whenever the message loop goes into an idle state when there 
are no messages to process.  If you are NEVER getting the OnIdle event triggered, 
that can only mean that the message queue is never idling, it always has 
a pending message waiting when the message loop checks it.

> I need the handler to be called regardless of the state of the program.

No, you don't.  That is not what the OnIdle event is meant for.  You are 
using the wrong solution to whatever problem you are trying to solve.

-- 
Remy Lebeau (TeamB)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 20-Jan-2015, at 12:18 PM EST
From: Remy Lebeau (TeamB)