MFC中单文档中m_pMainWnd的初始化


找了很多地方都没有找到单文



了很多地方都没有找到单文档的初始化,今天我自己来找。。

 

工具

: UltraEdit, VS2005, AJC Grep 1.1.1 试用版,

 

参考文献

:深入浅出MFC

 

目标

:找到m_pMainWnd的赋值的地方

 

m_pMainWnd

定义于

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/include/afxwin.h

 

class

CWinThread : public CCmdTarget

 

{

 

    CWnd* m_pMainWnd;      

// main window (usually same AfxGetApp()->m_pMainWnd)

 

}

 

 

 

绪:

 

我的单文档DEMO

 

BOOL CtestApp::InitInstance()

 

{

 

      

 

        InitCommonControls();

 

 

 

        CWinApp::InitInstance();

 

 

 

        AfxEnableControlContainer();

 

 

 

        CSingleDocTemplate* pDocTemplate;

 

        pDocTemplate = new CSingleDocTemplate(

 

                IDR_MAINFRAME,

 

                RUNTIME_CLASS(CtestDoc),

 

                RUNTIME_CLASS(CMainFrame),       //  SDI 框架窗口

 

                RUNTIME_CLASS(CtestView));

 

        AddDocTemplate(pDocTemplate);

 

    

 

        CCommandLineInfo cmdInfo;

 

        ParseCommandLine(cmdInfo);

 

        ProcessShellCommand(cmdInfo);

 

 

 

        // 唯一的一个窗口已初始化因此显示它并对其进行更新

 

        m_pMainWnd->ShowWindow(SW_SHOW);

 

        m_pMainWnd->UpdateWindow();

 

        // 仅当存在后缀时才调用 DragAcceptFiles

 

        //   SDI 应用程序中这应在 ProcessShellCommand  之后发生

 

        return TRUE;

 

}

 

 

 

 

 

MFC的主函数

 

Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/winmian.cpp

 

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)

 

{

 

        int nReturnCode = -1;

 

        CWinThread* pThread = AfxGetThread();

 

        CWinApp* pApp = AfxGetApp();

 

        AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow); 

 

        pApp->InitApplication();

 

        pThread->InitInstance();

 

        nReturnCode = pThread->Run();

 

        AfxWinTerm();

 

        return nReturnCode;

 

}

 

 

 

上面构造了 pThread ,pApp;其中pApp指向theApp

 

AfxGetApp AfxWin1.inl

 

AfxGetThreadAfxWin.h中定义实现于

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/thrdcore.cpp

 

 

 

为了简化过程,上面的代码中的判断语句被我删掉了!

 

 

 

开始

 

第一步:

 

搜索到 m_pMainWnd 的赋值的地方

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/docsingl.cpp

 

(1.1)CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible)

 

{

 

                ............

 

        if (bCreated && pThread->m_pMainWnd == NULL)

 

        {

 

                // set as main frame (InitialUpdateFrame will show the window)

 

               

pThread->m_pMainWnd = pFrame;

 

        }

 

......................

 

 }

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/thrdcore.cpp

 

(1.2)UINT APIENTRY _AfxThreadEntry(void* pParam)

 

{  

      

 

 

if (pApp != NULL &&pThread->m_pMainWnd == NULL && pApp->m_pMainWnd->GetSafeHwnd() != NULL)

 

   {

 

           // just attach the HWND

 

           threadWnd.Attach(pApp->m_pMainWnd->m_hWnd);

 

          

pThread->m_pMainWnd = &threadWnd;

 

    }

 

}

 

初步估计可能是在(1.1)中初始化。猜测理由初始化的时候可能需要打开一个默认的空文档。

 

第二步:

 

2.1 查找OpenDocumentFile调用的地方,

 

如果我的猜测方向没有错的话,那么在搜索到的文件中,应该是void CDocManager::OnFileNew()中调用的

 

void CDocManager::OnFileNew()

 

{

 

         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();

 

         CNewTypeDlg dlg(&m_templateList);

 

         INT_PTR nID = dlg.DoModal();

 

         if (nID == IDOK)

 

                   pTemplate = dlg.m_pSelectedTemplate;

 

         else

 

                   return;     // none - cancel operation

 

        

 

        

pTemplate->OpenDocumentFile(NULL);

 

                   // if returns NULL, the user has already been alerted

 

}

 

上述函数位于C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/docmgr.cpp

 

 

 

2.2 接着找OnFileNew的调用地方。

 

这个可能比较多,具体什么地方调用的我还不敢估计;先全部找出来在说!

 

呵呵,很幸运,我在MFC目录下搜索,只有两个文件调用过这个函数;

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/src/mfc/apppdlg.cpp

 

void CWinApp::OnFileNew()

 

{

 

        if (m_pDocManager != NULL)

 

              

 m_pDocManager->OnFileNew();

 

}

 

 

 

BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)

 

{

 

        BOOL bResult = TRUE;

 

        switch (rCmdInfo.m_nShellCommand)

 

        {

 

        case CCommandLineInfo::FileNew:

 

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

 

                     

  OnFileNew();

 

                if (m_pMainWnd == NULL)

 

                        bResult = FALSE;

 

                break;

 

 

 

                // If we've been asked to open a file, call OpenDocumentFile()

 

 

 

        case CCommandLineInfo::FileOpen:

 

                if (!OpenDocumentFile(rCmdInfo.m_strFileName))

 

                        bResult = FALSE;

 

                break;

 

……...…………………………………………………………………..

 

}

 

OK ,找到了,CWinApp::ProcessShellCommand调用CWinApp::OnFileNewCWinApp::OnFileNew调用

CDocManager::OnFileNew()

 

 

 

现在找到了什么地方初始化的m_pMainWnd,但是这个消息循环是怎么调用的呢?难道初始化的时候,一开始CCommandLineInfo::FileNew:就有这个消息?

 

 

 

2.3 再接再厉

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/include/afxwin.h中有这个定义

 

enum { FileNew, FileOpen, FilePrint, FilePrintTo, FileDDE, AppRegister,AppUnregister, FileNothing = -1 } m_nShellCommand;

 

 

 

C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/atlmfc/include/appcore.cpp中有如下定义:

 

CCommandLineInfo

的构造函数如下:

 

CCommandLineInfo::CCommandLineInfo()

 

{

 

        m_bShowSplash = TRUE;

 

        m_bRunEmbedded = FALSE;

 

        m_bRunAutomated = FALSE;

 

        m_nShellCommand = FileNew;

 

}

 

 

 

void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)

 

{

 

        for (int i = 1; i < __argc; i++)

 

        {

 

                LPCTSTR pszParam = __targv[i];

 

                BOOL bFlag = FALSE;

 

                BOOL bLast = ((i + 1) == __argc);

 

                if (pszParam[0] == '-' || pszParam[0] == '/')

 

                {

 

                        // remove flag specifier

 

                        bFlag = TRUE;

 

                        ++pszParam;

 

                }

 

                rCmdInfo.ParseParam(pszParam, bFlag, bLast);

 

        }

 

}

 

 

 

OK,搞定了,在初始化的时候,就把rCmdInfo.m_nShellCommand的值赋为FileNew,那么在调用的时候就很自然的执行Switch中的第一个case了哈。

 

于是调用CWinApp::OnFileNew,在调用CDocManager::OnFileNew(),接着调用pTemplate->OpenDocumentFile(NULL);最后在这个函数中初始化了m_pMainWnd找到了!!!

新手路上,不知道这个是不是对的,还望高手指点!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值