Last updated:
22. July 2001
(Start sub-menu)
User Interface Programming Column
Splitter Controls and Dialog Resizing
(End sub-menu)
Windows applications typically display an hourglass cursor during lengthy operations, as follows:
// Set hourglass cursor and save the current cursor: const HCURSOR hcurSave = SetCursor( LoadCursor( 0, IDC_WAIT ) ); // ...perform lengthy operation here... // Restore old cursor: SetCursor( hcurSave );
SetCursor() returns a handle to the previous cursor; this seems to imply such usage. Most Windows books I’ve seen do the above, and the MFC class CWaitCursor encapsulates the same functionality.
So, what’s wrong with this picture? Consider the following sequence of events:
The problem is that the cursor should not be an arrow when it’s on the split bar. As soon as the mouse pointer is moved, the cursor will display correctly, but in the meantime, there’s a tiny crack in the smooth surface of illusion we strive to create for our users.
This particular crack can be mended quite easily, and the result is actually simpler to use than the standard example above. What I need is a function analogous to InvalidateRect(), except that it operates on the cursor. I no longer need to save the existing cursor, and the above example becomes:
// Set hourglass cursor: SetCursor( LoadCursor( 0, IDC_WAIT ) ); // ...perform lengthy operation here... // Restore normal cursor: InvalidateCursor();
The implementation of InvalidateCursor() is simple:
void InvalidateCursor( void ) { POINT pt; // Screen coordinates! GetCursorPos( &pt ); SetCursorPos( pt.x, pt.y ); }
This moves the cursor to its current location (i.e., the cursor does not actually move anywhere), forcing a WM_SETCURSOR message in the process. Doing it this way is a lot simpler than synthesizing and dispatching a WM_SETCURSOR message.
Please note that GetCursorPos() and SetCursorPos() have changed somewhat during the migration from Win16 to Win32. In Win16, these were void functions; in Win32, they each return TRUE for success and FALSE for failure. Presumably, this change is related to preemptive multithreading. As is its wont, however, Microsoft’s documentation is not very specific about possible causes of failure, except to say that the calling process must have WINSTA_READATTRIBUTES access to the window station. This is relevant only for the Windows NT family of operating systems.
waitcurs.h and waitcurs.cpp show a C++ replacement class for CWaitCursor, including a somewhat more careful Win32 implementation of the InvalidateCursor() functionality.
(Start bottom menu)
Top •
Home
• Articles
• Book
• Resources
Windows Developer Magazine
• R&D Books
• CMP Books
Amazon.com
• Amazon.co.uk
• Contact Petter Hesselberg
(End bottom menu)