void RunMessageLoop() throw()
{
MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/*virtual int CWinApp::Run();可能是虚继承了模板类CAtlExeModuleT<T> 在该模板类中
有 T* pT=>PreMessageLoop(); pT->RunMessageLoop(); pt->PostMessageLoop();*/
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;
}
/////////////////////////////////////////////////////////////////////////////
// Official way to send message to a CWnd
LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
WPARAM wParam = 0, LPARAM lParam = 0)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
pThreadState->m_lastSentMsg.hwnd = hWnd;
pThreadState->m_lastSentMsg.message = nMsg;
pThreadState->m_lastSentMsg.wParam = wParam;
pThreadState->m_lastSentMsg.lParam = lParam;
#ifdef _DEBUG
_AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
#endif
// Catch exceptions thrown outside the scope of a callback
// in debug builds and warn the user.
LRESULT lResult;
TRY
{
#ifndef _AFX_NO_OCC_SUPPORT
// special case for WM_DESTROY
if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
pWnd->m_pCtrlCont->OnUIActivate(NULL);
#endif
// special case for WM_INITDIALOG
CRect rectOld;
DWORD dwStyle = 0;
if (nMsg == WM_INITDIALOG)
_AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
// delegate to object's WindowProc
lResult = pWnd->WindowProc(nMsg, wParam, lParam); //将返回传入窗口对象指针pWnd的窗口过程函数WindowProc()
// more special case for WM_INITDIALOG
if (nMsg == WM_INITDIALOG)
_AfxPostInitDialog(pWnd, rectOld, dwStyle);
}
CATCH_ALL(e)
{
lResult = AfxProcessWndProcException(e, &pThreadState->m_lastSentMsg);
TRACE(traceAppMsg, 0, "Warning: Uncaught exception in WindowProc (returning %ld).\n",
lResult);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
pThreadState->m_lastSentMsg = oldState;
return lResult;
}
////////////////////////////////////////////////////////////////////////////
// The WndProc for all CWnd's and derived classes
/*wincore.cpp全局域的AfxWndProc(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)函数返回传入窗口句柄hWnd
message消息对应的窗口过程函数,异常情况下调用
DefWindowProc(hWnd,nMsg,wParam,lParam)返回默认窗口
过程函数,正常情况下调用AfxCallWndProc(pWnd,hWnd,nMsg,
wParam,lParam)返回pWnd->WindowProc(nMsg,wParam,lParam)
即传入窗口的WindowProc()窗口过程函数*/
LRESULT CALLBACK
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
// special message which identifies the window as using AfxWndProc
if (nMsg == WM_QUERYAFXWNDPROC)
return 1;
// all other messages route through message map
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); //句柄转指针
ASSERT(pWnd != NULL);
ASSERT(pWnd==NULL || pWnd->m_hWnd == hWnd); //CWnd窗口类对象的内存可能被移动 所以存储有对象句柄m_hWnd
if (pWnd == NULL || pWnd->m_hWnd != hWnd)
return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}
////////////////////////////////
HRESULT PostMessageLoop() throw()
{
HRESULT hr = S_OK;
#ifndef _ATL_NO_COM_SUPPORT
T* pT = static_cast<T*>(this);
hr = pT->RevokeClassObjects();
if (m_bDelayShutdown)
Sleep(m_dwPause); //wait for any threads to finish
#endif // _ATL_NO_COM_SUPPORT
return hr;
}
void RunMessageLoop() throw()
{
MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
const MSG* PASCAL CWnd::GetCurrentMessage()
{
// fill in time and position when asked for
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
pThreadState->m_lastSentMsg.time = ::GetMessageTime();
pThreadState->m_lastSentMsg.pt = CPoint(::GetMessagePos());
return &pThreadState->m_lastSentMsg;
}
BOOL CWnd::PreTranslateMessage(MSG* pMsg)
{
// handle tooltip messages (some messages cancel, some may cause it to popup)
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
if (pModuleState->m_pfnFilterToolTipMessage != NULL)
(*pModuleState->m_pfnFilterToolTipMessage)(pMsg, this);
// no default processing
return FALSE;
}
//****************************************************
typedef struct tagMSG { //MSG消息结构体
HWND hwnd;
UINT message;
WPARAM wParam; //对WM_COMMAND消息 其WPARAM表示消息来自哪一个菜单项
LPARAM lParam;
DWORD time;
POINT pt;
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
// pointer to afx_msg member function
#ifndef AFX_MSG_CALL
#define AFX_MSG_CALL
#endif
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
/*所有能处理消息的类的父类CCmdTarget的成员函数指针
(从而可以被派生类继承并在派生类重定义)*/
struct AFX_MSGMAP_ENTRY //消息映射结构体
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT_PTR nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
#define PASCAL __stdcall //相当于递归地返回上一个基类的消息映射结构体数组指针
struct AFX_MSGMAP //由于包含有返回指向上一个基类的该AFX_MSGMAP结构体
{ //通常是上一个基类的&TheBaseClass::GetThisMessageMap
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)(); //返回指向AFX_MSGMAP结构体的指针的函数指针pfnGetBaseMap
const AFX_MSGMAP_ENTRY* lpEntries; //指向AFX_MSGMAP_ENTRY消息映射结构体(数组)的指针
};
#define DECLARE_MESSAGE_MAP() \
protected: \
static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
virtual const AFX_MSGMAP* GetMessageMap() const; \
//声明了两个成员函数 其中GetMessageMap()调用并返回GetThisMessageMap()的返回值 return GetThisMessageMap();
//*************************************************
#define PTM_WARNING_DISABLE \
__pragma(warning( push )) \
__pragma(warning( disable : 4867 ))
#define PTM_WARNING_RESTORE \
__pragma(warning( pop ))
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \ //该宏的两个参数分别是拥有此消息映射结构体数组的类及其父类
PTM_WARNING_DISABLE \ //用于链接本类与其上层类(派生类)的消息映射链
/*定义了接收消息的CCmdTarget派生类theClass的GetMessageMap()函数
调用GetThisMessageMap() 返回AFX_MSGMAP* */
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \ //该函数定义消息映射数组攒进并返回当前文件定义的AFX_MSGMAP结构体地址
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \ //构造消息映射结构体数组_messageEntries[]
{ /*定义为本类成员函数theClass::GetThisMessageMap()
中的static静态常数组 确保本类的所有对象当进入这里
查找消息响应函数时均面对的是同一个消息映射结构体
数组 即这里的静态消息映射结构体数组是属于本类的 所有
对象公用的*/
/*
#define WM_PAINT 0x000F
#define WM_SETFOCUS 0x0007
enum AfxSig
{
AfxSig_end = 0, // [marks end of message map]
AfxSig_v_v_v =19 , // void ()
AfxSig_vv = AfxSig_v_v_v, // void (void)
AfxSig_v_W_v=35, // void (CWnd*)
AfxSig_vW = AfxSig_v_W_v, // void (CWnd*)
}
// pointer to afx_msg member function
#ifndef AFX_MSG_CALL
#define AFX_MSG_CALL //占位符 没有替换文本 啥也不替换 相当于注释 为以后可能的作用埋藏下
#endif
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void); //AFX_PMSG CCmdTarget类的函数指针
typedef void (AFX_MSG_CALL CWnd::*AFX_PMSGW)(void); //AFX_PMSGW CWnd类的函数指针
// like 'AFX_PMSG' but for CWnd derived classes only
*/
/*能产生命令消息的用户界面对象有菜单项、工具栏项和快捷键 它们都有有可自定义的ID来标识
这里也用ID标识匹配响应函数*/
#define ON_COMMAND(id, memberFxn) \ //COMMAND命令消息映射宏需指定传入的菜单项ID|工具栏项ID 以及响应函数
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \ //(不重写基类已命名的响应函数)
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_WM_PAINT() \ //一个消息映射结构体 (不指定响应函数 说明要重写基类
{ WM_PAINT, 0, 0, 0, AfxSig_vv, \ //已命名的响应函数 这个消息映射宏(单纯地文本替换)可以指定自定义
(AFX_PMSG)(AFX_PMSGW) \ //函数名的响应函数并在其中调用基类已命名的同消息响应函数CWnd::OnPaint())
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > ( &ThisClass :: OnPaint)) },
#define ON_WM_SETFOCUS() \
{ WM_SETFOCUS, 0, 0, 0, AfxSig_vW, \ //一个消息映射结构体
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(CWnd*) > ( &ThisClass :: OnSetFocus)) },
// update ui's are listed as WM_COMMAND's so they get routed like commands
/*当点击某菜单项|工具栏按钮|快捷键后更新显示本身或其他用户界面对象(启用或禁用用户界面对象)*/
#define ON_UPDATE_COMMAND_UI(id, memberFxn) \
{ WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)id, AfxSigCmdUI, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \
(memberFxn)) },
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ //一个消息映射结构体 (AfxSig_end = 0)
}; \ //结束压栈消息映射结构体数组_messageEntries[]
static const AFX_MSGMAP messageMap = \ //构造AFX_MSGMAP结构体
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \ //返回当前文件定义的AFX_MSGMAP结构体地址 (AFX_MSGMAP*)
/*Windows消息只能由CWnd对象来处理 采用向基类直线上溯的方式查找消息对应的响应函数
一旦找到消息响应函数(若有返回值且为TRUE),就停止上溯。
返回基类CDialogEx的GetThisMessageMap()函数地址 是在theClass类的GetThisMessageMap()
函数体内消息映射数组_messageEntries[]中未找到该消息时前往基类CDialogEx的
GetThisMessageMap()函数体内消息映射数组_messageEntries[]继续寻找匹配传入消息
若仍未找到 则到CDialogEx的GetThisMessageMap()返回的基类CDialog::GetThisMessageMap()的
函数体内消息映射数组_messageEntries[]中继续寻找匹配传入消息
若仍未找到 则到CWnd的GetThisMessageMap()返回的基类CCmdTarget::GetThisMessageMap()的
函数体内消息映射数组_messageEntries[]中继续寻找匹配传入消息
若仍未找到 由于基类CObject已经没有声明有消息响应等函数和DECLARE_MESSAGE_MAP()宏
可能也就没有消息映射可寻了
*/
/*首元素是基类(CDialogEx)的GetThisMessageMap()函数地址、二元素是指向AFX_MSGMAP_ENTRY
消息映射结构体数组(就定义在GetThisMessageMap()函数里面) 的指针 相当于theClass的函数
GetThisMessageMap()返回了(其基类的GetThisMessageMap()函数地址,与在其函数域内定义的
消息映射结构体数组(栈内存?)的地址)共同构造的AFX_MSGMAP结构体(栈内存?)的地址
基类CDialogEx类的声明中也有DECLARE_MESSAGE_MAP()并且在此前声明了OnActivate()、
OnDestroy()等函数 那其实现文件肯定也声明有BEGIN_MESSAGE_MAP(CDialogEx,CDialog).....
的基类CDialog类的声明中也有DECLARE_MESSAGE_MAP()并且在此前声明了OnPaint()、
OnOK()等函数 那其实现文件肯定也声明有BEGIN_MESSAGE_MAP(CDialog,CWnd).....
的基类CWnd类的声明中也有DECLARE_MESSAGE_MAP()并且在此前声明了OnSetFocus()、
OnPaint()等函数 那其实现文件肯定也声明有BEGIN_MESSAGE_MAP(CWnd,CCmdTarget).....
的基类CCmdTarget类的声明中也有DECLARE_MESSAGE_MAP()但已经没有在此前声明消息响应等函数
.....
*/
} \ //theClass::GetThisMessageMap()函数结束
PTM_WARNING_RESTORE
//************************************************
MFC消息映射源码 解析
最新推荐文章于 2025-01-26 21:43:52 发布
4423

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



