Reliable way to change the cursor

L

Luke R

1) Me.Cursor = Cursors.WaitCursor
This works - except when you hover the mouse over a textbox or datagridview
control, it doesnt show the waitcursor.

2) Me.UseWaitCursor = True
This works if i set it off a button click. It does not work if i set it as
part of a process, which is extremely odd.
One would suspect that would be because im unsetting it somewhere in the
process, but to eliminate this possibility, i did a replace and changed them
to the Me.Cursor method and it worked fine. Of course, its not fine because
of the problems i described in #1.

Anyone else had this issue?
 
A

Armin Zingler

Luke R said:
1) Me.Cursor = Cursors.WaitCursor
This works - except when you hover the mouse over a textbox or
datagridview control, it doesnt show the waitcursor.

2) Me.UseWaitCursor = True
This works if i set it off a button click. It does not work if i set
it as part of a process, which is extremely odd.
One would suspect that would be because im unsetting it somewhere in
the process, but to eliminate this possibility, i did a replace and
changed them to the Me.Cursor method and it worked fine. Of course,
its not fine because of the problems i described in #1.

Anyone else had this issue?


Why not use Cursor.Current= Cursors.Waitcursor?


Armin
 
L

Luke R

At first i thought that didnt even work at all, and then i discovered that
it works if you dont touch the mouse... if you move the mouse one pixel in
any direction it goes back to the default cursor for the object the cursor
is over.
 
A

Armin Zingler

Luke R said:
At first i thought that didnt even work at all, and then i
discovered that it works if you dont touch the mouse... if you move
the mouse one pixel in any direction it goes back to the default
cursor for the object the cursor is over.

Works here. I assumed that the WaitCursor only makes sense if the thread is
busy. Then it should work. If it is not busy, or if you use
Application.Doevents, then it does not work, but then one shouldn't use the
WaitCursor (IMO).


Armin
 
L

Luke R

Am i confused or are you saying that you shouldnt use the WaitCursor if you
are using DoEvents?

It works if the ui thread is locked (i.e. running a process). But what about
if i want to write status messages to the status bar during the process? The
only way to make them display is by calling DoEvents.


This really pisses me off. Why cant things just work the way they say they
do. Especially with something as fundamental as the wait cursor.

UseWaitCursor: "Gets or sets a value indicating whether to use the wait
cursor for the current control and all child controls."

That is false. It simply doesnt work like that.
 
A

Armin Zingler

Luke R said:
Am i confused or are you saying that you shouldnt use the WaitCursor
if you are using DoEvents?

Yes. DoEvents means that the user can interact with the application, whereas
a WaitCursor indicates that he can not. Therefore I would not show a
WaitCursor if I called Doevents.
It works if the ui thread is locked (i.e. running a process). But
what about if i want to write status messages to the status bar
during the process? The only way to make them display is by calling
DoEvents.


This really pisses me off.

Me too! The reason for this is that since WinXP we don't have the choice
only to OUT-put something without accepting IN-put.

But to start from the beginning: Til Win98 (or ME) you could have a busy
application (without doevents) and still update the display. We had to call
the control's Refresh method after, for example, updating a label's text.
Worked well. The user must not operate the application in this time. At
least this was our (programmer's) choice.

Since WinXP there are ghost windows: (2nd paragraph)
http://msdn2.microsoft.com/en-us/library/ms644927.aspx

This means: If we want to update the display, it is not sufficient to call
the control's Refresh method because our window might have been replaced by
a ghost window. In order to update the display we are forced to keep the
application responsive, but this means the user can also interact with the
application although we don't want this and we only want to update the
display. This can cause a lot of work because the state working+responsive
must be handled. So, we have to use Doevents (which I never use), or put
the work in a separate thread.

One day I found a workaround for this problem without using
Doevents or another thread: In addition to calling the control's Refresh
method, call the PeekMessage API function during your
process. This prevents the window from being replaced by a ghost window.

Now that I've been googling the history of this topic, I came across a
probably helpful new feature:
http://support.microsoft.com/kb/817611

I've no clue yet what it is but I'll have a look at it. Maybe it helps you
too. Seems to be a problem fixed with SP2, but the Toolkit might be
interesting....


So, if you don't use Doevents anymore, you can use the Waitcursor. But, if
you want to use Doevents, don't show the Waitcursor.


Armin
 
L

Luke R

I haven't been writing code long enough to have known about the Refresh
thing, but that sounded alright.

I had a quick look at those pages, and it looks interesting ill have a read
(especially the first link), but just a couple of questions...

1) The ghost window appears after a certain number of seconds of
non-responsiveness. Does this mean the .Refresh solution for updating status
messages will still work for processes which do not run long enough for a
ghost window to be created?

2) Why do you never use DoEvents? Is it because you now use the PeekMessage
API instead, meaning no ghost window, which in turn means you can use the
..Refresh method to update your display?
So, if you don't use DoEvents anymore, you can use the WaitCursor. But, if
you want to use DoEvents, don't show the Waitcursor.

All I want, is a reliable way of making sure the cursor remains WaitCursor
over all controls on my form until I explicitly set it back to default. If I
don't use DoEvents, I cant write status messages but ill have a reliable
wait cursor. If I do use DoEvents, I can write status messages but my cursor
will change back prematurely. This sucks.

Thank you for your responses though.
 
A

Armin Zingler

Luke R said:
I haven't been writing code long enough to have known about the
Refresh thing, but that sounded alright.

I had a quick look at those pages, and it looks interesting ill have
a read (especially the first link), but just a couple of
questions...

1) The ghost window appears after a certain number of seconds of
non-responsiveness. Does this mean the .Refresh solution for
updating status messages will still work for processes which do not
run long enough for a ghost window to be created?

Right. But I would not rely on this because the time til the ghost window is
created can vary. (after "several" seconds)
2) Why do you never use DoEvents? Is it because you now use the
PeekMessage API instead, meaning no ghost window, which in turn
means you can use the .Refresh method to update your display?

Yes, but more often I use threads If I want the user to be able to keep
working with the application, be it only pressing a Cancel button.
All I want, is a reliable way of making sure the cursor remains
WaitCursor over all controls on my form until I explicitly set it
back to default. If I don't use DoEvents, I cant write status
messages but ill have a reliable wait cursor. If I do use DoEvents,
I can write status messages but my cursor will change back
prematurely. This sucks.


Why do you insist on the Waitcursor? You use Doevents, so the user does not
have to wait. So, I still see 3 ways:

- Doevents. No Waitcursor.
- Another thread. No Doevents. No Waitcursor.
- Peekmessage (work-around). Show Waitcursor.


Armin
 
L

Luke R

The reason the wait cursor is important is because my application
communicates with the database via a web service. Running operations on a
background process is not always practical, so when I do need to wait for a
web service call to return, I need the cursor to be the wait cursor.
Sometimes I run multiple web service calls in a row, meaning I need to
update status messages along the way. The only reason I use DoEvents is
because I need the status label to update...
 
A

Armin Zingler

Luke R said:
The reason the wait cursor is important is because my application
communicates with the database via a web service. Running operations
on a background process is not always practical, so when I do need
to wait for a web service call to return, I need the cursor to be
the wait cursor. Sometimes I run multiple web service calls in a
row, meaning I need to update status messages along the way. The
only reason I use DoEvents is because I need the status label to
update...


I understand, but the point is: You use Doevents, consequently the user can
use the Forms and Controls. Why do you /still/ want to show a Waitcursor
because the user does /not/ have to wait. If you wanna show that there is
something going on in the background, show it in a label or put an animated
gif on the Form. Though, how do you handle it that the user can even close
the Form while waiting for the web service?

Armin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top