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);中我们可以看到程序保存了处理WM_LBUTTONDOWN的控件的句柄,如下所示:

我们于是点击F5让程序继续运行,这时的SWindow *pCapture=SWindowMgr::GetWindow(m_hCapture);会再次触发,返回了有效的对象指针了,于是该对象就去处理了WM_LBUTTONUP消息。

在对象的WM_LBUTTONUP消息响应函数OnLButtonUp中我们也可以看到,在执行FireCommand函数前,代码先执行了ReleaseCapture函数,在ReleaseCapture函数中将上述m_hCapture保存的句柄清空了,代码如下

清空之后程序就可以继续处理下一次的点击消息了。

程序代码执行流程图如下

Created with Raphaël 2.2.0CSimpleWnd::WindowProcSOUI::CSimpleWnd::WindowProcCMainDlg::ProcessWindowMessageCMainDlg::_ProcessWindowMessageSOUI::SHostWnd::ProcessWindowMessageSOUI::SHostWnd::_ProcessWindowMessageSOUI::SHostWnd::OnMouseEventSOUI::SwndContainerImpl::DoFrameEventSOUI::SwndContainerImpl::OnFrameMouseEventSOUI::SWindow::SSendMessageSOUI::SButton::ProcessSwndMessageSOUI::SWindow::ProcessSwndMessageSOUI::SWindow::OnLButtonUpSOUI::SWindow::FireEventSOUI::SHostWnd::OnFireEventCMainDlg::_HandleEventCMainDlg::OnClose

以上就是本博客的全文,本人限于能力,上文中难免有错误的地方,若读者发现上文的错误,请于评论区中指出,本人看到之后会立即修改的,谢谢。

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

  1. SOUI界面库 第1讲-开发环境搭建

    本套视频教程由"界面工厂"和"SOUI"共同整理出品. 转载请注明"界面工厂". 感谢一直以来大家对我的支持,使我才能继续更新这些教程.没有 ...

  2. android lib 界面库,全开源C++ DirectUI 界面库SOUI 3.0更新

    全开源C++ DirectUI 界面库SOUI 3.0更新 发布时间:2019-08-04 16:10, 浏览次数:1077 , 标签: DirectUI SOUI 从2019.5.22开始,SOUI ...

  3. Duilib界面库学习笔记

    1.Duilib的下载编译 由于一些事件google无法访问,托管在其上的项目也无法检出也基本无人更新,因此从第三方代码仓库同步下载代码, 地址如下: 1.https://github.com/Cod ...

  4. 以金山界面库(openkui)为例思考和分析界面库的设计和实现——代码结构(完)

    三年前,准备将金山界面库做一个全面的剖析.后来由于种种原因,这个系列被中断而一直没有更新.时过境迁,现在在windows上从事开发的人员越来越少,关注这块的技术的朋友也很少了.本以为这系列也随着技术的 ...

  5. 以金山界面库(openkui)为例思考和分析界面库的设计和实现——资源读取模块分析

    按照软件的执行流程,我们首先遇到<以金山界面库(openkui)为例思考和分析界面库的设计和实现--问题>中提出的最后一个问题:界面描述文件的放置位置.我们曾提出一种方案:将界面描述文件打 ...

  6. 以金山界面库(openkui)为例思考和分析界面库的设计和实现——问题

    随着物质生活的丰富,人们的精神生活也越来越丰富.人们闲暇的时间也相对变多,于是很多人就开始寻找打发时间的方法.其中电视便是其中一种非常重要的消遣方式.假如我们打开电视机,看到了一个电视台正在播一部我们 ...

  7. 嵌入式python 图形界面_有哪些好的嵌入式操作系统界面库(GUI library)?

    20190809上面答案没提到的,个人认为好用的 1.LittlevGL LittlevGL 是一个开源免费(MIT许可)的GUI,支持触摸屏操作,移植简单方便,开发者一直在不断完善更新.Little ...

  8. VC界面库BCGControlBar和Xtreme Toolkit详细对比评测

    概述:如今对软件界面的要求越来越高,如用Delphi.VS2008等开发底层的应用程序时,效率远不如VC++.虽然Visual Studio集成了一些MFC的类库,但是这些只是基础应用,并不能满足大多 ...

  9. 炫彩界面库使用方法问题记录

    1. 'ele_event' : undeclared identifier  'RegisterAll': identifier not found 在使用炫彩界面库时,如果遇到以上错误,一般是由于 ...

  10. 一些界面库比较以及如何选择界面库

    记得很早的时候看了一个哥们写的界面库的使用历程,当时还挺有感触的,不断地尝试,不断地被坑,最后有两条结论: 1.自己积累界面库: 2.买就买贵的.好的,并且提前根据自己需要协商好. 今天又重看关于界面 ...

最新文章

  1. Ubuntu 15.10安装ns2.35+nam
  2. 34 JavaScript中的构造函数和原型
  3. OpenCV学习笔记大集锦
  4. 当深度学习遇上量化交易——公开信息篇
  5. java-DBUtils的练习题
  6. Linux使用信号量监控程序异常退出
  7. 计算机基础cpu知识,CPU基础知识大全详解
  8. 对抗机器学习——Min Max模型(Towards Deep Learning Models Resistant to Adversarial Attacks)
  9. python二元一次方程组用鸡兔同笼的思路来写编程_二元一次方程组应用 —鸡兔同笼...
  10. am调制解调仿真matlab,AM调制与解调仿真matlab
  11. 数字通信之数字信号基带传输(九)
  12. 手把手教你写专利申请书/如何申请专利
  13. CCF-CSP 201912-1 报数(python实现)
  14. 原生JS制作自动+手动轮播图,附带二级分类菜单
  15. 百度网盘怎么批量转存到阿里云盘
  16. Three.js-灯光与阴影
  17. CheckBox的使用
  18. 安利几个翻译照片的好用软件
  19. 如果结束进程拒绝访问,可以尝试以下
  20. 【vue】滴滴cube-ui 简化安装

热门文章

  1. 博弈论的经典入门课程和资料
  2. 《组合数学引论》第一章部分习题解答
  3. Ae:时间轴面板(时间线区域)
  4. 显控触摸屏编程手册_深圳显控AKWORKSHOP触摸屏与ALLENBRADLEY通讯手册.pdf
  5. 专利技术交底书撰写经历
  6. Python3中的md5加密
  7. CrossApp环境搭建
  8. java 授课录像_讲课视频录制方法,录制上课录像详细步骤
  9. html css 鼠标手势,CSS设置鼠标手势:cursor属性说明
  10. Python——银行管理系统