4 / 18
b. 在函数入口处设置条件断点[[esp+4]+4]==202,即可设置鼠标左键释放断点。
说明:此函数的入口参数为:MSG* pMsg,在入口处时,[esp]是函数返回地址,所以:
[esp+4]就是 pMsg,而[[esp+4]]就是 pMsg->hWnd , [[esp+4]+4]就是 pMsg->Message
c. [[esp+4]]==002407B4 && [[esp+4]+4]==202 可以为指定按钮设置点击断点。这里 002407B4 是目标按钮的句柄.
3. CWnd::WalkPreTranslateTree 函数
CWnd::WalkPreTranslateTree()的所使用的策略很简单,拥有该消息窗口最先获得该消息的处理权,如果它不想对该消
息进行处理(该窗口对象的 PreTranslateMessage()函数返回 FALSE),就将处理权交给它的父亲窗口,如此向树的根部遍历,
直到遇到 hWndStop(在 CWinThread::PreTranslateMessage()中,hWndStop 表示的是线程主窗口的句柄)。
记住这个消息处理权的传递方向,是由树的某个一般节点或叶子节点向树的根部传递!
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{ for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) //从当前窗口到父窗口,逐层往上
{ CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{ // target window is a C++ window
if (pWnd->PreTranslateMessage(pMsg)) return TRUE; //消息被某一窗口处理了,返回
}
if (hWnd == hWndStop) break; // got to hWndStop window without interest
}
return FALSE; // no special processing
}
正是这个 if (pWnd->PreTranslateMessage(pMsg)) return TRUE; 才实现了 MFC 灵活的消息分发处理机制。MFC 程
序各个窗口类中重载的 PreTranslateMessage 虚函数,都是从这里进来的。
MFC 从当前消息窗口类逐级向上搜索执行各个类的 PreTranslateMessage 函数,只要有一个 PreTranslateMessage 函数
返回 TRUE,WalkPreTranslateTree 就中止搜索,并返回 TRUE,否则返回 FALSE。
在 PumpMessage 函数中最终就是根据 WalkPreTranslateTree 函数返回值决定是否要进行下一步的 Tanslate 和 Dispatch。
WalkPreTranslateTree 函数反汇编代码如下:
73D31389 MOV EDI,EDI ; D1.0040308C
73D3138B PUSH ESI
73D3138C PUSH EDI
73D3138D MOV EDI,DWORD PTR SS:[ESP+10]
73D31391 MOV ESI,DWORD PTR DS:[EDI]
73D31393 JMP SHORT MFC42.73D313BD
73D31395 /PUSH ESI
73D31396 |CALL MFC42.#2867_?FromHandlePermanent@CWnd@@SGPAV> ;取得 CWnd 指针值
73D3139B |TEST EAX,EAX ;CWnd * 值不为 NULL 时,则调用 CWnd::PreTranslateMessage()
73D3139D |JE SHORT MFC42.73D313AE
73D3139F |MOV EDX,DWORD PTR DS:[EAX]
73D313A1 |PUSH EDI
73D313A2 |MOV ECX,EAX
73D313A4 |CALL DWORD PTR DS:[EDX+98] ;<JMP.&MFC42.#5280_?PreTranslateMessage > ;通过虚函数方式调用
73D313AA |TEST EAX,EAX
73D313AC |JNZ SHORT MFC42.73D313C8 ;消息被处理了,返回 TRUE
73D313AE |CMP ESI,DWORD PTR SS:[ESP+C]
评论0
最新资源