Hourglass problem in a WinForm application
Asked Answered
S

6

15

In my program with a UI in WinForm. I set the cursor to a hourglass just before to launch a method in ThreadPool.

My code in UI thread to set the cursor looks like this :

Application.UseWaitCursor = true;

When the method is finished, i go back to the UI Thread to set the cursor to the normal case.

Application.UseWaitCursor = false;

My problem is the cursor stay to the Hourglass till I don't move the mouse. It's a little bit disturbing if the user wait on the end of the action without moving the mouse.

Anyone can help me ?

Jérôme

Sammer answered 28/6, 2010 at 7:17 Comment(0)
I
8

I am unable to reproduce this behaviour? It works fine for me.

One thing to note though if you use the Control.Cursor = Cursors.WaitCursor approach is that it usually used like so:

this.Cursor = Cursors.WaitCursor

Which would appear to work fine, however, this refers the form so if the user moves the mouse to a different control, e.g a TextBox then the mouse does not show the wait cursor.

This may cause confusion for the users. Or could cause some issues if the user continues to work on something else when the Application is busy doing other work.

Ide answered 28/6, 2010 at 7:35 Comment(1)
Finally I have changed the Cursor Property on the main Form instead of Application.UseWaitCursor and the behavior of my cursor is what I have expected. I have no idea what the problem is coming from...Sammer
B
17

Actually, there is one more way to do it, which I found somewhere after hours of researching this problem.

Unfortunately, it is a hack.

Below is a method that I wrote that handles the problem.

/// <summary>
    /// Call to toggle between the current cursor and the wait cursor
    /// </summary>
    /// <param name="control">The calling control.</param>
    /// <param name="toggleWaitCursorOn">True for wait cursor, false for default.</param>
    public static void UseWaitCursor(this Control control, bool toggleWaitCursorOn)
    {
        ...

        control.UseWaitCursor = toggleWaitCursorOn;

        // Because of a weird quirk in .NET, just setting UseWaitCursor to false does not work
        // until the cursor's position changes. The following line of code fakes that and 
        // effectively forces the cursor to switch back  from the wait cursor to default.
        if (!toggleWaitCursorOn)
            Cursor.Position = Cursor.Position;
    }
Burnett answered 5/1, 2011 at 22:37 Comment(2)
Thanks for the most useful tip. Actually Cursor.Position = Cursor.Position; was enough for me to add.Zipangu
You don't need a function for that. Simply write 2 lines: Application.UseWaitCursor = false; Cursor.Position = Cursor.Position;Colony
D
12

One more way:

Cursor.Current = Cursors.WaitCursor;

When finished, just change the cursor back:

Cursor.Current = Cursors.Default;
Dogcart answered 28/6, 2010 at 9:45 Comment(2)
I am informed that this is the wrong approach: csharp411.com/the-proper-way-to-show-the-wait-cursorBenitobenjamen
This method worked for me over the Application.UseWaitCursor method. I need to make a wait cursor when I click a button on a tab control. When I set Application.UseWaitCursor or this.UseWaitCursor, the tab.UseWaitCursor property also gets set to true. Then when I do Application.UseWaitCursor = false; the tab.UseWaitCursor remains true! When I get to that tab later, it keeps showing a wait cursor. Not sure why the tab.UseWaitCursor gets set and not cleared, but when I use the Cursor object it seems to work correctly.Resolved
I
8

I am unable to reproduce this behaviour? It works fine for me.

One thing to note though if you use the Control.Cursor = Cursors.WaitCursor approach is that it usually used like so:

this.Cursor = Cursors.WaitCursor

Which would appear to work fine, however, this refers the form so if the user moves the mouse to a different control, e.g a TextBox then the mouse does not show the wait cursor.

This may cause confusion for the users. Or could cause some issues if the user continues to work on something else when the Application is busy doing other work.

Ide answered 28/6, 2010 at 7:35 Comment(1)
Finally I have changed the Cursor Property on the main Form instead of Application.UseWaitCursor and the behavior of my cursor is what I have expected. I have no idea what the problem is coming from...Sammer
T
2

My solution....

public class SetMouseCursor
{
    public static void Wait()
    {
        Application.UseWaitCursor = true;
        Cursor.Current = Cursors.WaitCursor;
    }

    public static void Default()
    {
        Application.UseWaitCursor = false;
        Cursor.Current = Cursors.Default;
    }
}
Telamon answered 16/2, 2021 at 21:10 Comment(0)
J
0

Set the cursor manually. That's what I do.

Joshia answered 28/6, 2010 at 7:20 Comment(3)
control.Cursor = Cursors.BusyJoshia
I think it should be control.Cursor = Cursors.WaitCursorIde
@barry: thanks, I couldn't remember, but the idea is still the same :)Joshia
U
0

A reusable solution is to use a little disposable helper class.

public sealed class WaitCursor : IDisposable
{
    public WaitCursor()
    {
        Application.UseWaitCursor = true;
        Cursor.Current = Cursors.WaitCursor;
    }

    public void Dispose()
    {
        Application.UseWaitCursor = false;
        Cursor.Current = Cursors.Default;
    }
}

With C#'s using var usage becomes very easy (example):

using var waitCursor = new WaitCursor();

using var dbContext = new MyDbContext();
await dbContext.Adresses.LoadAsync();
var adresses = _dbContext.Adressen.Local.ToBindingList();
gridControl1.DataSource = adresses;

The default cursor will be restored automatically at the end of the current code block. No need for an explicit try-finally to make the code safe.

User answered 5/11, 2023 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.