Wait for hourglass behaviour

Apr 29, 2011 at 7:18 AM

I had some trouble getting the WaitBasedOnHourGlass functionality working correctly in a WPF application on Windows XP, so I thought I'd post the solution for discussion here.

Firstly, we used a custom 'busy' cursor in the app - White uses the hardcoded IDs of the cursors from Windows so you need to use 

Mouse.OverrideCursor = Cursors.Wait

in your code before doing your long-running work.

 

Secondly, the white code to do this check works as follows:

 - Get the mouse cursor

 - If it's a wait cursor, move the mouse to the top left of the screen (0,0)

 - Keep performing the above steps until the timeout is reached (and then throw an exception) or until the cursor is not a wait cursor.

 

This causes an issue with apps where the cursor changes when you move it out of the application window - in this situation, White will move the mouse to (0,0) which will change the cursor back to the arrow, so White tries to continue when the application isn't ready.

Note that the mouse move is required to handle some special cases (eg if you select an item from a dropdown list, which leaves the mouse sitting over a text field, the cursor changes to an i-bar but windows reports it as a wait cursor).

 

To fix this, I've made the following changes to the white source:

In White.Core.InputDevices.Mouse.cs, add:

 

public virtual void MoveOut(Point windowLocation)
{
	Location = new Point(windowLocation.X + 10, windowLocation.Y + 10);
}

 

In White.Core.UIItems.Actions.Action.cs, make the following change to the Handle() method:

 

Clock.Matched matched = delegate(object obj)
{
    var cursor = (MouseCursor) obj;
    if (MouseCursor.WaitCursors.Contains(cursor))
    {
        Mouse.Instance.MoveOut();
        return false;
    }
    return true;
};

 

 

Clock.Matched matched = delegate(object obj)
{
    var cursor = (MouseCursor) obj;
    if (MouseCursor.WaitCursors.Contains(cursor))
    {
        Mouse.Instance.MoveOut(window.Location);
        return false;
    }
    return true;
};

 

What this does is make the mouse move to the menubar of the current window, so the wait cursor still hangs around until the application changes it back.