定位事件处理程序

Posted

技术标签:

【中文标题】定位事件处理程序【英文标题】:Locating an Event Handler 【发布时间】:2012-08-09 03:28:40 【问题描述】:

我有一个非常大的 MFC 应用程序的源代码,但文档很差。我试图在代码执行时跟踪它,以了解它在做什么。不幸的是,一旦用户获得了对应用程序的控制权,我需要在事件处理程序上设置一个断点,以便在调试器中再次开始跟踪。如果我尝试逐行执行代码,那么用户将永远无法控制应用程序,因为它会开始逐步遍历空闲例程。

我需要在单击按钮之前确定与按钮关联的事件处理程序的名称。这样,我可以在该事件处理程序上设置一个断点,并在按下它后立即遍历相关代码。

由于应用程序的大小,在每个事件处理程序处手动设置断点是不可行的。如果有一种简单的方法可以在包含特定模式的所有行上设置断点,那么这也可以。我可以在 (alt+e+f+i) 中搜索 '::On' 并同时在数千个结果命中设置断点。我必须手动取消选择以这种方式无意触发的所有断点,但这仍然有效。有没有办法做到这一点?

此外,我尝试通过资源查看器进行搜索,并找到了一些看起来像我想要的按钮的东西,但一直找不到。即使我这样做了,我也不确定这会有什么帮助。难道不应该在某个地方有一个简单的列表,列出图形元素及其相关事件吗?

我还有哪些选择?

【问题讨论】:

【参考方案1】:

好的,我要做的第一件事就是您显然已经尝试过:在资源查看器中查找相关控件的资源 ID。如果您有该 ID,则可以在您的类声明中搜索它,其中将有 MFC 宏将“单击”事件映射到该控件的回调。回调当然是您要查找的事件处理程序。

所以,如果您无法用眼睛找到按钮,请搜索它。有一些合理的可能性:

    它在资源文件中,但您看不到它 - 可能它被其他按钮覆盖; 在应用程序中动态命名; 它是在应用程序中动态创建的。

在您的项目中搜索按钮上显示的文本 - 匹配大小写并尝试首先包含引号,如果不成功则不包含引号。您可能需要手动打开并搜索资源文件(关闭资源编辑器并将 RC 文件作为文本加载到 Visual Studio 中,然后搜索)。

如果它在资源文件中,您将能够将控件与 ID 匹配。如果根本找不到,请检查字符串表。如果它在字符串表中,则追溯该字符串资源的使用位置。

在动态命名和/或创建的情况下,您可能需要做更多的侦探工作。

这种方法可能发生的最糟糕的事情是按钮上的文本出现在整个项目中,或者按钮有一个图标而没有文本。如果你真的很苦恼,你可能会通过使用 Spy++ 来获取有关按钮的信息。您应该能够从中检索数字 ID,然后在 resource.h 中寻找它。

玩得开心!

【讨论】:

【参考方案2】:

假设您的应用程序是一个相当标准的 MFC 应用程序,几乎所有按钮点击都将通过消息映射处理,并且看起来像:

ON_BN_CLICKED( IDC_BUTTONID, OnMyButtonClicked )

将按钮 IDC_BUTTONID 的 BN_CLICKED 通知映射到方法 OnMyButtonClicked。

因此,查找事件处理程序的最简单方法是在源代码中搜索按钮的资源 ID(您应该在对话框编辑器或 .rc 文件中找到)。显然,如果您想更具体一点,可以进行正则表达式搜索,例如

ON_BN_CLICKED.*IDC_BUTTONID

该项目可能看起来像一个按钮但实际上不是一个按钮,或者它是通过 OnCmdMsg 手动路由的,在这种情况下,您最好寻找点击的症状(即您的一些代码)必须运行 KNOW)在此处设置中断,然后跟踪调用堆栈以查看消息是如何处理的。

对于广泛的源代码搜索,我建议查看专用的第 3 方搜索程序,例如 Agent Ransack 或 WinGrep。

【讨论】:

以上是关于定位事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

服务案例|基于IT事件管理,提升业务连续性

Vue事件处理

浅谈JavaScript的事件(事件处理程序)

深入理解DOM事件机制系列第二篇——事件处理程序

深入理解js Dom事件机制——添加事件处理程序

iOS用contenteditable滚动时,光标不会刷新定位的处理方法