ShowWindow (hwnd, iCmdShow) ; //显示窗口
UpdateWindow (hwnd) ; //刷新窗口
GetMessage函数用于从消息队列中获取消息,DispatchMessage函数(在Windows USER模块的帮助下)则是将消息分派到相应的窗口函数进行处理。这是Windows编程中常见的一种机制,用于处理用户界面的交互和事件。
WM_QUIT是特定的消息类型,当接收到这个消息时,GetMessage会返回0并结束while循环,进而结束整个程序。
下图为Windows处理用户交互信息的过程:
使用者按下系统菜单中的Close命令 -> 系统送出WM_CLOSE消息 -> DefWindowProc处理调用DestroyWindow -> Destroy Window送出WM_DESTROY消息 -> 程序对WM_DESTROY的标准反应是调用PostQuitMessage送出WM_QUIT消息 -> 消息循环中的GetMessage取得,如步骤2,结束消息循环.
通过Windows SDK程序可以得出程序运行的最重要的两部分为WinMain(初始化操作)、WinProcedure(处理信息)
MFC中类的派生关系:CObject->CCmdTarget->CWinThread->CWinApp
MFC程序中WinMain函数的作用被CWinApp类取代了,它所负责的全部初始化工作和对消息解释及分派都有 CWinApp类的内部函数来完成,但是WinMain仍然存在,并且扮演着驾驭CWinApp的角色。CWinApp中几个最重要的函数如下:
virtual BOOL InitApplication();
virtual BOOL InitInstance();
virtual int Run();
在SDK程序设计中至关重要的主窗口句柄(就是那个hwnd,几乎程序所有有关窗口的操作都必须用到该句柄,它为Windows定位所要输出的信息 的目的窗口),它被存储在CWinThread中名为m_MainWnd的成员变量中,而CWinThread是CWinApp的父类。
WndProc窗口函数与WinMain一样被变形后由单独生成的类进行了替代,替代它的是名为CFrameWnd的类,该类一般因程序不同而被继承为不同的模样,比较有代表性的一般形态如下:
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWND();
afx_msg void OnPaint();
afx_msg boid OnAbout();
DECLARE_MESSAGE_MAP();
};
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)
{
...
CWinApp* pApp = AfxGetApp();
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance())
{...};
nReturnCode = pThread->Run();
}
重点为AfxWinInit函数调用、pApp->InitInstance(); nReturnCode=pApp->run();
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
...
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
{
// Windows specific initialization (not done if no CWinApp)
pApp->m_hInstance = hInstance;
pApp->m_hPrevInstance = hPrevInstance;
pApp->m_lpCmdLine = lpCmdLine;
pApp->m_nCmdShow = nCmdShow;
pApp->SetCurrentHandles();
}
}
BOOL CTestApp::InitInstance()
{
...
CMainFrame* pMainFrame = new CMainFrame;//调用了CMainFrame的构造函数
...
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOW); //这两行与SDK程序
m_pMainWnd->UpdateWindow(); //极为相似
}
int CWinThread::Run()
{
while (bIdle &&
!::PeekMessage(&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))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}
ASSERT(FALSE); // not reachable
}
PumpMessage代码如下:
BOOL CWinThread::PumpMessage()
{
ASSERT_VALID(this);
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{
return FALSE;
}
// process this message
if (m_msgCur.message != WM_KICKIDLE
&& !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);//SDK相似代码
::DispatchMessage(&m_msgCur);
}
return TRUE;
}
MFC程序死亡调用顺序与Win32程序大同小异。
文章主要参考:
http://blog.chinaunix.net/uid-21169302-id-446230.html