[转载自:《深入浅出MFC 第2版 侯俊杰》]
1、消息映射被CWnd窗口类对象查找的前奏过程:
MFC2.5(确认VS2010的MFC4.x同)的virtual int CWinApp::Run(),查找定义到atlbase.h的:
namespace ATL
{
template <class T>
class ATL_NO_VTABLE CAtlExeModuleT :
public CAtlModuleT <T>
{
...
int WinMain(_In_ int nShowCmd) throw()
{
T* pT = static_case<T*>(this);
HRESULT hr = S_OK;
...
hr = pT->Run(nShowCmd);
...
}
...
HRESULT Run(_In_ int nShowCmd = SW_HIDE) throw()
{
HRESULT hr = S_OK;
T* pT = static_cast<T*>(this);
hr = pT->PreMessageLoop(nShowCmd);
// Call RunMessageLoop only if PreMessageLoop returns S_OK.
if (hr == S_OK)
{
pT->RunMessageLoop();
}
// Call PostMessageLoop if PreMessageLoop returns success.
if (SUCCEEDED(hr))
{
hr = pT->PostMessageLoop();
}
ATLASSERT(SUCCEEDED(hr));
return hr;
}
...
void RunMessageLoop() throw()
{
MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
....
}
...
}
//继续查找定义全局域的DispatchMessage(MSG*)到WinUser.h中已经没有了源码:
#if defined(_M_CEE)
#undef DispatchMessage
__inline
LRESULT
DispatchMessage(
CONST MSG *lpMsg
)
{
#ifdef UNICODE
return DispatchMessageW(
#else
return DispatchMessageA(
#endif
lpMsg
);
}
#endif /* _M_CEE */
//以下来自docs.microsoft.com

即:WinUser.h文件全局域的DispatchMessage(MSG* pMsg)函数分发一个消息到一个窗口过程window procedure,通常用于分发一个GetMessage()函数检索到的消息。
其返回值是窗口过程window procedure返回值,尽管返回值的意义取决于被分发的消息,返回值通常被忽略。
备注:传入参数MSG结构体必须包含有效的消息值,如果lpmsg参数指向一个WM_TIMER消息并且该WM_TIMER消息的lParam参数不是NULL,此时lParam是指向被调用的函数而不是窗口过程window procedure。
注意到应用程序CWinApp有责任检索retrieve并分发dispatch输入的消息到对话框dialog box。大多数应用程序为此使用主消息循环 main message loop。然而,为了允许用户通过使用键盘来移动并且选择控件,应用程序必须调用IsDialogMessage()。详见对话框键盘接口添加链接描述
本文深入探讨了MFC2.5版本中CWinApp::Run()函数的消息映射机制,详细分析了从虚拟函数查找、消息循环、消息分发到窗口过程的全过程。特别关注了ATL模块类CAtlExeModuleT的实现细节,以及DispatchMessage(MSG*)函数在WinUser.h中的定义和作用。
903

被折叠的 条评论
为什么被折叠?



