PreSubclassWindow里面再次调用Create函数创建子控件

来源:互联网 发布:linux 打包压缩文件夹 编辑:程序博客网 时间:2024/04/30 12:08

问题描述:here

我写了一个类继承CListCtrl,当然需要重写滚动条,滚动条是用CStatic的,初始化放在PresubClassWindow中(如调用cstatic的create创建滚动条),测试时使用MFC Dialog,在窗口上拉了一个CListCtrl,然后用向导生成了,然后手动修改,使其改成我自定义的CMyListCtrl,运行没有哦问题,但是我换一种方式使用ListCtrl的时候,问题出现了,我不是用MFC的向导,而是用m_ctrlMyList.Create(。。)函数,结果却导致程序崩了,这个现象很容易复现,但是将本来放在PresubClassWindow中初始化部分放到OnCreate中,程序就正常了,然而使用向导生成的(就是在MFC的DoDataExchange中让MFC自己处理),将不会调用OnCreate

问题分析:

当CListCtrl调用CreateEx函数时

1.CreateEx会调用CWnd的CreateEx,在该函数内部会依次调用PreCreateWindow,AfxHookWindowCreate(this),CreateWindowEx(SDK真正创建窗口的函数)

2.AfxHookWindowCreate(CWnd* pWnd)里面如果当前线程没有钩子函数会调用::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());设置_AfxCbtFilterHook钩子函数,WH_CBT类型的钩子会在激活、创建、销毁、最小化、最大化、移动等之前调用钩子函数(即当执行到第一步CreateWindowEx函数时会调用_AfxCbtFilterHook)。然后ASSERT(pThreadState->m_pWndInit == NULL);   // hook not already in progress,接着再pThreadState->m_pWndInit = pWnd;

3._AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)在钩子函数中会依次调用pWndInit->Attach(hWnd); (hWnd是该函数的第二个参数wParam传进来的值即HWND hWnd = (HWND)wParam;)再调用pWndInit->PreSubclassWindow();、SetWindowLongPtr(设置窗口过程)、pThreadState->m_pWndInit = NULL;,在调用pWndInit->PreSubclassWindow()时(还没有执行后面的SetWindowLongPtr和pThreadState->m_pWndInit = NULL;),正如问题中所述,在PresubClassWindow中调用Create创建CStatic,那么会回到第一步CreateEx一直执行,当执行到ASSERT(pThreadState->m_pWndInit == NULL);   // hook not already in progress 时pThreadState->m_pWndInit未清除是有值的在debug模式下必然会打印断言错误;在release模式下可以运行,但是CStatic未被成功创建。(注,我的电脑Windows7_64 vs2012下如此)

0 0