// 我在创建新文档时通常通过pDocTemplate->OpenDocumentFile(NULL)的方式创建;
// 下面贴出调用代码
// AFX_IDP_FAILED_TO_CREATE_DOC就是“创建空文档失败”
// 当前遇到的情况是在CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
// 创建框架窗口时失败,进行跟就去
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible)
{
return OpenDocumentFile(lpszPathName, TRUE, bMakeVisible);
}
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible)
{
CDocument* pDocument = CreateNewDocument();
if (pDocument == NULL)
{
TRACE(traceAppMsg, 0, "CDocTemplate::CreateNewDocument returned NULL.\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT_VALID(pDocument);
BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong
CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
pDocument->m_bAutoDelete = bAutoDelete;
if (pFrame == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
delete pDocument; // explicit delete on error
return NULL;
}
ASSERT_VALID(pFrame);
if (lpszPathName == NULL)
{
// create a new document - with default document name
SetDefaultTitle(pDocument);
// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;
if (!pDocument->OnNewDocument())
{
// user has be alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
pFrame->DestroyWindow();
return NULL;
}
// it worked, now bump untitled count
m_nUntitledCount++;
}
else
{
// open an existing document
CWaitCursor wait;
if (!pDocument->OnOpenDocument(lpszPathName))
{
// user has be alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
pFrame->DestroyWindow();
return NULL;
}
pDocument->SetPathName(lpszPathName, bAddToMRU);
pDocument->OnDocumentEvent(CDocument::onAfterOpenDocument);
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
// 更进去之后发现,CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
// 进行创建框架窗口,继续跟进去
CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)
{
if (pDoc != NULL)
ASSERT_VALID(pDoc);
// create a frame wired to the specified document
ASSERT(m_nIDResource != 0); // must have a resource ID to load from
CCreateContext context;
context.m_pCurrentFrame = pOther;
context.m_pCurrentDoc = pDoc;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (m_pFrameClass == NULL)
{
TRACE(traceAppMsg, 0, "Error: you must override CDocTemplate::CreateNewFrame.\n");
ASSERT(FALSE);
return NULL;
}
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
if (pFrame == NULL)
{
TRACE(traceAppMsg, 0, "Warning: Dynamic create of frame %hs failed.\n",
m_pFrameClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CFrameWnd, pFrame);
if (context.m_pNewViewClass == NULL)
TRACE(traceAppMsg, 0, "Warning: creating frame with no default view.\n");
// create new from resource
if (!pFrame->LoadFrame(m_nIDResource,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame styles
NULL, &context))
{
TRACE(traceAppMsg, 0, "Warning: CDocTemplate couldn't create a frame.\n");
// frame will be deleted in PostNcDestroy cleanup
return NULL;
}
// it worked !
return pFrame;
}
// 跟到这里发现了原因m_pfnCreateObject的值为空
// DECLARE_DYNCREATE发现了这个宏
// 猜测跟创建子框架窗口的类时添加的宏有关
// 发现我自己创建子框架添加的宏是DECLARE_DYNAMIC
// 将修改为DECLARE_DYNCREATE即可成功
// 在.cpp文件中修改IMPLEMENT_DYNCREATE宏
// 出现这样的原因是通过向导创建默认添加的是DECLARE_DYNAMIC宏
CObject* CRuntimeClass::CreateObject()
{
ENSURE(this);
if (m_pfnCreateObject == NULL)
{
TRACE(traceAppMsg, 0,
_T("Error: Trying to create object which is not ")
_T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),
m_lpszClassName);
return NULL;
}
CObject* pObject = NULL;
TRY
{
pObject = (*m_pfnCreateObject)();
}
END_TRY
return pObject;
}
// 下面给出这些宏定义的区别
#define DECLARE_DYNAMIC(class_name) \
public: \
static const CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
#define _DECLARE_DYNAMIC(class_name) \
public: \
static CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
#endif
// not serializable, but dynamically constructable
#define DECLARE_DYNCREATE(class_name) \
DECLARE_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();
#define _DECLARE_DYNCREATE(class_name) \
_DECLARE_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();
// 这只是我找到的原因之一,调试了很久都没找到原因。
// 因为我发现问题的项目调试时无法进到OpenDocumentFile中。
// 所以另创建了一个测试项目进行调试,才可以跟就去。
转载于:https://my.oschina.net/u/3618870/blog/1476117