现在的位置: 首页 > 综合 > 正文

MFC下关于“建立空文档失败”问题的分析(转载)

2012年05月11日 ⁄ 综合 ⁄ 共 3686字 ⁄ 字号 评论关闭

这类问题的出现主要在bool CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo);

函数的关键内容: "zj[v1K9-A  
BOOL bResult = TRUE; PzOnS  
switch (rCmdInfo.m_nShellCommand) 't6l@ _x  
{ /k8I6  
case CCommandLineInfo::FileNew:  // 新建 Om^(CAp  
 if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) P -NR]f  
  OnFileNew(); )9^)t  
 if (m_pMainWnd == NULL) D(l,Z  
  bResult = FALSE; /_WR:?l  
 break; m^!:n$  
case CCommandLineInfo::FileOpen: pJx7S sW  
 if (!OpenDocumentFile(rCmdInfo.m_strFileName)) uLafO=Q  
  bResult = FALSE; T[ZmD{6l  
 break; R|n  
通过上面的内容我们可以看出:如果没有对ID_FILE_NEW做映射的话出现问题就在OnFileNew(); (oi:lC@h*  
CWinApp对OnFileNew的默认实现是调用m_pDocManager->OnFileNew();

我们继续解析cdocmanager,它究竟干了些什么? I )rO|  
(首先说明一下CDocManager它主要的功能是帮助CWinApp是管理文档模板链表和注册文件类型.)

//如果模板列表为空的话 0n{.96r0R  
if (m_templateList.IsEmpty()) @ j^R+F  
{ O;H6`JQ  
 TRACE0("Error: no document templates registered with CWinApp. 3PE.7-HF  
"); {Rkd;`Q`!  
 AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);  //报错并返回.这里不会报建立新文档出错。 VBX)xQazU  
 return; /rS*/g:i  
}

cdoctemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead(); ./#YUIC  
if (m_templateList.GetCount() > 1) )[ V8YiyU  
{ )9hqd  
 // more than one document template to choose from 32wtN8kx  
 // bring up dialog prompting user Sq5,}oT_{j  
 CNewTypeDlg dlg(&m_templateList); "^#O7.oVi+  
 int nID = dlg.DoModal(); $|~ <6A{y  
 if (nID == IDOK) p:~#(/GWf  
  pTemplate = dlg.m_pSelectedTemplate; W`[VLi}fe  
 else {8m&Z36E  
  return;     // none - cancel operation tj;47UtH  
}

assert(ptemplate != NULL); ~cm4e>o  
ASSERT_KINDOF(CDocTemplate, pTemplate);

ptemplate->opendocumentfile(null);

通过上面的代码我们可以看出,cwinapp的onfilenew和onfileopen分别调用cdocmanager的虚拟函数onfilenew和onfileopen。而在cdocmanager里面。通过模板链表选择不同的模板来调用文档模板的opendocumentfile(); tR!C8:u  
如果传入参数NULL表示新建文件。

下面我们来看看cdoctemplate::opendocumentfile()它是一个最关键的函数。因为他是虚拟函数,我们考虑CSingleDocTemplate::OpenDocumentFile的情况。 }1 O"?6  
这个函数里面有一段代码: lf-.c$.>  
其中:AFX_IDP_FAILED_TO_CREATE_DOC 就是字符“建立空文档失败”的资源id 6$OmOCA%  
// create a new document ! VT$U6  
pDocument = CreateNewDocument(); 4V9BmVS|Th  
ASSERT(pFrame == NULL);     // will be created below Fug4u?-n  
bCreated = TRUE; ^Zvb3RJg  
if (pDocument == NULL) -/p&18K#  
{ z4 =OR@ h  
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); ,8zJD&HMx  
return NULL; aoz+Th3  
} &3IkC(yD  
ASSERT(pDocument == m_pOnlyDoc); %7 -(c  
if (pFrame == NULL) CH(Y.Kj-  
{ LK4NNZf7  
ASSERT(bCreated);

// create frame - set as main document frame ZD]{HxGL!  
BOOL bAutoDelete = pDocument->m_bAutoDelete; F#yn'j8  
pDocument->m_bAutoDelete = FALSE; Z&?4<-@6/p  
// don’t destroy if something goes wrong L_9uwua.B~  
pFrame = CreateNewFrame(pDocument, NULL); Zgp9Uu}"  
pDocument->m_bAutoDelete = bAutoDelete; l'Za"TL:  
if (pFrame == NULL) 49>b] f,Vc  
{ {hOS0).(w7  
 AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); i"n_oO  
 delete pDocument;       // explicit delete on error ;{ H Dz$  
 return NULL; fnr8{sr.2Z  
}

通过观察上面的代码我们很容易的看出 有两个可能出错的原因:1 CreateNewDocument返回为NULL 2 createnewframe 返回为空。

先看 CreateNewDocument() 一般来说这个函数很少失败。不过在调试时也不能掉以轻心。 z]hRc8 g}d  
再看看CreateNewFrame()  里面有一个函数LoadFrame是造成这种“建立新文档失败”错误的源泉所在。 3^&`E} r  
只要它返回False就会弹出这样的提示。 PN9vg9'  
我们在来看看LoadFrame() 里面调用CFrameWnd::Create()来创建窗口,创建窗口失败返回Fasle。 x.t&NP^V)  
这样问题就变的比较简单了。

看看create和createex函数的动作就知道怎么回事了。 /$4z@`nY  
**************************************************************** :, v(l q  
1 如果找不到菜单资源 返回False 同时也弹出“建立空文档失败” z<!A;.iD  
HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU); JBw2#ry  
if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL) WW3Jxd  
{ Cb<7?),vK  
 TRACE0("Warning: failed to load menu for CFrameWnd. Br s}  
"); /{8Y,pZbu  
 PostNcDestroy();            // perhaps delete the C++ object uw8g%  
 return FALSE; +U, t*U4,  
} :&z!o" K  
2 重载了PreCreateWindow而且返回False也会导致弹出“建立空文档失败” }mZCQJ#`  
3 在OnCreate 里面返回-1 也会导致弹出“建立空文档失败”。
(qc <'$o  
******************************************************************

以上就是我分析的 出现这样“建立空文档失败”问题的大致原因。也许还有其他的原因。我这里就不一一列举了。

//////

我碰到一个例子是在资源管理删除了工具栏后,编译通过,但是运行是报错“建立空文档失败”。其实就是当中的第三个因素。后面我把创建工具栏的代码去掉后,运行成功。

 (摘自 http://blog.ccw.com.cn/article-htm-itemid-11391-type-blog.html)

抱歉!评论已关闭.