PRB: Dialog Procedure Cannot Change Cursor of Control

ID Number: Q79983

3.00

WINDOWS

docerr

Summary:

SYMPTOMS

An application uses the method described in the documentation for

WM_SETCURSOR in version 3.0 of the "Microsoft Windows Software

Development Kit Reference Volume 1" on pages 6-98 and 6-99 to

change the cursor for one of the child window controls in a dialog

box, and the cursor does not change.

CAUSE

A dialog procedure cannot change the value returned by DefDlgProc()

in response to WM_SETCURSOR.

RESOLUTION

Subclass the child window control in the dialog box and change the

cursor in the subclass procedure.

More Information:

In the documentation for WM_SETCURSOR, the comments section states

that when the message is not processed by a window, DefWindowProc()

sends the message to the parent window to allow it to change the

cursor. If the parent window's window procedure returns TRUE, further

processing of the message is halted and the cursor specified by the

parent window is used. This method gives the parent window control

over the cursor used in a child window.

This technique does not work when a standard dialog box attempts to

set the cursor for one of its child window controls because there is

no method to change the value returned by DefDlgProc() in response to

the WM_SETCURSOR message. DefDlgProc() is the window procedure for the

standard dialog-box class. It calls the user-defined dialog procedure.

If the dialog procedure returns FALSE to indicate that it did not

process a message, DefDlgProc() performs the default processing.

The Boolean value returned from the dialog procedure in response to

WM_SETCURSOR indicates only whether the dialog procedure has processed

the message or not. It does not specify the value that DefDlgProc()

should return in response to the message. [Note that the WM_CTLCOLOR,

WM_COMPAREITEM, WM_VKEYTOITEM, and WM_CHARTOITEM messages are treated

differently. The value returned by the dialog procedure in response to

these messages is returned by DefDlgProc().]

Because it is not possible for the dialog procedure to specify the

value returned by DefDlgProc() when it processes the WM_SETCURSOR

message, it cannot indicate that a new cursor was specified for a

child window control. DefDlgProc() always returns FALSE in response to

the WM_SETCURSOR message, regardless of how the dialog procedure

processed the message. Therefore, the control's default cursor is

always used because its parent window did not return TRUE in response

to the WM_SETCURSOR message.

One way to work around this problem is to subclass the control that

will have its cursor changed. The following code demonstrates how the

subclass procedure can process the WM_SETCURSOR message:

case WM_SETCURSOR:

SetCursor(hCursor);

return 0L; // Do not pass this message on

This technique succeeds because the control sets its own cursor and

does not pass the WM_SETCURSOR message to DefDlgProc().

Additional reference words: 3.00