Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / MFC
Article

A Persistent Wait Cursor

Rate me:
Please Sign up or sign in to vote.
4.70/5 (28 votes)
26 Jan 20033 min read 112.3K   1.6K   41   17
A simple method of maintaining a wait cursor across messages

Introduction

To use the CWaitCursor class to show a wait cursor, an instance of the object is simply created. Destroying the object restores the normal cursor. However, the documentation states that although the lifetime of the object may span messages, the wait cursor is only guaranteed to remain on the screen for the duration of the currently processing message.

The purpose of this article is to describe a simple and neat method of allowing the wait cursor to persist across messages.

Background

The reason the wait cursor is not guaranteed to persist across messages is that as well as our messages using the wait cursor, the WM_SETCURSOR message may also be processed. The default processing of this message will cause the cursor to change. To prevent this from happening, WM_SETCURSOR needs to be handled, and if the wait cursor is to be shown, we need to call CCmdTarget::RestoreWaitCursor(), thus :

BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (WaitCursorShown())
    {
        // We are showing the wait cursor
        RestoreWaitCursor();
        return TRUE;
    }

    // Let the base class deal with this one
    return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

WaitCursorShown() is simple enough - all we need to do when we create the CWaitCursor is to set a variable to indicate this, and then of course, set the variable again to indicate the destruction of the CWaitCursor. However, this has the potential to get a little messy, particularly as we may well need to implement this in a number of windows (for example, CFrameWnd and CView derived classes). It is also rather error prone, as we have to make sure we update the variable accordingly wherever the CWaitCursor object is destroyed, because it goes out of scope.

CPersistentWaitCursor

CPersistentWaitCursor is a very simple class derived from CWaitCursor. Construction of a CPersistentWaitCursor object increments a reference count, to indicate that the wait cursor is to be shown. Similarly, destruction of the object decrements the reference count. Being derived from CWaitCursor, the constructor and destructor cause the wait cursor to be shown and hidden appropriately.

CPersistentWaitCursor offers only one more method than CWaitCursor, CPersistentWaitCursor::WaitCursorShown(). This returns a bool, to indicate whether or not the wait cursor should be shown, based on the value of the reference count.

Using CPersistentWaitCursor is very simple :

#include "PersistentWaitCursor.h"

void CMyWnd::DoSomeLengthyOperation()
{
    // Create and show the wait cursor
    CPersistentWaitCursor waitCursor;

    // Do some lengthy operation
    ...

    // waitCursor goes out of scope and cursor is restored
}

BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (CPersistentWaitCursor::WaitCursorShown())
    {
        // We are showing the wait cursor
        RestoreWaitCursor();
        return TRUE;
    }

    // Let the base class deal with this one
    return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

Reference counting is performed using a single instance of CPersistentWaitCursorMonitor, a simple class which maintains the count. Access to the count is protected using a critical section.

Conclusion

Because of the simplicity of the class, I have not included a demonstration of it's use.

The class has found use in the application I am currently developing. This application is very similar in style to Windows Explorer. Items in the tree represent rows in a database. Expanding these items performs two jobs - first, child items are loaded from the database and placed in the tree, and secondly data is taken from the child items, processed, and placed into a view. Both the loading of the database items (a function of the tree), and the processing (a function of the document / view) are lengthy operations, but appear to the user as single operation. CPersistentWaitCursor simplifies showing and managing the wait cursor whilst these operations take place.

History

  • 27th January 2003 - Updated to correct compiler error in source file (included non-existent file!)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
United Kingdom United Kingdom
I started computer programming on the Spectrum (writing nothing more complicated than "Hello World" and a few programs that tunelessly Beeped ad infinitum) but then progressed to slightly more serious programming on the Amiga.

After A-Levels in Maths, Physics and Chemistry, I went to the University of East Anglia, Norwich, and studied beer, women and Computing Science.
Some years after graduating, I still have an appreciation of Computing Science, but as I am now married, my other studies are frowned upon.

Since graduating, I have worked on many diverse projects in areas including call centres, logistics, architecture and engineering, and heritage.

Comments and Discussions

 
QuestionHow can we use this with a smart pointer member variable? Pin
Andrew Truckle19-Oct-21 0:35
professionalAndrew Truckle19-Oct-21 0:35 
SuggestionCan I just say thank you for this class! Pin
andrewtruckle28-Sep-12 4:40
andrewtruckle28-Sep-12 4:40 
QuestionThreads? Pin
Pixbyte18-Mar-11 13:52
Pixbyte18-Mar-11 13:52 
GeneralGood job Pin
Franc Morales20-Apr-05 15:33
Franc Morales20-Apr-05 15:33 
GeneralRe: Good job Pin
Buzz23-Oct-06 19:50
Buzz23-Oct-06 19:50 
GeneralRe: Good job Pin
wzh1983122111-Dec-06 14:12
wzh1983122111-Dec-06 14:12 
GeneralPlease help with CCriticalSection Pin
Edward11115-Mar-05 11:14
Edward11115-Mar-05 11:14 
GeneralRe: Please help with CCriticalSection Pin
Martyn Pearson15-Mar-05 11:34
Martyn Pearson15-Mar-05 11:34 
GeneralNeat Pin
Alastair Taylor17-Oct-03 5:49
Alastair Taylor17-Oct-03 5:49 
GeneralThanks Pin
John R. Shaw11-Jul-03 13:59
John R. Shaw11-Jul-03 13:59 
Generalclass declaration Pin
Ghost12-Jun-03 5:48
Ghost12-Jun-03 5:48 
GeneralRe: class declaration Pin
Martyn Pearson12-Jun-03 8:39
Martyn Pearson12-Jun-03 8:39 
Generalsome remarks and tips Pin
dan o6-Mar-03 1:28
dan o6-Mar-03 1:28 
GeneralGood job Pin
rrrado28-Jan-03 23:19
rrrado28-Jan-03 23:19 
GeneralRe: Good job Pin
Martyn Pearson31-Jan-03 7:02
Martyn Pearson31-Jan-03 7:02 
GeneralIf I only had this a few weeks ago... Pin
Nitron8-Jan-03 3:26
Nitron8-Jan-03 3:26 
GeneralRe: If I only had this a few weeks ago... Pin
Martyn Pearson31-Jan-03 7:03
Martyn Pearson31-Jan-03 7:03 

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.