Win10环境下,拦截WM_NCCREATE消息时的一个 诡异BUG
这几天在编写一个测试渲染管线的程序时,我直接使用了一段大约在10年前封装的一段窗口代码:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{//窗口过程;
LRESULT lRet = 0;
CGRSWnd* pWnd = NULL;
......
switch (uMsg)
{
case WM_NCCREATE:
{
LPCREATESTRUCT pCS = reinterpret_cast<LPCREATESTRUCT>(lParam);
pWnd = reinterpret_cast<CGRSWnd*>(pCS->lpCreateParams);
GRS_ASSERT(NULL != pWnd);
.......
lRet = 1;
}
break;
......
return lRet;
}
看上去也没有什么特别的,就是拦截了一下WM_NCCREATE消息而已,当然目的也只是为了用自己的C++类封装Windows窗口对象。而窗口过程必须是类的静态方法,要在其中得到一个窗口句柄对应的C++对象的话,就要通过拦截这个消息然后从lpCreateParams参数中将对象指针恢复回来。仅此而已!
于是我就愉快的编译执行了这个程序,一切看上去没什么,程序运行也很正常,窗口显示也正常,画面也能正常渲染。可是,等等,窗口的标题呢?起先我并没有注意这个小细节,以为是我窗口Style不对,用现在流行的话来说,可能是我打开窗口的方式不对!当然不要太在意这些细节!
于是简单的修正了一下窗口的Style,设几个小断点跟踪下,可是我居然沮丧的发现窗口依然没有标题。鬼知道它都经历了些什么?!
最后我干脆把所有拦截处理的消息先统统注释了,然后运行,发现窗口标题居然正常显示了!好,那就排除法,一个一个恢复,然后运行,最后我发现一旦恢复了对WM_NCCREATE拦截处理,就铁定没有窗口标题,Oh,MyGod!之前这段代码都很正常啊?Why?我也没做什么处理啊,就是得到我传给它的指针而已啊,其他的我都照着微软的文档:
Return value
Type: LRESULT
If an application processes this message, it should return TRUE to continue creation of the window. If the application returns FALSE, the CreateWindow or CreateWindowEx function will return a NULL handle.
正常返回TRUE给系统了啊?
突然我反应过来,于是在调用中插入了DefWindowProc的调用,改动之后代码如下:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{//窗口过程;
LRESULT lRet = 0;
CGRSWnd* pWnd = NULL;
......
switch (uMsg)
{
case WM_NCCREATE:
{
LPCREATESTRUCT pCS = reinterpret_cast<LPCREATESTRUCT>(lParam);
pWnd = reinterpret_cast<CGRSWnd*>(pCS->lpCreateParams);
GRS_ASSERT(NULL != pWnd);
.......
lRet = DefWindowProc(hwnd, uMsg, wParam, lParam);
}
break;
......
return lRet;
}
ok,编译,运行!一切正常了。
当然这反过来也说明Windows中的核心代码细节在这10年中还是经历了很多修改,居然让我这10年前的代码都出现了这种从来没遇到过的BUG。再想想老夫硬盘上存储的这么多年来辛苦积累的代码沉淀,突然惊得我虎躯一震,菊花一紧。。。。。。。。。