How can I make the cursor turn to the wait cursor?
Solution 1
You can use Cursor.Current
.
// Set cursor as hourglass
Cursor.Current = Cursors.WaitCursor;
// Execute your time-intensive hashing code here...
// Set cursor as default arrow
Cursor.Current = Cursors.Default;
However, if the hashing operation is really lengthy (MSDN defines this as more than 2-7 seconds), you should probably use a visual feedback indicator other than the cursor to notify the user of the progress. For a more in-depth set of guidelines, see this article.
Edit:
As @Am pointed out, you may need to call Application.DoEvents();
after Cursor.Current = Cursors.WaitCursor;
to ensure that the hourglass is actually displayed.
Solution 2
Actually,
Cursor.Current = Cursors.WaitCursor;
temporarily sets the Wait cursor, but doesn’t ensure that the Wait cursor shows until the end of your operation. Other programs or controls within your program can easily reset the cursor back to the default arrow as in fact happens when you move mouse while operation is still running.
A much better way to show the Wait cursor is to set the UseWaitCursor property in a form to true:
form.UseWaitCursor = true;
This will display wait cursor for all controls on the form until you set this property to false. If you want wait cursor to be shown on Application level you should use:
Application.UseWaitCursor = true;
Solution 3
Building on the previous, my preferred approach (since this is a frequently performed action) is to wrap the wait cursor code in an IDisposable helper class so it can be used with using() (one line of code), take optional parameters, run the code within, then clean up (restore cursor) afterwards.
public class CursorWait : IDisposable
{
public CursorWait(bool appStarting = false, bool applicationCursor = false)
{
// Wait
Cursor.Current = appStarting ? Cursors.AppStarting : Cursors.WaitCursor;
if (applicationCursor) Application.UseWaitCursor = true;
}
public void Dispose()
{
// Reset
Cursor.Current = Cursors.Default;
Application.UseWaitCursor = false;
}
}
Usage:
using (new CursorWait())
{
// Perform some code that shows cursor
}
Solution 4
It is easier to use UseWaitCursor at the Form or Window level. A typical use case can look like below:
private void button1_Click(object sender, EventArgs e)
{
try
{
this.Enabled = false;//optional, better target a panel or specific controls
this.UseWaitCursor = true;//from the Form/Window instance
Application.DoEvents();//messages pumped to update controls
//execute a lengthy blocking operation here,
//bla bla ....
}
finally
{
this.Enabled = true;//optional
this.UseWaitCursor = false;
}
}
For a better UI experience you should use Asynchrony from a different thread.
Solution 5
My approach would be to make all the calculations in a background worker.
Then change the cursor like this:
this.Cursor = Cursors.Wait;
And in the thread's finish event restore the cursor:
this.Cursor = Cursors.Default;
Note, this can also be done for specific controls, so the cursor will be the hourglass only when the mouse is above them.
Related videos on Youtube
Programatt
I am a programmer by day, and a tinkerer by night.
Updated on December 23, 2021Comments
-
Programatt over 2 years
How can I display the Wait/Busy Cursor (usually the hourglass) to the user to let them know the program is doing something?
-
Amirshk over 14 yearsthis won't necessary change the cursor - if the message loop won't be called during the time-intensive code. to enable it you need to add Application.DoEvents(); after the first cursor set.
-
Amirshk over 14 years@Malfist: good approach :), then all you need to do is place the restore in the end event, and your done.
-
TrueWill over 14 yearsYou probably want a try..finally block after setting Current, too (insuring that Current gets reset to Default).
-
Hans Rudel almost 12 yearsFYI, i couldnt get the above to work, but by changing it to this.cursor = cursors.waitcursor; it worked.
-
itsho almost 11 yearsGood to know. I was trying to do the same in WPF, and ended up with Cursor = Cursors.Wait and Cursor = Cursors.Arrow. But I couldn't find the Cursor under App
-
Vbp over 10 yearsHourglass was not displayed if I used Application.DoEvents() after Cursor.Current = Cursors.WaitCursor However, it did worked without Application.DoEvents() . Not sure Why
-
Bron Davies about 10 yearsRun your time intensive operations on a background Thread like this: ThreadStart ts = new ThreadStart(DoSomethingLong); Thread t = new Thread(ts); t.Start();
-
Chandra Eskay over 9 yearsCouldn't find UseWaitCursor under Application !
-
John Henckel almost 9 yearsThis should be the ACCEPTED answer. It is the only one that uses try-finally.
-
torno over 8 years
-
mhapps over 8 yearsHadn't seen that, but yes similar approach. He backs up the current cursor then restores it, which may be useful if you're doing heavy cursor changing.
-
Jack almost 8 yearshave my upvote, I was missing a try-finally in my implementation
-
Gianpiero over 7 yearsIt is better to use
Application.UseWaitCursor = true
andApplication.UseWaitCursor = false
-
Danny Mahoney over 7 years@GianpieroCaretti Why is that? Please explain.
-
Stewart over 6 yearsI found that, when setting form.UseWaitCursor = false at the end of the operation, it doesn't actually reset the cursor until you move or click the mouse. OTOH, form.Cursor doesn't have this problem. I couldn't get Cursor.Current to work at all.
-
AlirezaK over 6 years@GianpieroCaretti, in all solutions that came above, only your solution worked for me.
-
Eric Wood over 3 yearsI like your answer but I would suggest placing it in the context of a try / finally. I used Donut's accepted answer for years, but it does not work in code behind on a C# .NET Core 3.1 WPF application like your answer. With the ,NET Core, Microsoft has changed the interface and objects in regards to cursors.
-
Epic Speedy about 3 yearsDefinitely use this if you want to use the wait cursor. I tried
Cursor.Current
but it kept being reset instantly for some reason, this solution makes the waiting cursor persist until changed tofalse
. -
Fabio Pagano about 3 years@GianpieroCaretti The solution is ok, anyway a "doevents" (after the instruction) is needed also in this case.
-
Sid133 almost 3 yearsThis is the clean solution if we need a responsive UI as well as inform something is running.
-
Dan Randolph about 2 yearsBut what do you do if your 2 sec task is loading data into the control itself? (such as RichTextbox) I don't think using a background worker would help in this case, but I could be wrong.