代码改变世界

如何消除Microsoft Office Spreadsheet 11.0控件引起的断言失败对话框

2011-04-25 14:32  愤怒的青蛙  阅读(997)  评论(0编辑  收藏  举报

转载自:程序人生

在一个对话框上,插入一个Microsoft Office Spreadsheet 11.0控件(Office 2003带的),再插入一个别的具有焦点的控件,比如Edit控件,运行之后,用鼠标在Microsoft Office Spreadsheet 11.0控件和Edit控件之间切换一下焦点(如果用Tab切换没问题),再关闭对话框,就出现断言失败(这时所有代码都是开发环境产生的), 调试器定位在cmdtarg.cpp中:

CCmdTarget::~CCmdTarget()
{
#ifndef _AFX_NO_OLE_SUPPORT
         if (m_xDispatch.m_vtbl != 0) 
                ((COleDispatchImpl*)&m_xDispatch)->Disconnect();
         ASSERT(m_dwRef <= 1); //<-中断在这句 
#endif
#ifdef _AFXDLL 
        m_pModuleState = NULL; 
#endif 
} 

此时m_dwRef的值,等于Microsoft Office Spreadsheet 11.0控件获得焦点(鼠标设置)的次数+1。 
使用Microsoft Office Spreadsheet 10.0控件(Office 2002带的)则没有这个问题。
应该是11.0版本的控件代码存在bug。
说明该控件作者在控件取得焦点时,++m_dwRef,而在控件失去焦点时,却没有相应的--m_dwRef。导致出现了上面所述的规律。 
release版本不会出现断言失败框,如果想在debug下关闭的烦人的断言失败框,最佳解决办法如下:
添加对话框WM_DESTROY消息处理,添加如下代码。
void CxxxDlg::-OnDestroy()
{ 
#ifdef _DEBUG 
    int old = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); 
#endif 
    CDialog::OnDestroy(); 
#ifdef _DEBUG 
    _CrtSetReportMode(_CRT_ASSERT, old); 
#endif
}