Win32: перенаправить дочернее сообщение родительскому — возвращаемое значение отличается

#c #winapi #sendmessage

#c #winapi #отправить сообщение

Вопрос:

У меня есть диалоговое окно, созданное с помощью CreateDialogParam . Он имеет только один ListView дочерний элемент управления. В обработчике диалоговых WM_INITDIALOG сообщений я подкласс ListView для настройки перерисовки заголовка.

Теперь я хочу запретить пользователю изменять размер ListView столбца (заголовка), и для этого мне просто нужно обработать HDN_BEGINTRACKA уведомление в ListView ‘s WndProc , как показано ниже:

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

Это работает нормально; но по какой-то причине я хочу обработать это сообщение в родительской (диалоговой) процедуре. Итак, я пересылаю это сообщение этому родителю, как показано ниже:

 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;
 

Сообщение отправляется нормально, но, несмотря на то, что я возвращаюсь TRUE из процедуры диалога, здесь, в ListView процедуре, возвращаемое значение SendMessage вызова равно FALSE .

В процедуре диалога код выглядит следующим образом:

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

Итак, мой вопрос в том, почему прямая отправка (пересылка) WM_NOTIFY сообщения родительскому устройству возвращает другой результат или просто просто не работает?

Редактировать :-

В прошлом я сталкивался с той же проблемой; чтобы решить ее, я попробовал пользовательское сообщение, например:

 #define UWM_WM_NOTIFY (WM_APP   7)
 

и используйте это SendMessage для связи между дочерним и родительским или между любыми другими диалогами. Но также не удается получить правильные возвращаемые значения.

Итак, я использую SendMessage следующее:

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

Отправка адреса переменной LPARAM для получения возвращаемого значения. Есть ли лучший способ сделать это. Или почему SendMessageA возвращаемое значение отличается?

Ответ №1:

Из документации Microsoft для WM_NOTIFY сообщения 1:

Если обработчик сообщения находится в процедуре диалогового окна, вы должны использовать SetWindowLong функцию with DWL_MSGRESULT для установки возвращаемого значения.

Итак, используя более современную SetWindowLongPtr функцию, ваша родительская (диалоговое окно) обработка WM_NOTIFY сообщения должна выглядеть примерно так:

 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;
        }
    }
 

Также обратите внимание, что ваш обработчик должен продолжать возвращать TRUE , как указано в этом документе:

Если вы используете SetWindowLong с DWL_MSGRESULT индексом для установки возвращаемого значения для сообщения, обработанного диалоговой процедурой, вы должны вернуться TRUE непосредственно после этого. В противном случае, если вы вызовете какую-либо функцию, в результате которой ваша диалоговая процедура получит сообщение window, сообщение вложенного окна может перезаписать возвращаемое значение, которое вы задали с помощью DWL_MSGRESULT .


1 На самом деле, вам нужно использовать описанный механизм для установки возвращаемого значения для (почти) любого сообщения, обрабатываемого диалоговой процедурой, как красиво описано в этом блоге Раймондом Ченом.

Комментарии:

1. Спасибо за ответ. это действительно полезно. Но все же я в замешательстве, как вы можете видеть, я отредактировал свой вопрос, чтобы исправить ошибку. Поскольку пользователь определяет сообщение, это не решило проблему, но я использовал LPARAM для получения возвращаемого значения. Проблема, похоже, не только в WM_NOTIFY сообщении, но и в каждом сообщении.

2. @vkchavda: Действительно, DWL_MSGRESULT используется для возврата любого сообщения из диалоговой процедуры. Ссылка на документацию WM_NOTIFY приведена потому, что это заметное сообщение, используемое в диалоговых окнах, которое возвращает значение.

3. @rodrigo — Да, действительно. Смотрите Мое редактирование и связанный блог Раймонда.