我们跟踪AfxWinMain()执行便可发现,在其中用到了多个Afx开头的函数进行引导。那么到底这些函数干了些什么?凭什么一个应用程序产生了呢?
我们将注意力转向AfxGetThread(),此函数返回一运行线程对象指针
CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in module thread state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
return pThread;
}
实际上此函数只进行了一下行为:
获取一AFX_MODULE_THREAD_STATE结构(AfxGetMainWnd())
获取当前线程指针(AFX_MODULE_THREAD_STATE::m_pCurrentWinThread),返回
期间最重要的操作,便是调用了AfxGetMainWnd函数。实际上AfxGetMainWnd函数中,控制权曾一度转交AfxGetModuleState。AfxGetModuleState完成的工作也就是从本地全局对象中获取数据。
下一步,我们看到,就是通过AfxGetApp()获取应用程序实例指针。接着出现了一个非常非常重要的函数,那便是AfxWinInit。看名字这么长,就知道这个函数非同寻常!!!首先,我们给出它的整个执行过程:
获取全局模块数据对象(AfxGetModuleState())
获取当前实例与资源句柄
获取应用程序实例指针(AfxGetApp())
初始化应用程序实例对象
检查是否DLL(AfxGetModuleState()->m_bDLL),不是则初始化线程(AfxInitThread())
获取user32.dll模块句柄,获取NotifyWinEvent函数指针
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
// handle critical errors and avoid Windows message boxes
SetErrorMode(SetErrorMode(0) |
SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
// set resource handles
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_hCurrentInstanceHandle = hInstance;
pModuleState->m_hCurrentResourceHandle = hInstance;
// fill in the initial state for the application
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();
}
// initialize thread specific data (for main thread)
if (!afxContextIsDLL)
AfxInitThread();
// Initialize CWnd::m_pfnNotifyWinEvent
HMODULE hModule = ::GetModuleHandle(_T("user32.dll"));
if (hModule != NULL)
{
CWnd::m_pfnNotifyWinEvent = (CWnd::PFNNOTIFYWINEVENT)::GetProcAddress(hModule, "NotifyWinEvent");
}
return TRUE;
}
值得一提的是其中的初始华线程过程:AfxInitThread()。它进行的主要操作,就是一个消息挂钩。
CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in module thread state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
return pThread;
}
这就是消息处理的真正所在!!
后面进行的Run操作,最吸引我眼球的莫过于其中的消息循环,各位看看是不是很熟悉呢?
int CWinThread::Run()
{
ASSERT_VALID(this);
_AFX_THREAD_STATE* pState = AfxGetThreadState();
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}
// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();
// reset "no idle" state after pumping "normal" message
//if (IsIdleMessage(&m_msgCur))
if (IsIdleMessage(&(pState->m_msgCur)))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
}
}