Click here to Skip to main content
Click here to Skip to main content

A Persistent Wait Cursor

, 26 Jan 2003
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Martyn Pearson
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

 
GeneralGood job PinmemberFranc Morales20-Apr-05 15:33 
GeneralRe: Good job PinmemberBuzz23-Oct-06 19:50 
GeneralRe: Good job Pinmemberwzh1983122111-Dec-06 14:12 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140902.1 | Last Updated 27 Jan 2003
Article Copyright 2003 by Martyn Pearson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid