创建空白文档失败的原因

好久没有写文章了.@_@!!!,每次写文章都是这句开头的,悲剧.

 

创建空白文档失败的原因

我们来跟踪下代码的执行:

1.       CSingleDocTemplate* pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CQTimerDoc),

                                                        RUNTIME_CLASS(CMainFrame),RUNTIME_CLASS(CQTimerView));

单步跟踪,最终到达这儿:

CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,

         CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)

{

         ASSERT_VALID_IDR(nIDResource);

m_nIDResource = nIDResource;

。。。

}

         这儿要求Resource必须是有效的,下面会看到这个id的用途

2.       继续向下调试,到这儿

// Dispatch commands specified on the command line

if (!ProcessShellCommand(cmdInfo))

           return FALSE;

看下cmdInfo的字段m_nShellCommand值:FileNew

 

3.       跟进ProcessShellCommand

case CCommandLineInfo::FileNew:

           if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))

                    OnFileNew();

           if (m_pMainWnd == NULL)

                    bResult = FALSE;

           break;

我们可以知道在这几行代码中创建了主窗体,并赋值给了m_pMainWnd

 

4.       重载OnCmdMsg,让它返回FALSE以便于我们进入到CWinApp::OnFileNew

这并不重要,继续跟踪将会到达这儿:

CDocument* CSingleDocTemplate::OpenDocumentFile(。。。。。)

{

         if (m_pOnlyDoc != NULL)

         {

                   pDocument = m_pOnlyDoc;

                   pFrame = (CFrameWnd*)AfxGetMainWnd();

         }

         else

                   pDocument = CreateNewDocument();

         if (pDocument == NULL)

                  AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

        

CFrameWnd* pFrame  = CreateNewFrame(pDocument, NULL);

     if (pFrame == NULL)

                            AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

}

 

AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC)就是你看到的“创建空文档失败”的对话框了。

从上面的代码中可以看到造成“创建空文档失败”的原因有两个:创建Document失败和创建Frame失败。现在来着重看下第二个,第一个的分析也类似。

 

上面的函数中的这句: CreateNewFrame(pDocument, NULL);就是负责创建主窗体的

CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)

{

if (!pFrame->LoadFrame(m_nIDResource,……..)

           return NULL;

}

这个LoadFrame会调用Create函数,其参数时这样的:

if (!Create(……ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext))

                   return FALSE;   // will self destruct on failure normally

         上面的这个nIDResource就是传递给CreateMenu菜单参数,用于加载主窗体的菜单的。

BOOL CFrameWnd::Create( LPCTSTR lpszMenuName)

{

         if (lpszMenuName != NULL)

         {

                  if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)

                            return FALSE;

         }

看到这儿问题的答案就很明显了::假如你的菜单的ID不是0而它又是无效菜单的ID,那就创建空文档失败了。事实上它是创建主创体失败了。

 

到这儿解决的办法倒也极其简单:不执行进if语句不就完了么!那就需要lpszMenuName值为NULL,追根溯源就是CSingleDocTemplate(IDR_MAINFRAME,。。。。)第一个参数传进去0,但是这种方法只能是在程序的Release版本中使用,原因自然是在上面分析的第一步中的那个ASSERT啦。

 

另外一种方法是:传给它一个有效的菜单ID,如果你又不想让它显示菜单,就重载PreCreateWindow, 并且写cs.hMenu = 0;

 

你可能感兴趣的:(command,File,null,Class,文档,menu)