发信人: sodo()
整理人: cobe(1999-12-17 10:23:54), 站内信件
|
MFC剖析:消息机制
首先,让我们看一下MFC的消息循环部分:
(程序取自MFC源程序,由于篇幅,我删去了一些非重要的部分。)
MFC的WinMain函数:
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
int AFXAPI AfxWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
int nReturnCode = -1;
CWinApp* pApp = AfxGetApp();
// ......
// Perform specific initializations
if (!pApp->InitInstance())
{
// ......
//初始化实例不成功,通常一个Dialog Based MFC程序必须返回FALSE
//这样就可以跳过消息循环。
nReturnCode = pApp->ExitInstance();
goto InitFailure;
}
nReturnCode = pApp->Run(); //进入消息循环部分
InitFailure:
// ......
// 程序结束
AfxWinTerm();
return nReturnCode;
}
int CWinApp::Run()
{
// ......
return CWinThread::Run(); // 消息循环被封装在CWinThread类里。
}
int CWinThread::Run()
{
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
// 死循环,只有收到 WM_QUIT 消息后才会退出。
for (;;)
{
while (bIdle &&
!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
if (!OnIdle(lIdleCount++))
bIdle = FALSE;
}
// 如果消息队列中没有消息,那么就调用OnIdle函数
// 否则,发送消息
do
{
if (!PumpMessage())
// PumpMessage函数仅在收到WM_QUIT消息才返回FALSE
return ExitInstance(); // 退出死循环
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
// 这段程序不仅完成了消息的发送,还实现了Idle功能。
// GetMessage函数在消息队列中没有消息时,将不会返回,
// 而是将控制权交给操作系统,直到消息队列中有消息为止。
// 这段程序在一开始就调用PeekMessage函数来检测消息队列中
// 是否有消息存在,如果存在就发送消息,
// 否则就意味着空闲,那么就调用OnIdle函数,
// 这样做,控制权永远不会交给操作系统。
// 由于Windows 95, NT都是抢占式的操作系统,
// 系统会自动进行任务切换。
// 所以不用担心别的程序不会被运行。
}
}
BOOL CWinThread::PumpMessage()
{
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{// 收到 WM_QUIT 消息,就返回 FALSE。
return FALSE;
}
// 否则就发送消息
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur) )
{
::TranslateMessage(&m_msgCur);
::DispatchMessage(&m_msgCur);
}
return TRUE;
}
主程序的流程:
(程序开始)
|
|
v
WinMain
|
|
v
AfxWinMain
|
|
v FALSE
CWinApp::InitInstance-------> 退出程序
|
|TRUE
|
v
CWinApp::Run
|
|
v
CWinThread::Run
|
|<----------------------------+
v FALSE |
PeekMessage------->OnIdle--------+
|TRUE |
|<-------------------------+ |
v | |
GetMessage | |
| | |
| | |
YES v | |
+-----WM_QUIT 消息? | |
| | | |
| |NO | |
| v | |
| TranslateMessage | |
| | | |
| | | |
| v | |
| DispatchMessage | |
| | | |
| | | |
| v TRUE | |
| PeekMessage------------------>+ |
| | |
| |FALSE |
| +-----------------------------+
|
v
(程序结束)
.......................................................... continued
-- 十年磨一剑,霜寒未曾试;
今日拔剑问,谁有不平事?
----老猫
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.234]
|
|