CWnd::GetStyle() 出错,COleControlSite 为非零无效值
问题表现:
调用对话框时出现访问非法地址错误。
出问题的对话框有:文件对话框(包括 CFileDialog 和 OPENFILENAME )和消息对话框(包括 AfxMessageBox 和 MessageBoxA ),其他对话框只是没用到,可能也有问题。
我已经进行过的分析:
通过调用栈发现所有问题的调用都是相同的,如下:
CWnd::GetStyle()
_AfxPostInitDialog()
_AfxActivationWndProc()
user32.dll!……()
//=============================================================================
// 出问题时,正在处理 WM_INITDIALOG 消息,_AfxActivationWndProc 中进行如下调用:
case WM_INITDIALOG:
{
DWORD dwStyle;
CRect rectOld;
CWnd* pWnd = CWnd::FromHandle(hWnd);
_AfxPreInitDialog(pWnd, &rectOld, &dwStyle);//====================== 1
bCallDefault = FALSE;
lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);//= 2
_AfxPostInitDialog(pWnd, rectOld, dwStyle);//======================= 3
}
break;
// _AfxPostInitDialog 中又进行了这样的调用:
AFX_STATIC void AFXAPI _AfxPostInitDialog(
CWnd* pWnd, const RECT& rectOld, DWORD dwStyleOld)
{
// must be hidden to start with
if (dwStyleOld & WS_VISIBLE)
return;
// must not be visible after WM_INITDIALOG
if (pWnd->GetStyle() & (WS_VISIBLE|WS_CHILD))
return;
……
}
// GetStyle 定义如下:
DWORD CWnd::GetStyle() const
{
ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));
if (m_pCtrlSite == NULL)//=============================================== 4
return (DWORD)GetWindowLong(m_hWnd, GWL_STYLE);
else
return m_pCtrlSite->GetStyle();//==================================== 5
}
//m_pCtrlSite 的声明如下(在 afxwin.h 中):
#ifndef _AFX_NO_OCC_SUPPORT
COleControlSite* m_pCtrlSite; // for wrapping an OLE control
#endif
//=============================================================================
出问题是在上述代码代附加注释5的那一行,m_pCtrlSite 为一个非零无效值,导致访问非法。
我已经查过,_AfxActivationWndProc 被调用,是 MFC 为了控制非 MFC 模态对话框的初始化而进行的,以保证以后切换活动窗体时的的正确响应,比如存在模态对话框时不能首先激活其父窗体。
其中,_AfxPreInitDialog 方法中也有对 GetStyle 的调用,跟踪中发现,在 Pre 中 m_pCtrlSite 的值还是 NULL ,调用默认的初始化方法之后在 Post 中就变成了 0xcdcdcdcd之类的值(也就是说还出现过其他类似“规则的”值)。
可能有用的相关环境:
我在程序里用了 CodeProject 上的一个 CSkinWin 的换肤组件,其中对软件的主窗体进行了子类化,以进行非客户区的自绘。但是 Hook 的操作是针对一个窗体进行的。
如果隔离皮肤代码,目前还没有出现过这种错误。
我用的是VS.net2003,XP sp2,简体中文;已经在简体和繁体2000上进行过,错误是一样的。但是2000发生的似乎更多。
错误在 Debug、Release 下都有,调试(Run)Release 版时本发生的情况更多。
文件对话框是自己调用的,消息对话框有自己调用的,也有断言失败MFC自己调用的。
我搜索过 MFC 中所有改变 m_pCtrlSite 的地方,但是没有跟踪到哪里改变了值。
断断续续已经忙了好些天了,仍然没有结果,所以只好求助大家,希望有能力的大侠帮忙,先行谢过了!
如果有哪些我没说明白的地方,我会再作说明。