在 CRichEditCtrl 派生和子 class 编辑 class 中消失 WS_STYLECHANGING/WS_STYLECHANGED 消息,还是 Spy++ 中的错误?

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

对此我真的很纳闷。我有一个 CRichEditCtrl derived class that is also subclassed in my CDialog as a child control. (The window class 用于 Win32 rich-edit window 本身是一个较新的 RICHEDIT50W。)

我正在尝试调查当光标刚好位于 window 底部时广播的消息,就在用户按下 ENTER 以使该控件显示垂直滚动条之前:

当我使用 Spy++ 检查 window 的消息时,它显示我收到了一系列 WS_STYLECHANGING/WS_STYLECHANGED 消息。但是当我试图将它们捕获到我的子类 WndProc 中时,没有任何反应。

所以我决定设置一个测试(在 Debug 构建中。)这是我为子类修改的 WndProc,在 br0br1 上有两个断点:

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++ 来监视我的 window 的消息,然后在控件本身的垂直滚动条即将显示时到达该点(上面的屏幕截图),然后点击 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 window-procedure AfxWndProc:[=35 上设置特定断点=]

作为条件:

看看 WS_STYLECHANGED 消息是否在我的子类收到它之前在 MFC 的某个地方被吃掉了。尽管应用程序启动时该断点会命中几次,但当 Spy++ 显示它时,它永远不会被命中。

那么是什么:它是 MFC 吗?我的代码?还是 Spy++ 中的错误?

PS。我正在使用 Spy++ x64 版本 15.00.27729

我检查 - 控件确实没有 WM_STYLECHANGINGWM_STYLECHANGED。但是当我在自己的线程上设置 SetWindowsHookExW(WH_CALLWNDPROC, ..) - 我在这里查看 WM_STYLECHANGINGWM_STYLECHANGED。 Spy++ 还使用 WH_CALLWNDPROC - 因为它会记录此消息。那么为什么 control window procedure 没有接收呢?我在调试器下查看 - window 过程是从 UserCallWinProcCheckWow 调用的,但对于一些 windows 消息 - ThemePreWndProc 首先调用,如果它 return true - 原始window 未为此消息调用过程。所以如果 WM_STYLECHANGINGWM_STYLECHANGED 它是 "swallowed" by ThemePreWndProc.

所以这不是您的代码或 MFC 中的错误,也不是 Spy++ 中的错误。只是 window "feature"