Click here to Skip to main content
13,448,385 members (57,340 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


1 bookmarked
Posted 27 Dec 2010

Hourglass Mouse Cursor Always Changes Back to its Original Image. How?

, 5 Jan 2011
Rate this:
Please Sign up or sign in to vote.
This topic is also covered by the RAII topic as described in RAII (Resource Acquisition Is Initialization) C# Helper Classes[^].Applying the RAII pattern results in more expressive code:using (new RAIIGuard(()=>owner.Cursor, c=>owner.Cursor = c)){ owner.Cursor =...
This topic is also covered by the RAII topic as described in RAII (Resource Acquisition Is Initialization) C# Helper Classes[^].

Applying the RAII pattern results in more expressive code:
using (new RAIIGuard<Cursor>(()=>owner.Cursor, c=>owner.Cursor = c))
   owner.Cursor = Cursor.WaitCursor;

If you have this situation more often, then you want to create your own class as mentioned in your code, e.g.:
public class CursorLifeTime: RAIIGuard<Cusror>
   CursorLifeTime(Control owner) : base(()=>owner.Cursor, c=>owner.Cursor=c) {}

using (new CursorLifeTime(owner))
    owner.Cursor = Cursor.WaitCursor;

(edited to address issues rised in the comments below):

There is a subtle difference to your code: as shown here above, I would recommend to build your code on existing building bocks (e.g. RAII pattern) and only assign the tasks of storing and restoring to the RAII class/code. Setting the Wait cursor is part of the normal function, not part of the RAII.

The sample RAII code is:
// used for symmetric actions that must pass
// over an object from init to cleanup and that
// need to provide the item to the "using" body
public class RAIIGuard<T>: IDisposable
    private Action<T> Cleanup { get; set; }
    public T Item { get; private set; }
    public RAIIGuard(Func<T> init, Action<T> cleanup)
        Cleanup = cleanup;
        Item = (init != null) ? init() : default(T);
    public void Dispose() { if (Cleanup != null) Cleanup(Item); }

And the WaitCursorLifeTime class variant that also sets the cursor is:
public class WaitCursorLifeTime: RAIIGuard<Cusror>
   WaitCursorLifeTime(Control owner) : base(()=>owner.Cursor, c=>owner.Cursor=c)
   { owner.Cursor = Cursors.WaitCursor; }

using (new WaitCursorLifeTime(owner))


I usually create, based on that CursorLifeTime class a class that triggers a timer and only after a certain time, turns that Wait Cursor on (and off if the block is left). The users' perception is more positive, if the cursor does not flicker too much with each action that lasts a very tiny moment - only the actions that last more than say 500 ms should turn on the Wait cursor.




This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Andreas Gieriet
Founder eXternSoft GmbH
Switzerland Switzerland
I feel comfortable on a variety of systems (UNIX, Windows, cross-compiled embedded systems, etc.) in a variety of languages, environments, and tools.
I have a particular affinity to computer language analysis, testing, as well as quality management.

More information about what I do for a living can be found at my LinkedIn Profile and on my company's web page (German only).

You may also be interested in...


Comments and Discussions

GeneralAll right, thank you for your alternative answer. I accepted... Pin
SAKryukov21-Jan-11 12:40
mvpSAKryukov21-Jan-11 12:40 
GeneralReason for my vote of 4 Please make constructor WaitCursorLi... Pin
SAKryukov21-Jan-11 12:36
mvpSAKryukov21-Jan-11 12:36 
GeneralReason for my vote of 5 Very good systematic approach, perfe... Pin
SAKryukov21-Jan-11 12:34
mvpSAKryukov21-Jan-11 12:34 
GeneralI've improved the alternative to address your questions abov... Pin
Andreas Gieriet28-Dec-10 13:09
memberAndreas Gieriet28-Dec-10 13:09 
I've improved the alternative to address your questions above (the "previous" handling is managed by the RAII guard class - that's its only purpose).

BTW: RAII is not "my idea" Wink | ;-) . It's a common pattern in C++, and I use it in the described way in C# whenever I have a pair of actions to be executed regardless of if normal or exception flow leaves the scope. I have several places where such pairs exist: CursorLifeTime, network connections, creating formally correct structured files, etc.

Regarding delays and perception of users of what is "acceptable" without feedback: there are data available (that I do not have right now at hand), but IIRC, the following "delays" are considered "ok":
- less than 0.3 sec delay for keyboard/remote-control/mouse/... feedback
- less than 3 sec delay for button/link/... press without feedback
- less than 30 sec processing time for any common daily action
Please don't cite me on these values - go and search for the numbers in the internet - there are usability studies that give quite useful numbers on that.

The discussion about style and re-inventing the wheel probably does not bring us anywhere... Wink | ;-)
GeneralAndreas, thanks a lot for your reply. I did not get enough t... Pin
SAKryukov28-Dec-10 8:20
mvpSAKryukov28-Dec-10 8:20 
GeneralMy first attempt would be, since the code for both implement... Pin
Andreas Gieriet27-Dec-10 23:00
memberAndreas Gieriet27-Dec-10 23:00 
GeneralMy first attempt would be, since the code for both implement... Pin
Andreas Gieriet27-Dec-10 22:39
memberAndreas Gieriet27-Dec-10 22:39 
GeneralThank you for your alternative. It looks quite good, but to ... Pin
SAKryukov27-Dec-10 19:28
mvpSAKryukov27-Dec-10 19:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03-2016 | 2.8.180318.3 | Last Updated 5 Jan 2011
Article Copyright 2010 by Andreas Gieriet
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid