Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

BeginWaitCursor() does not work effectively?

406 views
Skip to first unread message

frank

unread,
Aug 25, 2004, 10:51:18 AM8/25/04
to
Dear all,

I have a computationally intensive task in a program and used
BeginWaitCursor() and EndWaitCursor() pair to indicate that the
program is running (based on shape change of mouse pointer when moving
it on the top of the dialog). To avoid a dialog refresh problem, I
insert the MessageLoop() routine within the loop as shown below. By
doing so, however, the BeginWaitCursor() does not work anymore, at
least I could see it is working because the shape of mouse pointer
does not change any more if I move it on the top of the dialog.

Could you please advice and how can I avoid that? Thank you very much.

Frank


void CTest::OnOK()
{
UpdateData(TRUE);
BeginWaitCursor();

for (int i = 0; i < 50000; i++)
{
for (int j = 0; j < 50000; j++)
{
ProcessingJobA();
}
MessageLoop();
}

EndWaitCursor();
CDialog::OnOK();
}


void MessageLoop()
{
MSG Msg;

while (PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
{
if (!AfxGetApp()->PreTranslateMessage(&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}

Michael K. O'Neill

unread,
Aug 25, 2004, 11:44:33 AM8/25/04
to
BeginWaitCursor is guaranteed to maintain the "hourglass" shape only while
processing a single message. As soon as your app begins processing other
messages (which you do with MessageLoop) it will soon encounter a
WM_SETCURSOR message and will re-set the cursor back to normal.

You need to override WM_SETCURSOR. Read "A Persistent Wait Cursor" at
http://www.thecodeproject.com/dialog/persistentwaitcursor.asp

Incidentally, in your MessageLoop function, rather than mimicking the work
done by CWinThread::PumpMessage(), why not simply call it. In other words,

while ( ::PeekMessage( &iMsg, NULL, NULL, NULL, PM_NOREMOVE ) )
{
::AfxGetThread()->PumpMessage(); // pump messages until queue
is empty
}

Regards,
Mike

"frank" <ocean...@hotmail.com> wrote in message
news:c21b5fc6.0408...@posting.google.com...

Joseph M. Newcomer

unread,
Aug 25, 2004, 11:33:46 AM8/25/04
to
BeginWaitCursor does a SetCursor, and it assumes that no other SetCursor will be done
until you reset the cursor yourself. You then insert a call to the message pump, a poor
practice at best, and of course, the next WM_SETCURSOR message will get processed, and if
you don't handle it, it goes to DefWindowProc and of course it resets the cursor to the
window's default cursor. What you said by this is "I don't want whatever cursor is
currently displayed, reset it at your earliest opportunity". That's exactly what happens.

If you have some long computation that needs a live GUI, it is considered best practice to
perform it in a thread, rather than using the quaint PeekMessage method, which is a
concession 16-bit Windows made to support pseudo-multitasking. If you don't need a live
GUI, why are you doing PeekMessage? Given this is an OnOK handler, there is nothing can be
activated in the GUI until you complete (excluding background messages such as timer
messages, asynchronous network messages and the like. But if you need these responsive,
the correct approach is to use a thread). Note that the complete absence of a PeekMessage
does not limit your ability to do anything else to any other app while the long loop is
running (only in 16-bit Windows was this an issue, and that system is very, very, dead)

A better strategy would be to have your OnOK handler launch a thread, disable the dialog,
and simple return without calling the CDialog::OnOK handler. When the thread completes, it
notifies the GUI that it has finished, and at that point you call the OnOK handler to
terminate the dialog. And this is only if you have some reason to need a live message pump
(note that for many reasons having a pseudo-live message pump that is only activated by
polling in a long loop will either result in a vastly slower loop than required, just to
do the polling, or uncontrollable delays based on how infrequently the polling is done)

If you must use such antiquated methods, then you must do your own OnSetCursor handler,
and expicitly set the cursor to the wait cursor whenever some flag you set says that you
should display the wait cursor.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

frank

unread,
Aug 26, 2004, 7:43:18 AM8/26/04
to
Thank you, all.
0 new messages