Click here to Skip to main content
15,887,027 members
Articles / Programming Languages / C#
Alternative
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.40/5 (4 votes)
5 Jan 2011CPOL1 min read 18.7K   1   8
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:
C#
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.:
C#
public class CursorLifeTime: RAIIGuard<Cusror>
{
   CursorLifeTime(Control owner) : base(()=>owner.Cursor, c=>owner.Cursor=c) {}
}


Usage:
C#
using (new CursorLifeTime(owner))
{
    owner.Cursor = Cursor.WaitCursor;
    //...
}


<Begin-Edit>
(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:
C#
// 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:
C#
public class WaitCursorLifeTime: RAIIGuard<Cusror>
{
   WaitCursorLifeTime(Control owner) : base(()=>owner.Cursor, c=>owner.Cursor=c)
   { owner.Cursor = Cursors.WaitCursor; }
}

Usage:
C#
using (new WaitCursorLifeTime(owner))
{
    //...
}


<End-Edit>

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.

Cheers

Andi

License

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


Written By
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).

Comments and Discussions

 
GeneralAll right, thank you for your alternative answer. I accepted... Pin
Sergey Alexandrovich Kryukov21-Jan-11 12:40
mvaSergey Alexandrovich Kryukov21-Jan-11 12:40 
GeneralReason for my vote of 4 Please make constructor WaitCursorLi... Pin
Sergey Alexandrovich Kryukov21-Jan-11 12:36
mvaSergey Alexandrovich Kryukov21-Jan-11 12:36 
GeneralReason for my vote of 5 Very good systematic approach, perfe... Pin
Sergey Alexandrovich Kryukov21-Jan-11 12:34
mvaSergey Alexandrovich Kryukov21-Jan-11 12:34 
GeneralI've improved the alternative to address your questions abov... Pin
Andreas Gieriet28-Dec-10 13:09
professionalAndreas Gieriet28-Dec-10 13:09 
GeneralAndreas, thanks a lot for your reply. I did not get enough t... Pin
Sergey Alexandrovich Kryukov28-Dec-10 8:20
mvaSergey Alexandrovich Kryukov28-Dec-10 8:20 
Andreas, thanks a lot for your reply. I did not get enough time for that -- just yet (I really want to complete last article to complete the series), but, for now, I have a couple of questions.

In your code above, you did not demonstrate a piece of code where "Owner.Cursor = Previous" is done, and not the piece where "Previous" is obtained. You should agree that, to reach the goal, these pieces should be somewhere not matter how you do it. So, for now, I simply don't understand. Second thing: in your usage sample you write "owner.Cursor = Cursor.Wait". Should be written in every point of usage? If so, it would defeat one of the purposes: code-reuse (violating Don't Repeat Yourself (DRY)); and your possible pure ideological arguments about what is normal function and what is not would cause my question "why". DRY is a primary principle, anyway.

I'm sure your idea of RAII is frutful anyway; even if there are problem, things can be improved.
Maybe, I also need to think about more general solutions than cursor-only stuff, I just never needed such thing so far but may need in future, so, thank for for inspiration.

Your idea to avoid cursor flicker is wonderful; the only concern would be somewhat arbitrary constant for the delay, but this is not a problem per se.

I did not understand one of your comments on my style -- I do not do public fields in this class; no properties are needed. I do have rational (not just taste) arguments for my styles.
About your last note I would say you're reinventing the wheel yourself, but you do it in a fundamental way, so I respect it. Generally speaking, I believe the problem is that in programming most kinds of machinery ("wheels") were never built, strange may it sound or not.

Again, I need some time to look at your code and think. Thank you again.
GeneralMy first attempt would be, since the code for both implement... Pin
Andreas Gieriet27-Dec-10 23:00
professionalAndreas Gieriet27-Dec-10 23:00 
GeneralMy first attempt would be, since the code for both implement... Pin
Andreas Gieriet27-Dec-10 22:39
professionalAndreas Gieriet27-Dec-10 22:39 
GeneralThank you for your alternative. It looks quite good, but to ... Pin
Sergey Alexandrovich Kryukov27-Dec-10 19:28
mvaSergey Alexandrovich Kryukov27-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.