关于SoUI界面库处理从WM_LBUTTONUP到按钮事件的消息路由过程分析

SoUI界面库的介绍和使用方法可以查看启程软件的博客园:https://www.cnblogs.com/setoutsoft/。这里默认大家都对SoUI有一定的了解了。

现在SoUI界面库已经发展到SoUI3版本了,但是由于本人一直在使用的是SoUI2版本,所以今天分析的也是SoUI2版本的代码。

分析流程

首先我们创建一个SoUI的测试项目,在SoUI项目的创建向导中全部选择默认即可,然后在CMainDlg::OnClose()中打上断点,如下所示
在这里插入图片描述
然后运行程序,点击右上角的关闭按钮,查看VS中的调用堆栈,如下所示
在这里插入图片描述
从调用堆栈图我们可以大致看到函数的执行顺序,于是我们一个个地进行分析,首先从调用堆栈中的> souid.dll!SOUI::CSimpleWnd::WindowProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam) 行 110 C++这个函数开始吧,这里是直接跳转到CMainDlg的消息处理函数ProcessWindowMessage中,如下所示
在这里插入图片描述
然后我们查看调用堆栈中的> SouiWizard1.exe!CMainDlg::ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) 行 30 C++> SouiWizard1.exe!CMainDlg::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) 行 35 C++,发现这里只是在CMainDlg的消息映射表中查看是否需要处理当前的点击消息,即WM_LBUTTONUP,默认是没有处理的,所以可以去查看下一项。

接着是> souid.dll!SOUI::SHostWnd::ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) 行 338 C++> souid.dll!SOUI::SHostWnd::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) 行 351 C++,在这里呢我们可以发现,代码从CMainDlg的消息映表跳转到了SHostWnd的消息映射表中,由于呢MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)中处理了WM_LBUTTONUP的消息,所以流程进入了OnMouseEvent函数中。

> souid.dll!SOUI::SHostWnd::OnMouseEvent(unsigned int uMsg, unsigned int wParam, long lParam) 行 662 C++中可以看到流程进入了DoFrameEvent函数。

> souid.dll!SOUI::SwndContainerImpl::DoFrameEvent(unsigned int uMsg, unsigned int wParam, long lParam) 行 81 C++中可以看到流程进入了OnFrameMouseEvent函数中。

> souid.dll!SOUI::SwndContainerImpl::OnFrameMouseEvent(unsigned int uMsg, unsigned int wParam, long lParam) 行 286 C++中呢,我们可以看到,pCapture->SSendMessage(uMsg,wParam,lParam,&bMsgHandled);这句代表就代表了消息交由了被点击控件处理。

于是可以继续查看下去> souid.dll!SOUI::SWindow::SSendMessage(unsigned int Msg, unsigned int wParam, long lParam, int * pbMsgHandled) 行 222 C++> souid.dll!SOUI::SButton::ProcessSwndMessage(unsigned int uMsg, unsigned int wParam, long lParam, long & lResult) 行 264 C++> souid.dll!SOUI::SButton::ProcessSwndMessage(unsigned int uMsg, unsigned int wParam, long lParam, long & lResult) 行 264 C++中和前面的一样,先是ProcessSwndMessage(Msg, wParam, lParam, lResult);进入消息映射表,然后现在SButtonSWindow的消息映射表中寻找处理WM_LBUTTONUP的消息的宏。

然后就到了> souid.dll!SOUI::SWindow::OnLButtonUp(unsigned int nFlags, SOUI::CPoint pt) 行 1547 C++souid.dll!SOUI::SWindow::FireEvent(SOUI::EventArgs & evt) 行 1127 C++,在这里我们可以看到调用了FireEvent(evtLButtonUp);函数和FireEvent(evt)函数。

最后呢> souid.dll!SOUI::SWindow::FireEvent(SOUI::EventArgs & evt) 行 1127 C++中调用了GetContainer()->OnFireEvent(evt)> souid.dll!SOUI::SHostWnd::OnFireEvent(SOUI::EventArgs & evt) 行 709 C++中调用了_HandleEvent(&evt);> SouiWizard1.exe!CMainDlg::_HandleEvent(SOUI::EventArgs * pEvt) 行 23 C++中就到了CMainDlg的SoUI消息宏里面去调用了OnClose函数。

上述就是整个调用流程。

但是,在 > souid.dll!SOUI::SwndContainerImpl::OnFrameMouseEvent(unsigned int uMsg, unsigned int wParam, long lParam) 行 286 C++ 中,我们要注意一句代码SWindow *pCapture=SWindowMgr::GetWindow(m_hCapture),这句代码是获取当前鼠标点击的控件的指针,在这里没有看到如何通过坐标之类计算出来,而是直接通过m_hCapture获取的,这样就不合理了。

于是我们可以在void SwndContainerImpl::OnFrameMouseEvent(UINT uMsg,WPARAM wParam,LPARAM lParam)SWindow *pCapture=SWindowMgr::GetWindow(m_hCapture)那里打一个断点,然后重新运行程序查看调用流程。

首先呢,该断点触发了,此时应该是WM_LBUTTONDOWN消息(鼠标左击一次会产生两个消息,先是WM_LBUTTONDOWN,再是WM_LBUTTONUP),然后流程走到了m_hHover=SwndFromPoint(CPoint(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)),FALSE);中,这句代码的作用是根据坐标计算出坐标位置最上面的控件,然后跟前面一样,使用该控件的SSendMessage函数处理WM_LBUTTONDOWN消息。

于是我们在上述的SWindow的消息映射表中找到OnLButtonDown响应函数,代码如下
在这里插入图片描述
在上述函数中打一个断点,继续执行程序。

我们让程序停留在上面图片中的SetCapture();位置,这里是重点,进入该函数发现,这里呢调用了GetContainer()->OnSetSwndCapture(m_swnd);CSimpleWnd::SetCapture();
SwndContainerImpl::OnSetSwndCapture(swnd);,在SwndContainerImpl::OnSetSwndCapture(swnd);中我们可以看到程序保存了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值