Home > Net >  Win32: Forward child message to parent - return value is different
Win32: Forward child message to parent - return value is different

Time:12-01

I have dialog created using CreateDialogParam. It has only a single ListView child control. In the dialog WM_INITDIALOG message handler, I subclass the ListView to customize header redrawing.

Now I want to prevent the user from resizing the ListView column (header) and, to do this, I just need to handle the HDN_BEGINTRACKA notification message in the ListView's WndProc, like below:

case WM_NOTIFY:
    {
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
            return TRUE; // to disable column resizing
    }

This works OK; but, for some reason I want to handle this message in the parent (dialog) procedure. So, I forward this message to that parent as below:

case WM_NOTIFY:
        {
            if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
                || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW)) 
            {
                BOOL b = FALSE;
                HWND hParent = GetRealParent(hwnd);
                if (hParent) b = SendMessage(hParent, msg, wParam, lParam);
                return b; // to disable column resizing return TRUE;
            }
        }
        break;

The message is sent OK but, even though I return TRUE from the dialog procedure, here in the ListView procedure, the return value of the SendMessage call is FALSE.

In the dialog procedure, the code is as below:

case WM_NOTIFY:
    {
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
            return TRUE;
    }

So, my question is why directly sending (forwarding) the WM_NOTIFY message to the parent returns a different result, or simply just doesn't work?

Edit :-

In the past, I have faced the same problem; to solve it, I tried a user-defined message, like:

#define UWM_WM_NOTIFY (WM_APP   7)

and use that with SendMessage to communicate between child and parent, or between any other dialogs. But it also fails to get proper return values.

So, I am using SendMessage as follow:

BOOL b = FALSE;
SendMessageA(hDlg, UWM_ANY_WM, 0, (LPARAM) &b);
return b;

Sending address of variable as LPARAM to get return value. Is there any better way to do this. Or Why SendMessageA return value is different?

CodePudding user response:

From the Microsoft documentation for the WM_NOTIFY message1:

If the message handler is in a dialog box procedure, you must use the SetWindowLong function with DWL_MSGRESULT to set a return value.

So, using the more up-to-date SetWindowLongPtr function, your parent (dialog box) handling for the WM_NOTIFY message should look something like this:

case WM_NOTIFY:
    {
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
        {
            SetWindowLongPtr(hWnd, DWL_MSGRESULT, TRUE); // hWnd is dialog's HWND
            return TRUE;
        }
    }

Also note that your handler should continue to return TRUE, as noted in this document:

If you use SetWindowLong with the DWL_MSGRESULT index to set the return value for a message processed by a dialog procedure, you should return TRUE directly afterward. Otherwise, if you call any function that results in your dialog procedure receiving a window message, the nested window message could overwrite the return value you set using DWL_MSGRESULT.


1 Actually, you need to use the outlined mechanism to set the return value for (almost) any message handled by a dialog procedure, as nicely described in this blog by Raymond Chen.

  • Related