在 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,在 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++ 来监视我的 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_STYLECHANGING
和 WM_STYLECHANGED
。但是当我在自己的线程上设置 SetWindowsHookExW(WH_CALLWNDPROC, ..)
- 我在这里查看 WM_STYLECHANGING
和 WM_STYLECHANGED
。 Spy++ 还使用 WH_CALLWNDPROC
- 因为它会记录此消息。那么为什么 control window procedure 没有接收呢?我在调试器下查看 - window 过程是从 UserCallWinProcCheckWow
调用的,但对于一些 windows 消息 - ThemePreWndProc
首先调用,如果它 return true - 原始window 未为此消息调用过程。所以如果 WM_STYLECHANGING
和 WM_STYLECHANGED
它是 "swallowed" by ThemePreWndProc
.
所以这不是您的代码或 MFC 中的错误,也不是 Spy++ 中的错误。只是 window "feature"
对此我真的很纳闷。我有一个 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,在 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++ 来监视我的 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_STYLECHANGING
和 WM_STYLECHANGED
。但是当我在自己的线程上设置 SetWindowsHookExW(WH_CALLWNDPROC, ..)
- 我在这里查看 WM_STYLECHANGING
和 WM_STYLECHANGED
。 Spy++ 还使用 WH_CALLWNDPROC
- 因为它会记录此消息。那么为什么 control window procedure 没有接收呢?我在调试器下查看 - window 过程是从 UserCallWinProcCheckWow
调用的,但对于一些 windows 消息 - ThemePreWndProc
首先调用,如果它 return true - 原始window 未为此消息调用过程。所以如果 WM_STYLECHANGING
和 WM_STYLECHANGED
它是 "swallowed" by ThemePreWndProc
.
所以这不是您的代码或 MFC 中的错误,也不是 Spy++ 中的错误。只是 window "feature"