Changing the Mouse Cursor Shape

BLOWUP1 uses the SetCursor calls to change the cursor shape from an arrow to a cross hair, then to an hourglass, and back to an arrow. All these are stock cursors available in Windows. You obtain the handle to the cursor using the LoadCursor function. In Chapter 8 we'll use LoadCursor to display customized mouse cursors.

Many applications display an hourglass cursor (defined in WINDOWS.H as IDC_WAIT) while doing processing that may take some time to complete. This is fairly simple to implement. You can save the handle to the original cursor by storing the return value from SetCursor and using it to reset the cursor later. First, you'll need a variable of type HCURSOR (defined in WINDOWS.H as a HANDLE, or 16-bit WORD) to store that value:

HCURSOR hCursor ;

Right before you start the lengthy processing, use the following two lines:

hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)) ;

ShowCursor (TRUE) ;

After you're done with the work, call:

ShowCursor (FALSE) ;

SetCursor (hCursor) ;

The two ShowCursor calls display and then hide the hourglass cursor if a mouse is not actually present.

Normally, Windows changes the mouse cursor to the cursor included in the window class structure whenever the window procedure receives a WM_MOUSEMOVE message. If you use SetCursor to change the mouse cursor and then exit the window procedure, the mouse cursor will be restored to the cursor in the window class structure the next time the mouse is moved. This does not happen in BLOWUP1, because the mouse is captured during the time the cross-hair cursor (IDC_CROSS) is displayed. Windows will not change the cursor to the window class cursor when the mouse is captured. Also, if you need to display an hourglass cursor when doing some lengthy work (as BLOWUP1 does when it calls StretchBlt), you don't have to worry about the problem, because you're not receiving any other messages during that time.

But if you want to use different mouse cursors for other purposes, you should define a NULL cursor handle in your window class:

wndclass.hCursor = NULL ;

In your window function, you then call SetCursor for each WM_MOUSEMOVE message. The SetCursor call is fast if the mouse cursor is not being changed.