21

我想获取 win32 旧版控件的工具提示文本(不是固有地支持UI 自动化的 WPF 控件)。

按钮的屏幕截图

我做了什么:

  • 给定一个感兴趣的按钮,我有它的AutomationElement, 和它的边界矩形
  • 我将鼠标移到这个按钮上(在代码中);
  • Thread.Sleep(1500)等待工具提示控件弹出;
  • 枚举Desktop的所有子窗口,得到子窗口tooltipAutomationElement,其类型为"Tooltip";
  • tooltipAutomationElement中,获取此工具提示的名称属性,该属性对应于工具提示字符串。

这实际上可行,但代价是:我必须sleep(1500)手动等待工具提示出现(要扫描 5-20 个按钮以查找工具提示字符串),这不符合性能要求。

预期什么(不确定是否可行)

  • 以编程方式获取按钮的工具提示字符串,而无需显示工具提示
  • 无需将鼠标一个一个地放在每个按钮上。

更新 1:对于TTN_NEEDTEXT,MSDN 文档似乎不是很清楚,我不知道如何使用 C# 进行编程。可以在此处找到与工具提示控件相关的低级结构/消息的相关链接之一。

更新 2:那些相信这可以通过 ... 来完成的人,我想说,说起来容易做起来难。我欢迎那些尝试过的人对此发表评论,如果您能提供一些证据来证明其适用性和有效性,也欢迎一些表面上可行的解决方案。

更新 3:如果我们尝试最小化以便TTM_SETDELAYTIME可以最小化,经过一些实验后这不起作用。我们只能在工具提示窗口句柄存在时进行调整。例如Nsleep(N)

SendMessage(_tooltipCtrl.Handle, TTM_SETDELAYTIME, _TTDT_INITIAL, 10); //10 ms

更新 4:使用TTM_GETTEXTA消息似乎是一个解决方案,但是,它类似于更新 3,我们需要的句柄,tooltipCtrl只有在创建工具提示后才可用,因为要创建此工具提示,我们别无选择将鼠标光标悬停在工具上方,这似乎存在如上所述的性能问题 ( Thread.Sleep)。

SendMessage(_tooltipCtrl.Handle, TTM_GETTEXTA, 0, ti);

更新 5:“如何获取工具提示文本”使用 InterOp (PInvoke) 或使用传统方法的自动化 UI(鼠标悬停在工具窗口上,找到 Hwnd 句柄,然后获取其文本......)不是这篇文章的关注点. 预期内容:我们可以在不需要悬停在控件上的情况下提取控件(比如按钮)的工具提示字符串吗?如果是,如何?

更新 6:使用 WM_MOUSEHOVER 激活工具提示窗口似乎不起作用,我已经使用 SendMessage(...) 进行了测试,并填充了正确的 wparam 和 lparam,但在静脉中。

4

3 回答 3

3

只是一个想法,但尝试使用消息而不是利用实际的鼠标。

与 WM_HOVER、WM_MOUSEHOVER、WM_MOUSEENTER 一起玩

 SendMessage(_buttonCtrl.Handle, WM_MOUSEHOVER, ..., ...)

等等

您的屏幕截图看起来像一个自定义控件,因此要弄清楚是什么触发了工具提示,这将是一个黑客问题。

潜在地,您可以同时发送多个 WM_MOUSEENTER 或 WM_MOUSEHOVER。这实际上取决于底层代码。

如果这导致了太长的延迟,(并且建议的解决方案都不起作用),请考虑将工具提示测试拉入一个执行频率较低或仅在特定请求时执行的辅助测试池。

另外...而且我确定您已经尝试过...但如果没有,请查看UI Spy并查看它是否在实际生成工具提示之前报告有关工具提示的任何信息。

于 2013-04-13T08:50:35.757 回答
1

从 UI 自动化的角度来看,我们可以做的最好的事情是订阅 ToolTip Opened Event,并且在事件处理程序过程中也是如此。此链接有一个示例http://msdn.microsoft.com/en-us/library/ms752286.aspx。UI 自动化事件列表可在此处找到http://msdn.microsoft.com/en-us/library/ms748252.aspx。可以在此处找到有关 AutomationElement.ToolTipOpenedEvent 的详细信息http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.tooltipopenedevent.aspx

至少使用 UI 自动化,我们应该让事情发生,无论是单击按钮还是打开窗口或显示工具提示。因此,订阅 ToolTip 事件会比硬 Sleep() 延迟具有更好的性能。否则,很少有人提到的 hacky 方式(尽管不是端到端)是预先获取工具提示字符串的资源字符串 ID,并在执行自动化测试期间验证资源字符串。

于 2013-04-13T08:36:47.330 回答
0

子类化工具提示的父级,即用你的替换按钮的windproc并过滤WM_NOTIFYfor TTN_GETDISPINFOcase,也许像这样..

case TTN_GETDISPINFO:
{
 // do this first
 NMTTDISPINFO pttdi = (LPNMTTDISPINFO)lparam;

 // next let the system do the default, ie fill the 
 //   relevant structures with the 
 // text that will appear on the tooltip. 
 // so

 CallWindowProc(OldListViewProc, hwnd, message, wparam, lparam);
 
 // then the text you seek will be in the 
 // NMTTDISPINFO pttdi structure. You can even alter 
 // the text to suit your needs if you want.     
}

显然,Visual Studio 2008 的 MSDN 库显示,对于 _WIN32_WINNT >= 0x0600,即在 Vista 之后,这个结构的额外成员 HBITMAP hbmp 有点隐藏,但代表“要显示的大型预览位图的句柄工具提示”。

于 2021-01-21T17:46:02.417 回答