Document/View的初始化过程

来源:互联网 发布:混乱与秩序无网络连接 编辑:程序博客网 时间:2024/06/08 15:57

最近正在看《mfc深入浅出》,看到第8章Document/View深入探讨时候,对Document/View的建立过程不是很清楚,于是下大力气猛啃书和各种百度,明白了一些,做个小结:

先从CTest_DrawRectApp::InitInstance()开始

Test_DrawRect.cpp(这个文件是我建立名为Test_DrawRect工程自动生成的文件)

CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTest_DrawRectDoc),RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口RUNTIME_CLASS(CTest_DrawRectView));if (!pDocTemplate)return FALSE;AddDocTemplate(pDocTemplate);

afxwin.h

class CSingleDocTemplate : public CDocTemplate
class AFX_NOVTABLE CDocTemplate : public CCmdTarget{DECLARE_DYNAMIC(CDocTemplate)......virtual CDocument* CreateNewDocument();virtual CFrameWnd* CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther);......}


doctempl.cpp

CDocument* CDocTemplate::CreateNewDocument(){// default implementation constructs one from CRuntimeClassif (m_pDocClass == NULL){TRACE(traceAppMsg, 0, "Error: you must override CDocTemplate::CreateNewDocument.\n");ASSERT(FALSE);return NULL;}CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();if (pDocument == NULL){TRACE(traceAppMsg, 0, "Warning: Dynamic create of document type %hs failed.\n",m_pDocClass->m_lpszClassName);return NULL;}ASSERT_KINDOF(CDocument, pDocument);AddDocument(pDocument);return pDocument;}/////////////////////////////////////////////////////////////////////////////// Default frame creationCFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther){if (pDoc != NULL)ASSERT_VALID(pDoc);// create a frame wired to the specified documentASSERT(m_nIDResource != 0); // must have a resource ID to load fromCCreateContext 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 resourceif (!pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame stylesNULL, &context)){TRACE(traceAppMsg, 0, "Warning: CDocTemplate couldn't create a frame.\n");// frame will be deleted in PostNcDestroy cleanupreturn NULL;}// it worked !return pFrame;}


上面的意思就是DocTemplate这个类管理CDocument、CFrameWnd、CView这三个对象,在CDocTemplate类里有创建CFrameWnd、CDocument这两个对象的函数。那么CView对象在哪里生成呢?

在CFrameWnd里生成。

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,const RECT& rect,CWnd* pParentWnd,LPCTSTR lpszMenuName,DWORD dwExStyle,CCreateContext* pContext){HMENU hMenu = NULL;if (lpszMenuName != NULL){// load in a menu that will get destroyed when window gets destroyedHINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, ATL_RT_MENU);if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL){TRACE(traceAppMsg, 0, "Warning: failed to load menu for CFrameWnd.\n");PostNcDestroy();            // perhaps delete the C++ objectreturn FALSE;}}m_strTitle = lpszWindowName;    // save title for laterif (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)){TRACE(traceAppMsg, 0, "Warning: failed to create CFrameWnd.\n");if (hMenu != NULL)DestroyMenu(hMenu);return FALSE;}return TRUE;}CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID){ASSERT(m_hWnd != NULL);ASSERT(::IsWindow(m_hWnd));ENSURE_ARG(pContext != NULL);ENSURE_ARG(pContext->m_pNewViewClass != NULL);// Note: can be a CWnd with PostNcDestroy self cleanupCWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();if (pView == NULL){TRACE(traceAppMsg, 0, "Warning: Dynamic create of view type %hs failed.\n",pContext->m_pNewViewClass->m_lpszClassName);return NULL;}ASSERT_KINDOF(CWnd, pView);// views are always created with a border!if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0), this, nID, pContext)){TRACE(traceAppMsg, 0, "Warning: could not create view for frame.\n");return NULL;        // can't continue without a view}if (pView->GetExStyle() & WS_EX_CLIENTEDGE){// remove the 3d style from the frame, since the view is//  providing it.// make sure to recalc the non-client areaModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);}return pView;}BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext){// default create client will create a view if asked for itif (pContext != NULL && pContext->m_pNewViewClass != NULL){if (CreateView(pContext, AFX_IDW_PANE_FIRST) == NULL)return FALSE;}return TRUE;}int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs){ENSURE_ARG(lpcs != NULL);CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;return OnCreateHelper(lpcs, pContext);}int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext){if (CWnd::OnCreate(lpcs) == -1)return -1;// create special children firstif (!OnCreateClient(lpcs, pContext)){TRACE(traceAppMsg, 0, "Failed to create client pane/view for frame.\n");return -1;}// post message for initial message stringPostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);// make sure the child windows have been properly sizedRecalcLayout();return 0;   // create ok}


这段代码的意思是,在CSingleDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)中,使得CFrameWnd::Create()得到调用,CFrameWnd::Create(...)调用CFrameWnd::CreateEx(...),此函数会使得系统在还未创建窗口前发送一个WM_CREATE消息,此消息得到CFrameWnd::OnCreate(...)响应,CFrameWnd::OnCreate(...)调用CFrameWnd::OnCreateHelper(...)函数,CFrameWnd::OnCreateHelper(...)函数会调用CFrameWnd::OnCreateClient(...)函数,而CFrameWnd::OnCreateClient(...)函数会最终调用CFrameWnd::OnCreateView(...)完成CView对象的生成。

总结过程就是:

CXXXApp::InitInstance()->CSingleTemplate::CreateNewDocument(),CSingleTemplate::CreateNewFrame()->

CFrameWnd::Create()->CFrameWnd::CreateEx()->发送WM_CREATE消息->CFrameWnd::OnCreate()->

CFrameWnd::OnCreateHelper()->CFrameWnd::OnCreateClient()->CFrameWnd::CreateView()(可算到了!)。


 

原创粉丝点击