Search code examples
c++winapiricheditspy++window-messages

Disappearing WS_STYLECHANGING/WS_STYLECHANGED messages in CRichEditCtrl derived & subclassed class, or a bug in Spy++?


I'm really puzzled over this. I have a CRichEditCtrl derived class that is also subclassed in my CDialog as a child control. (The window class for the Win32 rich-edit window itself is a newer RICHEDIT50W.)

I'm trying to investigate messages that are broadcast at the moment when the cursor is right at the bottom of the window right before the user hits ENTER to have that control show the vertical scrollbar:

enter image description here

When I check the messages for that window using Spy++, it shows that I'm getting a sequence of WS_STYLECHANGING/WS_STYLECHANGED messages. But when I try to trap them in my subclassed WndProc, nothing happens.

So I decided to set up a test (in Debug build.) Here's my modified WndProc for the subclass, with two breakpoints on br0 and 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);
}

So I set up Spy++ to monitor messages for my window and then get to the point in the control itself when its vertical scrollbar is about to be shown (screenshot above) and then hit Enter. At that point br0 is hit for WM_NCCALCSIZE message. I then manually set bDoLogging to 1, remove all breakpoints, and let it run.

Here's the output from Spy++:

enter image description here

And this is the copy of my log:

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

See that WS_STYLECHANGING/WS_STYLECHANGED messages are missing in my log. The following is their properties from 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

Additionally, the next time I run the app, I do the same, but now set a specific breakpoint on the root MFC window-procedure AfxWndProc:

enter image description here

as a condition:

enter image description here

to see if maybe WS_STYLECHANGED message gets eaten up somewhere in MFC before my subclass receives it. And although that breakpoint hits a couple of times when the app starts up, it never gets hit when the Spy++ is showing it to be.

So what gives: Is it MFC? My code? or a bug in Spy++?

PS. I'm using Spy++ x64 version 15.00.27729


Solution

  • i check - the control really not got WM_STYLECHANGING and WM_STYLECHANGED. but when i set SetWindowsHookExW(WH_CALLWNDPROC, ..) on self thread - i view WM_STYLECHANGING and WM_STYLECHANGED here. Spy++ also use WH_CALLWNDPROC - because this it and log this messages. so why control window procedure not receiver it ? i look under debugger - the window procedure is called from UserCallWinProcCheckWow, but for some windows messages - the ThemePreWndProc called first and if it return true - original window procedure not called for this message. so in case WM_STYLECHANGING and WM_STYLECHANGED it was "swallowed" by ThemePreWndProc.

    so this not bug in your code or MFC, not bug in Spy++. simply window "feature"