MDI中我们看的很清楚,App::InitInstance() 中 m_pMainWnd指向了新建的FrameWnd。 但用appwizard做的SDI程序,却没有这种语句,对其他几条语句跟踪了一下,也没发现。那么,其m_pMainWnd什么时候赋值了?

解决方案 »

  1.   

    在SDI程序中,框架在CDocTemplate::CreateNewFrame(CDocument* pDoc,CFrameWnd* pOther)这个函数中。
      

  2.   

    我找到一本书,书上是这样说明的:
    1。无论是新建文档还是打开文档,最终都要调用CSingleDocTemplate::OpenDocumentFile(),
    这个函数动态的创建了文档(调用CreateNewDoucment()函数),主框架对象(CreateNewFrame()函数)。在这个函数源码的最后,有这样的代码:
       CWinThread* pThread=AfxGetMainWnd();
       if(bCreated && pThread->m_pMainWnd==NULL)
       {
          pThread->m_pMainWnd=pFrame;//pFrame是创建的主窗口
       }
    此外还是这样的代码:
      InitialUpdateFrame(pFrame,pDocument,bMakeVisible);
    用来初始化主框架窗口和主视图(CFramewnd::InitialUpdateFrame()和CView::OnInitalUpdate()).
    如果你需要完整的源码,给我发短信。。
      

  3.   

    好像不在这里啊,MFC6.0 源码如下:CDocument* CDocTemplate::CreateNewDocument()
    {
    // default implementation constructs one from CRuntimeClass
    if (m_pDocClass == NULL)
    {
    TRACE0("Error: you must override CDocTemplate::CreateNewDocument.\n");
    ASSERT(FALSE);
    return NULL;
    }
    CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
    if (pDocument == NULL)
    {
    TRACE1("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 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)
    {
    TRACE0("Error: you must override CDocTemplate::CreateNewFrame.\n");
    ASSERT(FALSE);
    return NULL;
    }
    CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
    if (pFrame == NULL)
    {
    TRACE1("Warning: Dynamic create of frame %hs failed.\n",
    m_pFrameClass->m_lpszClassName);
    return NULL;
    }
    ASSERT_KINDOF(CFrameWnd, pFrame); if (context.m_pNewViewClass == NULL)
    TRACE0("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))
    {
    TRACE0("Warning: CDocTemplate couldn't create a frame.\n");
    // frame will be deleted in PostNcDestroy cleanup
    return NULL;
    } // it worked !
    return pFrame;
    }
      

  4.   

    原来是在这里:
    CDocument* CSingleDocTemplate::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; if (m_pOnlyDoc != NULL)
    {
    // already have a document - reinit it
    pDocument = m_pOnlyDoc;
    if (!pDocument->SaveModified())
    return NULL;        // leave the original one pFrame = (CFrameWnd*)AfxGetMainWnd();
    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;
    }
    } 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
    TRACE0("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
    TRACE0("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())
    {
    TRACE0("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();
    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;
    }总结一下,大家共同提高:
    由appwizard生成的sdi程序,在其InitInstance()中,有这么两句:if (!ProcessShellCommand(cmdInfo))
    return FALSE;
    此时cmdInfo等于FileNew,后来其调用了AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL),其调用了CWinApp::OnFileNew(),其调用CDocManager::OnFileNew();其调用CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
    BOOL bMakeVisible);这里面有一句pThread->m_pMainWnd = pFrame;------------------------还不算太复杂呵