What is the default cursor for a thread?

Raymond Chen


When we looked at the process by which the cursor is set, we neglected to discuss the case where nobody bothers to set the cursor. What is the ultimate default cursor?

Let’s write a program that refuses to set the cursor. Take the scratch program and add these lines:

BOOL OnSetCursor(HWND hwnd, HWND hwndCursor,
                 UINT codeHitTest, UINT msg)
  return TRUE;
   HANDLE_MSG(hwnd, WM_SETCURSOR, OnSetCursor);

What we did was make the window explicitly refuse to set the cursor by making it do nothing and return TRUE, which means, “It’s all good. I set the cursor!” (Liar, liar, pants on fire.)

Run this program, move the cursor over the window, and what do you get?

The hourglass.

Now, this is clearly some sort of pathological case, where there is a thread that covers its ears and hums whenever the window manager asks it to specify a cursor. But you can end up in this case unintentionally, and in fact there’s a good chance that you’ve seen it happen. Just write an application that blocks the UI thread during startup. Take a fresh scratch program and add a different line of code:

        ShowWindow(hwnd, nShowCmd);
        while (GetMessage(&msg, NULL, 0, 0)) {

Here, we’re simulating a program that hangs its UI thread during initialization. During that initial five-second delay, the program has yet to pump any messages, so it hasn’t yet received the WM_MOUSE­MOVE or WM_NC­MOUSE­MOVE message that would normally trigger the WM_SET­CURSOR message. All the window manager can do is show the default cursor.

That’s why the default cursor is an hourglass.


Comments are closed.