views:

61

answers:

2

I have created three checkbox controls for three threads and each would start by checking a checkbox control. When a user unchecks a checkbox, I want to turn on the Wait Cursor on the other thread controls rather than completely disabling them for an instance of time, letting a particular thread to stop.

How would you set a IDC_WAIT cursor id for a specific control or should i let the user to freely start/stop multiple threads in order?

+2  A: 

Handle WM_SETCURSOR (The parent window usually gets the chance to set the cursor for its children, if the child window has special handling, you would have to subclass it and handle WM_SETCURSOR there)

Anders
+1, agreed. However, sub-classing will almost certainly be required. The parent window only sees WM_SETCURSOR if the child doesn't handle it.
Hans Passant
Why does the button still can be clicked while the wait cursor is on it?
Dave18
@Dave18 The cursor has nothing to do with that, either disable the control or ignore the click message
Anders
+2  A: 

Many people do not understand how "wait" cursors are ... I hesitate to say indended to work.

The history of the message is really telling however: WM_SETCURSOR has existed since Windows 3.1 - a 16 bit co-operatively multitasked operating system. Because there was only a single thread (Being co-operatively multitasked) - it was not possible for non driver level code to run while an application was "busy". Hence, the handling for "busy" cursors was like this:

WM_SETCURSOR would always respond with the appropriate "non busy" cursor.

Any code that was going to be "busy" would look like:

SetCursor(hHourglass);
DoBusyThing();
SetCursor(hRegular);

This would change the hardware cursor to the hourglass - DoBusyThing would occupy the thread, and WM_SETCURSOR messages would not, and could not, be handled until it exited.

Win32 changed the semantics a little - It remembers on each thread the last cursor a window on that thread set - allowing the co-operative logic of Windows 3.1 to work in the casynchronously multitasked Win32 environment: If a thread is busy (i.e. not pumping messages) WM_SETCURSOR messages for windows on that thread will just get "stuck" in the message queue - hence the hourglass cursor remains the default cursor for all windows owned by the blocked thread, until the busy operation completes and the thread returns to the message processing loop.

Of course, none of this logic works really well in the modern world where we no longer block UI threads:- The busy work is now offset to a worker thread, meaning the UI thread is dispatching WM_SETCURSOR messages and resetting the busy cursor back to the class cursor.

This is not really a problem: The wait cursor have always implied that the application is non responsive and a functioning UI thread + busy worker thread is not what this feedback mechanism is really designed or intended to cover.

I think the correct thing to do would be to leave the cursor alone, and reflect on the UI some other way (stop icons next to the buttons?) that further threads can not / should not be launched.

Chris Becke
In Multithreading, Would you suspend the UI Thread and wait on worker threads to reset the cursor back to regular?
Dave18
Id let the UI thread pump messages -thats *why* we have worker threads now :P. As the UI remains responsive I don't see it as appropriate to display a wait cursor.
Chris Becke