探索MFC中单文档中m_pMainWnd的初始化过程

目标:找到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中

AfxGetThread在AfxWin.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::OnFileNew,CWinApp::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。找到了!!!


 

你可能感兴趣的:(探索MFC中单文档中m_pMainWnd的初始化过程)