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

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

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

enter image description here

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

Итак, я решил настроить тест (в Debug build.) Вот мой модифицированный 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 ++:

enter image description here

А это копия моего журнала:

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:

enter image description here

как условие:

enter image description here

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

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

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

1 Ответ

2 голосов
/ 05 апреля 2019

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

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

...