05 MFC框架运行大概流程
先明确以下关系:
CWinApp取代了原来Win32下的WinMain
CFrameWnd取代了原来Win32下的WndProc
调试代码如下:
/*
*HelloMFC.h
*/
#ifndef _HELLO_MFC_
#define _HELLO_MFC_
class CMyApp : public CWinApp{
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd{
public:
CMainWindow();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
};
#endif
/*
*HelloMFC.cpp
*/
#include <afxwin.h>
#include "HelloMFC.h"
CMyApp myApp;
BOOL CMyApp::InitInstance()
{
//这里虽然在堆区创建的对象,但我们并没有释放,是因为有一个PostNcDestroy函数在
//窗口销毁时会被调用来销毁这个对象
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
Create(NULL, TEXT("Hello MFC"));
}
void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
AfxMessageBox(TEXT("OnLButtonDown"));
}
我们现在如图所示F9下断点,然后F10进入到AfxWinMain中;
下面我们将AfxWinMain提出来写点注释:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);//断言,作用同容错判断
//在进入这里前已经初始化好了myApp
int nReturnCode = -1;
//以下两句,效果差不多,取应用程序实例指针
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
/*
下面这个函数我们跟进去,发现其作用是初始化类成员变量,所以我们在我们InitInstance
函数中用的m_nCmdShow成员变量实际在这里面已经初始化好了,关键代码如下:
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
{
// Windows specific initialization (not done if no CWinApp)
pApp->m_hInstance = hInstance;
hPrevInstance; // Obsolete.
pApp->m_lpCmdLine = lpCmdLine;
pApp->m_nCmdShow = nCmdShow;
pApp->SetCurrentHandles();
}
*/
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// 全局初始化,几乎不用,我们不去关注它
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
// 这就是我们的核心,就是我们代码中我们的类重写的虚函数,这里就进到我
//们的InitInstance,这里也就解释了为什么我们的InitInstance()要放回TRUE
//如果返回FALSE就会销毁窗口,退出程序
if (!pThread->InitInstance())
{
if (pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
//这里就实现Win32中消息循环,下面把关键代码贴出来
/*
// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// 根据空闲状态标志判断线程是否为空闲,如果是就调用OnIdle虚函数,我们可以重写
//这个虚函数实现我们想要的效果
while (bIdle &&
!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
{
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}
// 非空闲状态
do
{
// PumpMessage中有我们熟悉的GetMessage ThranslateMessage
//DispatchMessage
if (!PumpMessage())
return ExitInstance();
if (IsIdleMessage(&(pState->m_msgCur)))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
}
*/
nReturnCode = pThread->Run();
InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}