Исчезающие сообщения WS_STYLECHANGING/WS_STYLECHANGED в классе, производном и подклассе CRichEditCtrl, или ошибка в Spy++?

Я действительно озадачен этим. У меня есть CRichEditCtrl. производный класс, который также является подклассом в моем CDialog как дочерний элемент управления. (класс окна для Win32 rich-edit само окно более новое RICHEDIT50W.)

Я пытаюсь исследовать сообщения, которые транслируются в тот момент, когда курсор находится прямо в нижней части окна прямо перед тем, как пользователь нажмет ENTER, чтобы этот элемент управления отображал вертикальную полосу прокрутки:

введите здесь описание изображения

Когда я проверяю сообщения для этого окна с помощью Spy++, это показывает, что я получаю последовательность сообщений WS_STYLECHANGING/WS_STYLECHANGED. Но когда я пытаюсь поймать их в своем подклассе WndProc, ничего не происходит.

Поэтому я решил настроить тест (в сборке Debug). Вот мой модифицированный WndProc для подкласса с двумя точками останова на br0 и br1:

LRESULT CMyRichEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class
    LRESULT lRes;

    static BOOL bDoLogging = 0;
    if(message == WM_NCCALCSIZE)
    {
        int br0 = 0;       //Breakpoint here
    }
    if(bDoLogging)
    {
        TRACE(L"msg=0x%X\n", message);
    }

    if(message == WM_STYLECHANGED)      //0x007D
    {
        int br1 = 0;       //Breakpoint here
    }

    //Then its regular processing
    // ....


    return CRichEditCtrl::WindowProc(message, wParam, lParam);
}

Итак, я настроил Spy++ для отслеживания сообщений в моем окне, а затем перешел к точке в самом элементе управления, когда должна быть показана его вертикальная полоса прокрутки (скриншот выше), а затем нажал Enter. В этот момент br0 попадает в сообщение WM_NCCALCSIZE. Затем я вручную устанавливаю bDoLogging в 1, удаляю все точки останова и запускаю программу.

Вот вывод Spy++:

введите здесь описание изображения

А это копия моего лога:

atlTraceGeneral - msg=0x83  WM_NCCALCSIZE
atlTraceGeneral - msg=0x47  WM_WINDOWPOSCHANGED
atlTraceGeneral - msg=0x5   WM_SIZE
atlTraceGeneral - msg=0xF   WM_PAINT
atlTraceGeneral - msg=0x85  WM_NCPAINT
atlTraceGeneral - msg=0x14  WM_ERASEBKGND
atlTraceGeneral - msg=0xF   WM_PAINT       <<-- missing after this one
atlTraceGeneral - msg=0x87  WM_GETDLGCODE
atlTraceGeneral - msg=0x102 WM_CHAR
atlTraceGeneral - msg=0x87  WM_GETDLGCODE
atlTraceGeneral - msg=0x8   WM_KILLFOCUS
atlTraceGeneral - msg=0x281 WM_IME_SETCONTEXT
atlTraceGeneral - msg=0x282 WM_IME_NOTIFY

Обратите внимание, что в моем журнале отсутствуют сообщения WS_STYLECHANGING/WS_STYLECHANGED. Ниже приведены их свойства из Spy++:

000619 -- WS_STYLECHANGING:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | 00D4

000621 -- WS_STYLECHANGED:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | 00D4

000623 -- WS_STYLECHANGING:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4

000625 -- WS_STYLECHANGED:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4

000627 -- WS_STYLECHANGING:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4

000629 -- WS_STYLECHANGED:
styleOld: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4
styleNew: WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_MAXIMIZEBOX | 00D4

Кроме того, в следующий раз, когда я запускаю приложение, я делаю то же самое, но теперь устанавливаю конкретную точку останова в корневой процедуре окна MFC AfxWndProc:

введите здесь описание изображения

как условие:

введите здесь описание изображения

чтобы увидеть, не будет ли сообщение WS_STYLECHANGED съедено где-то в MFC до того, как его получит мой подкласс. И хотя эта точка останова срабатывает пару раз при запуске приложения, она никогда не срабатывает, когда Spy++ показывает, что это так.

Итак, что дает: это MFC? Мой код? или ошибка в Spy++?

PS. Я использую Spy++ x64 версии 15.00.27729.


person c00000fd    schedule 05.04.2019    source источник


Ответы (1)


я проверяю - управление действительно не получило WM_STYLECHANGING и WM_STYLECHANGED. но когда я устанавливаю SetWindowsHookExW(WH_CALLWNDPROC, ..) в собственный поток - я просматриваю WM_STYLECHANGING и WM_STYLECHANGED здесь. Spy++ также использует WH_CALLWNDPROC - потому что он и регистрирует эти сообщения. так почему же оконная процедура управления не получает ее? я смотрю под отладчиком - оконная процедура вызывается из UserCallWinProcCheckWow, но для некоторых оконных сообщений - ThemePreWndProc вызывается первой, и если она возвращает true - исходная оконная процедура не вызывается для этого сообщения. поэтому в случае WM_STYLECHANGING и WM_STYLECHANGED он был "проглочен" ThemePreWndProc.

так что это не ошибка в вашем коде или MFC, а не ошибка в Spy++. просто окно "функция"

person RbMm    schedule 05.04.2019
comment
Хорошо, я думаю, это особенность. И совсем не задокументировано. Хорошая находка! - person c00000fd; 05.04.2019