7 个解决方案
#1
ding
#2
SDI中我该怎么关闭当前打开的文档,而不关闭当前程序,
#3
这个问题我研究了一下,还是比较复杂的。
首先,如果只是实现“怎么关闭当前打开的文档,而不关闭当前程序”,还是比较简单的:
在菜单中添加一个“关闭文件”菜单,菜单ID选择ID_FILE_CLOSE,这是一个预定义的ID,也可以自己添加一个ID。在文档类中添加菜单消息响应:
void C...Doc::OnClose()
{
// TODO: 在此添加命令处理程序代码
if (!SaveModified())
return;
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy document while closing views
while (!m_viewList.IsEmpty())
{
// get view attached to the document
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
pView->DestroyWindow();
}
m_bAutoDelete = bAutoDelete;
// clean up contents of document before destroying the document itself
DeleteContents();
// delete the document if necessary
if (m_bAutoDelete)
delete this;
}
这些代码是综合了CDocument::OnFileClose()和CDocument::OnCloseDocument()两个函数修改的,主要目的是实现关闭文档和视图而不关闭框架。
首先,如果只是实现“怎么关闭当前打开的文档,而不关闭当前程序”,还是比较简单的:
在菜单中添加一个“关闭文件”菜单,菜单ID选择ID_FILE_CLOSE,这是一个预定义的ID,也可以自己添加一个ID。在文档类中添加菜单消息响应:
void C...Doc::OnClose()
{
// TODO: 在此添加命令处理程序代码
if (!SaveModified())
return;
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy document while closing views
while (!m_viewList.IsEmpty())
{
// get view attached to the document
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
pView->DestroyWindow();
}
m_bAutoDelete = bAutoDelete;
// clean up contents of document before destroying the document itself
DeleteContents();
// delete the document if necessary
if (m_bAutoDelete)
delete this;
}
这些代码是综合了CDocument::OnFileClose()和CDocument::OnCloseDocument()两个函数修改的,主要目的是实现关闭文档和视图而不关闭框架。
#4
接下来的问题是这样关闭了视图之后,默认的单文档框架类没有绘制客户区,因此比较难看(试一下就知道了)。
这个问题比较简单,重载框架类的OnEraseBkgnd()函数自己绘制一个背景就可以了:
BOOL C...Frame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rcClient;
GetClientRect(rcClient);
pDC->FillSolidRect(rcClient, GetSysColor(COLOR_APPWORKSPACE));
return TRUE;
//return CFrameWnd::OnEraseBkgnd(pDC);
}
如果要效果好一些,可以像MDI一样在客户区创建一个窗口来绘制背景。
这个问题比较简单,重载框架类的OnEraseBkgnd()函数自己绘制一个背景就可以了:
BOOL C...Frame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rcClient;
GetClientRect(rcClient);
pDC->FillSolidRect(rcClient, GetSysColor(COLOR_APPWORKSPACE));
return TRUE;
//return CFrameWnd::OnEraseBkgnd(pDC);
}
如果要效果好一些,可以像MDI一样在客户区创建一个窗口来绘制背景。
#5
但是还有一个严重的问题,SDI的在新建的时候会创建一个新的框架窗口。所以如果用上面的方法来关闭文档,再新建一个文档就会出来一个新的框架窗口,而旧的又不会关闭。
解决这个问题稍微复杂一些。
我们可以重载文档模板。
从CSingleDocTemplate继承一个CSingleDocTemplateEx类,在
C...App::InitInstance()中将
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
替换为:
CSingleDocTemplateEx* pDocTemplate;
pDocTemplate = new CSingleDocTemplateEx(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
要注意:不要忘了添加CSingleDocTemplateEx的头文件;
CSingleDocTemplateEx类的构造函数和析构函数按照CSingleDocTemplate类改写一下,然后重载CSingleDocTemplateEx::OpenDocumentFile()函数:
CDocument* CSingleDocTemplateEx::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
// if lpszPathName == NULL => create new file of this type
{
CDocument* pDocument = NULL;
CFrameWnd* pFrame = NULL;
BOOL bCreated = FALSE; // => doc and frame created
BOOL bWasModified = FALSE;
pFrame = (CFrameWnd*)AfxGetMainWnd();
if (m_pOnlyDoc != NULL)
{
// already have a document - reinit it
pDocument = m_pOnlyDoc;
if (!pDocument->SaveModified())
return NULL; // leave the original one
ASSERT(pFrame != NULL);
ASSERT_KINDOF(CFrameWnd, pFrame);
ASSERT_VALID(pFrame);
}
else
{
// create a new document
pDocument = CreateNewDocument();
//ASSERT(pFrame == NULL); // will be created below
bCreated = TRUE;
}
if (pDocument == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT(pDocument == m_pOnlyDoc);
if (pFrame == NULL)
{
ASSERT(bCreated);
// create frame - set as main document frame
BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE;
// don't destroy if something goes wrong
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;
}
}
else
{
CCreateContext context;
context.m_pCurrentFrame = pFrame;
context.m_pCurrentDoc = pDocument;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (pFrame->CreateView(&context, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
//// make sure the child windows have been properly sized
pFrame->RecalcLayout();
}
if (lpszPathName == NULL)
{
// create a new document
SetDefaultTitle(pDocument);
// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;
if (!pDocument->OnNewDocument())
{
// user has been alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
if (bCreated)
pFrame->DestroyWindow(); // will destroy document
return NULL;
}
}
else
{
CWaitCursor wait;
// open an existing document
bWasModified = pDocument->IsModified();
pDocument->SetModifiedFlag(FALSE); // not dirty for open
if (!pDocument->OnOpenDocument(lpszPathName))
{
// user has been alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
if (bCreated)
{
pFrame->DestroyWindow(); // will destroy document
}
else if (!pDocument->IsModified())
{
// original document is untouched
pDocument->SetModifiedFlag(bWasModified);
}
else
{
// we corrupted the original document
SetDefaultTitle(pDocument);
if (!pDocument->OnNewDocument())
{
TRACE(traceAppMsg, 0, "Error: OnNewDocument failed after trying "
"to open a document - trying to continue.\n");
// assume we can continue
}
}
return NULL; // open failed
}
pDocument->SetPathName(lpszPathName);
}
CWinThread* pThread = AfxGetThread();
ASSERT(pThread);
if (bCreated && pThread->m_pMainWnd == NULL)
{
// set as main frame (InitialUpdateFrame will show the window)
pThread->m_pMainWnd = pFrame;
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
这里的代码是参照CSingleDocTemplate::OpenDocumentFile()函数和CSingleDocTemplate::CreateNewDocument()、CFrameWnd::LoadFrame()改写的。
这样一来,基本很好地实现了搂主的要求。
解决这个问题稍微复杂一些。
我们可以重载文档模板。
从CSingleDocTemplate继承一个CSingleDocTemplateEx类,在
C...App::InitInstance()中将
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
替换为:
CSingleDocTemplateEx* pDocTemplate;
pDocTemplate = new CSingleDocTemplateEx(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
要注意:不要忘了添加CSingleDocTemplateEx的头文件;
CSingleDocTemplateEx类的构造函数和析构函数按照CSingleDocTemplate类改写一下,然后重载CSingleDocTemplateEx::OpenDocumentFile()函数:
CDocument* CSingleDocTemplateEx::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
// if lpszPathName == NULL => create new file of this type
{
CDocument* pDocument = NULL;
CFrameWnd* pFrame = NULL;
BOOL bCreated = FALSE; // => doc and frame created
BOOL bWasModified = FALSE;
pFrame = (CFrameWnd*)AfxGetMainWnd();
if (m_pOnlyDoc != NULL)
{
// already have a document - reinit it
pDocument = m_pOnlyDoc;
if (!pDocument->SaveModified())
return NULL; // leave the original one
ASSERT(pFrame != NULL);
ASSERT_KINDOF(CFrameWnd, pFrame);
ASSERT_VALID(pFrame);
}
else
{
// create a new document
pDocument = CreateNewDocument();
//ASSERT(pFrame == NULL); // will be created below
bCreated = TRUE;
}
if (pDocument == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT(pDocument == m_pOnlyDoc);
if (pFrame == NULL)
{
ASSERT(bCreated);
// create frame - set as main document frame
BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE;
// don't destroy if something goes wrong
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;
}
}
else
{
CCreateContext context;
context.m_pCurrentFrame = pFrame;
context.m_pCurrentDoc = pDocument;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (pFrame->CreateView(&context, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
//// make sure the child windows have been properly sized
pFrame->RecalcLayout();
}
if (lpszPathName == NULL)
{
// create a new document
SetDefaultTitle(pDocument);
// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;
if (!pDocument->OnNewDocument())
{
// user has been alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
if (bCreated)
pFrame->DestroyWindow(); // will destroy document
return NULL;
}
}
else
{
CWaitCursor wait;
// open an existing document
bWasModified = pDocument->IsModified();
pDocument->SetModifiedFlag(FALSE); // not dirty for open
if (!pDocument->OnOpenDocument(lpszPathName))
{
// user has been alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
if (bCreated)
{
pFrame->DestroyWindow(); // will destroy document
}
else if (!pDocument->IsModified())
{
// original document is untouched
pDocument->SetModifiedFlag(bWasModified);
}
else
{
// we corrupted the original document
SetDefaultTitle(pDocument);
if (!pDocument->OnNewDocument())
{
TRACE(traceAppMsg, 0, "Error: OnNewDocument failed after trying "
"to open a document - trying to continue.\n");
// assume we can continue
}
}
return NULL; // open failed
}
pDocument->SetPathName(lpszPathName);
}
CWinThread* pThread = AfxGetThread();
ASSERT(pThread);
if (bCreated && pThread->m_pMainWnd == NULL)
{
// set as main frame (InitialUpdateFrame will show the window)
pThread->m_pMainWnd = pFrame;
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
这里的代码是参照CSingleDocTemplate::OpenDocumentFile()函数和CSingleDocTemplate::CreateNewDocument()、CFrameWnd::LoadFrame()改写的。
这样一来,基本很好地实现了搂主的要求。
#6
谢谢mackz 。
#7
简单的方法:
AfxGetMainWnd()->PostMessage(WM_COMMAND,ID_FILE_NEW);
AfxGetMainWnd()->PostMessage(WM_COMMAND,ID_FILE_NEW);
#1
ding
#2
SDI中我该怎么关闭当前打开的文档,而不关闭当前程序,
#3
这个问题我研究了一下,还是比较复杂的。
首先,如果只是实现“怎么关闭当前打开的文档,而不关闭当前程序”,还是比较简单的:
在菜单中添加一个“关闭文件”菜单,菜单ID选择ID_FILE_CLOSE,这是一个预定义的ID,也可以自己添加一个ID。在文档类中添加菜单消息响应:
void C...Doc::OnClose()
{
// TODO: 在此添加命令处理程序代码
if (!SaveModified())
return;
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy document while closing views
while (!m_viewList.IsEmpty())
{
// get view attached to the document
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
pView->DestroyWindow();
}
m_bAutoDelete = bAutoDelete;
// clean up contents of document before destroying the document itself
DeleteContents();
// delete the document if necessary
if (m_bAutoDelete)
delete this;
}
这些代码是综合了CDocument::OnFileClose()和CDocument::OnCloseDocument()两个函数修改的,主要目的是实现关闭文档和视图而不关闭框架。
首先,如果只是实现“怎么关闭当前打开的文档,而不关闭当前程序”,还是比较简单的:
在菜单中添加一个“关闭文件”菜单,菜单ID选择ID_FILE_CLOSE,这是一个预定义的ID,也可以自己添加一个ID。在文档类中添加菜单消息响应:
void C...Doc::OnClose()
{
// TODO: 在此添加命令处理程序代码
if (!SaveModified())
return;
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy document while closing views
while (!m_viewList.IsEmpty())
{
// get view attached to the document
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
pView->DestroyWindow();
}
m_bAutoDelete = bAutoDelete;
// clean up contents of document before destroying the document itself
DeleteContents();
// delete the document if necessary
if (m_bAutoDelete)
delete this;
}
这些代码是综合了CDocument::OnFileClose()和CDocument::OnCloseDocument()两个函数修改的,主要目的是实现关闭文档和视图而不关闭框架。
#4
接下来的问题是这样关闭了视图之后,默认的单文档框架类没有绘制客户区,因此比较难看(试一下就知道了)。
这个问题比较简单,重载框架类的OnEraseBkgnd()函数自己绘制一个背景就可以了:
BOOL C...Frame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rcClient;
GetClientRect(rcClient);
pDC->FillSolidRect(rcClient, GetSysColor(COLOR_APPWORKSPACE));
return TRUE;
//return CFrameWnd::OnEraseBkgnd(pDC);
}
如果要效果好一些,可以像MDI一样在客户区创建一个窗口来绘制背景。
这个问题比较简单,重载框架类的OnEraseBkgnd()函数自己绘制一个背景就可以了:
BOOL C...Frame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rcClient;
GetClientRect(rcClient);
pDC->FillSolidRect(rcClient, GetSysColor(COLOR_APPWORKSPACE));
return TRUE;
//return CFrameWnd::OnEraseBkgnd(pDC);
}
如果要效果好一些,可以像MDI一样在客户区创建一个窗口来绘制背景。
#5
但是还有一个严重的问题,SDI的在新建的时候会创建一个新的框架窗口。所以如果用上面的方法来关闭文档,再新建一个文档就会出来一个新的框架窗口,而旧的又不会关闭。
解决这个问题稍微复杂一些。
我们可以重载文档模板。
从CSingleDocTemplate继承一个CSingleDocTemplateEx类,在
C...App::InitInstance()中将
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
替换为:
CSingleDocTemplateEx* pDocTemplate;
pDocTemplate = new CSingleDocTemplateEx(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
要注意:不要忘了添加CSingleDocTemplateEx的头文件;
CSingleDocTemplateEx类的构造函数和析构函数按照CSingleDocTemplate类改写一下,然后重载CSingleDocTemplateEx::OpenDocumentFile()函数:
CDocument* CSingleDocTemplateEx::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
// if lpszPathName == NULL => create new file of this type
{
CDocument* pDocument = NULL;
CFrameWnd* pFrame = NULL;
BOOL bCreated = FALSE; // => doc and frame created
BOOL bWasModified = FALSE;
pFrame = (CFrameWnd*)AfxGetMainWnd();
if (m_pOnlyDoc != NULL)
{
// already have a document - reinit it
pDocument = m_pOnlyDoc;
if (!pDocument->SaveModified())
return NULL; // leave the original one
ASSERT(pFrame != NULL);
ASSERT_KINDOF(CFrameWnd, pFrame);
ASSERT_VALID(pFrame);
}
else
{
// create a new document
pDocument = CreateNewDocument();
//ASSERT(pFrame == NULL); // will be created below
bCreated = TRUE;
}
if (pDocument == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT(pDocument == m_pOnlyDoc);
if (pFrame == NULL)
{
ASSERT(bCreated);
// create frame - set as main document frame
BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE;
// don't destroy if something goes wrong
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;
}
}
else
{
CCreateContext context;
context.m_pCurrentFrame = pFrame;
context.m_pCurrentDoc = pDocument;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (pFrame->CreateView(&context, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
//// make sure the child windows have been properly sized
pFrame->RecalcLayout();
}
if (lpszPathName == NULL)
{
// create a new document
SetDefaultTitle(pDocument);
// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;
if (!pDocument->OnNewDocument())
{
// user has been alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
if (bCreated)
pFrame->DestroyWindow(); // will destroy document
return NULL;
}
}
else
{
CWaitCursor wait;
// open an existing document
bWasModified = pDocument->IsModified();
pDocument->SetModifiedFlag(FALSE); // not dirty for open
if (!pDocument->OnOpenDocument(lpszPathName))
{
// user has been alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
if (bCreated)
{
pFrame->DestroyWindow(); // will destroy document
}
else if (!pDocument->IsModified())
{
// original document is untouched
pDocument->SetModifiedFlag(bWasModified);
}
else
{
// we corrupted the original document
SetDefaultTitle(pDocument);
if (!pDocument->OnNewDocument())
{
TRACE(traceAppMsg, 0, "Error: OnNewDocument failed after trying "
"to open a document - trying to continue.\n");
// assume we can continue
}
}
return NULL; // open failed
}
pDocument->SetPathName(lpszPathName);
}
CWinThread* pThread = AfxGetThread();
ASSERT(pThread);
if (bCreated && pThread->m_pMainWnd == NULL)
{
// set as main frame (InitialUpdateFrame will show the window)
pThread->m_pMainWnd = pFrame;
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
这里的代码是参照CSingleDocTemplate::OpenDocumentFile()函数和CSingleDocTemplate::CreateNewDocument()、CFrameWnd::LoadFrame()改写的。
这样一来,基本很好地实现了搂主的要求。
解决这个问题稍微复杂一些。
我们可以重载文档模板。
从CSingleDocTemplate继承一个CSingleDocTemplateEx类,在
C...App::InitInstance()中将
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
替换为:
CSingleDocTemplateEx* pDocTemplate;
pDocTemplate = new CSingleDocTemplateEx(
IDR_MAINFRAME,
RUNTIME_CLASS(CShowBitmapDoc),
RUNTIME_CLASS(CShowBitmapFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CShowBitmapView));
要注意:不要忘了添加CSingleDocTemplateEx的头文件;
CSingleDocTemplateEx类的构造函数和析构函数按照CSingleDocTemplate类改写一下,然后重载CSingleDocTemplateEx::OpenDocumentFile()函数:
CDocument* CSingleDocTemplateEx::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
// if lpszPathName == NULL => create new file of this type
{
CDocument* pDocument = NULL;
CFrameWnd* pFrame = NULL;
BOOL bCreated = FALSE; // => doc and frame created
BOOL bWasModified = FALSE;
pFrame = (CFrameWnd*)AfxGetMainWnd();
if (m_pOnlyDoc != NULL)
{
// already have a document - reinit it
pDocument = m_pOnlyDoc;
if (!pDocument->SaveModified())
return NULL; // leave the original one
ASSERT(pFrame != NULL);
ASSERT_KINDOF(CFrameWnd, pFrame);
ASSERT_VALID(pFrame);
}
else
{
// create a new document
pDocument = CreateNewDocument();
//ASSERT(pFrame == NULL); // will be created below
bCreated = TRUE;
}
if (pDocument == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT(pDocument == m_pOnlyDoc);
if (pFrame == NULL)
{
ASSERT(bCreated);
// create frame - set as main document frame
BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE;
// don't destroy if something goes wrong
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;
}
}
else
{
CCreateContext context;
context.m_pCurrentFrame = pFrame;
context.m_pCurrentDoc = pDocument;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (pFrame->CreateView(&context, AFX_IDW_PANE_FIRST) == NULL)
return FALSE;
//// make sure the child windows have been properly sized
pFrame->RecalcLayout();
}
if (lpszPathName == NULL)
{
// create a new document
SetDefaultTitle(pDocument);
// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;
if (!pDocument->OnNewDocument())
{
// user has been alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
if (bCreated)
pFrame->DestroyWindow(); // will destroy document
return NULL;
}
}
else
{
CWaitCursor wait;
// open an existing document
bWasModified = pDocument->IsModified();
pDocument->SetModifiedFlag(FALSE); // not dirty for open
if (!pDocument->OnOpenDocument(lpszPathName))
{
// user has been alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
if (bCreated)
{
pFrame->DestroyWindow(); // will destroy document
}
else if (!pDocument->IsModified())
{
// original document is untouched
pDocument->SetModifiedFlag(bWasModified);
}
else
{
// we corrupted the original document
SetDefaultTitle(pDocument);
if (!pDocument->OnNewDocument())
{
TRACE(traceAppMsg, 0, "Error: OnNewDocument failed after trying "
"to open a document - trying to continue.\n");
// assume we can continue
}
}
return NULL; // open failed
}
pDocument->SetPathName(lpszPathName);
}
CWinThread* pThread = AfxGetThread();
ASSERT(pThread);
if (bCreated && pThread->m_pMainWnd == NULL)
{
// set as main frame (InitialUpdateFrame will show the window)
pThread->m_pMainWnd = pFrame;
}
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}
这里的代码是参照CSingleDocTemplate::OpenDocumentFile()函数和CSingleDocTemplate::CreateNewDocument()、CFrameWnd::LoadFrame()改写的。
这样一来,基本很好地实现了搂主的要求。
#6
谢谢mackz 。
#7
简单的方法:
AfxGetMainWnd()->PostMessage(WM_COMMAND,ID_FILE_NEW);
AfxGetMainWnd()->PostMessage(WM_COMMAND,ID_FILE_NEW);