作者:liguisen
blog:http://blog.csdn.net/liguisen/
在这一篇我们准备进入MFC源码分析,打开上一篇所建立的工程,不加任何断点,F11开始调试,进入APPMODUL.CPP:
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{//zuilang:光标停在这里,注意,加个断点。
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
然后停止debug,在CSdiApp theApp;这一句加上断点,重新F11开始,你会发现,光标首先停在这一句而不是刚才的那一句,这说明了“在C++程序中,全局对象在主程序被执行之前就已经被构造好了”(visual c++ .net技术内幕第六版P23)。
下面不断继续F11:
CSdiApp::CSdiApp()//zuilang:Sdi.cpp
{// zuilang:光标停在这里。
}
CWinApp::CWinApp(LPCTSTR lpszAppName) //zuilang:APPCORE.CPP
{// zuilang::光标停在这里,theApp父类是CWinApp。
if (lpszAppName != NULL)
m_pszAppName = _tcsdup(lpszAppName);
……
}
CWinThread::CWinThread()//zuilang:THRDCORE.CPP
{// zuilang:光标停在这里,CwinApp父类是CWinThread。
m_pThreadParams = NULL;
……
}
CCmdTarget::CCmdTarget()//zuilang:CMDTARG.CPP
{// zuilang:光标停在这里,CWinThread父类是CCmdTarget。
……
}
_ AFX_INLINE CObject::CObject()//zuilang:AFX.INL
{// zuilang:光标停在这里,CCmdTarget父类是:CObject。 }
至此,F5;
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{// zuilang:光标停在这里,改为F11往下。
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{// zuilang:光标停在这里,F10往下。
ASSERT(hPrevInstance == NULL);
int nReturnCode = -1;
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance())//zuilang:光标停在这里,F11回到CSdiApp::InitInstance()。
{
if (pThread->m_pMainWnd != NULL)
{
TRACE0("Warning: Destroying non-NULL m_pMainWnd/n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run();
InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE1("Warning: Temp map lock count non-zero (%ld)./n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}
BOOL CSdiApp::InitInstance()
{// zuilang:光标停在这里,F10往下。下面是单文档模板的创建,暂时忽略。
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSdiDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CSdiView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// zuilang:处理命令行、外壳命令等
if (!ProcessShellCommand(cmdInfo)) // zuilang:光标停在这里,F11.
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)
{// zuilang:光标停在这里,F10往下。
BOOL bResult = TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) // zuilang:光标停在这里,F11往下,然后马上Shift+F11跳出AfxGetApp()然后再次F11进入OnCmdMsg,MFC越来越复杂^_^。
OnFileNew();
if (m_pMainWnd == NULL)
bResult = FALSE;
break;
……
}
OnCmdMsg函数较长,只贴最后我们关心的:
BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{// zuilang:光标停在这里,找下面那一句。
……………..
#endif //_DEBUG
return _AfxDispatchCmdMsg(this, nID, nCode,
lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo);// zuilang::找到这一句,CTRL+F10运行到这里,F11继续。
}
}
return FALSE; // not handled
}
AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,
AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo)
// return TRUE to stop routing
{// zuilang:光标停在这里,找下面那一句。
……………..
switch (nSig)
{
case AfxSig_vv:
// normal command or control notification
ASSERT(CN_COMMAND == 0); // CN_COMMAND same as BN_CLICKED
ASSERT(pExtra == NULL);
(pTarget->*mmf.pfn_COMMAND)(); // zuilang:找到这一句,CTRL+F10运行到这里,F11继续。
break;
……………..
}
void CWinApp::OnFileNew()
{ // zuilang:终于找到FileNew。
if (m_pDocManager != NULL)
m_pDocManager->OnFileNew();//zuilang:到这里F11。
}
void CDocManager::OnFileNew()
{// zuilang:光标停在这里,找下面那一句。
if (m_templateList.IsEmpty())
{
TRACE0("Error: no document templates registered with CWinApp./n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return;
}
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
if (m_templateList.GetCount() > 1)
{
// more than one document template to choose from
// bring up dialog prompting user
CNewTypeDlg dlg(&m_templateList);
int nID = dlg.DoModal();
if (nID == IDOK)
pTemplate = dlg.m_pSelectedTemplate;
else
return; // none - cancel operation
}
ASSERT(pTemplate != NULL);
ASSERT_KINDOF(CDocTemplate, pTemplate);
pTemplate->OpenDocumentFile(NULL); // zuilang:CTRL+F10到这里F11。
// if returns NULL, the user has already been alerted
}
CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
// if lpszPathName == NULL => create new file of this type
{// zuilang:光标停在这里,找下面那一句。
……………..
InitialUpdateFrame(pFrame, pDocument, bMakeVisible); // zuilang:CTRL+F10到这里F11。
return pDocument;
}
至此我突然想改变主意,不再继续往下分析,原因有:
A:方法已经很明显,再往下,显得太罗嗦。
B:最困难的不是里面的知识点,而是要把它们很简单的说出来。很简单的说出来,让人很容易明白,这正是我的初衷,现在已不太可能。
同时,也放弃一开始说的逐句代码添加回去直到和删除代码前一模一样,以便分析每一行代码的作用的想法,因为我觉得到了现在已经不是一件什么难事。
下面用另外一个方法结尾,新建一个SDI工程(用一开始备份的也行),利用ClassWizard对CMainFrame添加如下函数:
1, BOOL CMainFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
2, nt CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
3, BOOL CMainFrame::DestroyWindow()
4, void CMainFrame::OnDestroy()
5, BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
对CSdiApp添加如下函数:
1, BOOL CSdiApp::InitApplication()
2, int CSdiApp::ExitInstance()
对CsdiView添加如下函数:
1, BOOL CSdiView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
2, void CSdiView::OnInitialUpdate()
3, BOOL CSdiView::DestroyWindow()
4, int CSdiView::OnCreate(LPCREATESTRUCT lpCreateStruct)
5, void CSdiView::OnDestroy()
通过增加上述函数(其实就是重载,放到自己的代码里,看得更清楚),然后再用“断点法”,你也许更容易发现MFC的一般流程。
初学者分析MFC代码,END!!!