需要做pc的自动化操作。
一个winform的软件,鼠标悬停到某个表格的单元格上,有个tooltip,我需要捕获那个tootip的文字信息。
如图“被引用文件中的问题”这样的字样。
https://learn.microsoft.com/zh-cn/dotnet/framework/ui-automation/ui-automation-support-for-the-tooltip-control-type
网上的资料很少,只有这一篇,也没好到解决方案。
谢谢!
引用new bing部分回答作答:
在 C# 的 UIAutomation 中,要获取 Tooltip 的文字信息,可以通过以下步骤:
1 首先使用 UIAutomation 查找到对应的表格单元格元素。可以使用 FindFirst() 或 FindAll() 方法,通过元素的 Name、AutomationId、ClassName、ControlType 等属性进行查找。例如:
var tableCell = window.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, "单元格名称"));
2 一旦找到了表格单元格元素,可以使用 GetUpdatedCacheRequest() 方法来获取当前 UIAutomation 缓存中的元素信息。例如:
var cacheRequest = new CacheRequest();
cacheRequest.Add(AutomationElement.NameProperty);
cacheRequest.Add(ValuePattern.ValueProperty);
cacheRequest.Add(ValuePattern.IsReadOnlyProperty);
cacheRequest.Add(ValuePattern.IsPasswordProperty);
cacheRequest.TreeScope = TreeScope.Element | TreeScope.Descendants;
cacheRequest.AutomationElementMode = AutomationElementMode.Full;
var cachedElement = Automation.Cached.GetUpdatedCacheRequest(cacheRequest).FindFirst(
TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "单元格名称"));
3 如果表格单元格上有 Tooltip,可以使用 AutomationElement.ToolTipOpenedEvent 和 AutomationElement.ToolTipClosedEvent 事件来检测 Tooltip 的打开和关闭。例如:
var tooltip = Automation.AddAutomationEventHandler(
AutomationElement.ToolTipOpenedEvent, tableCell, TreeScope.Element, (sender, e) =>
{
// 在此处获取 Tooltip 的信息
});
4 在 tooltip 事件处理程序中,可以使用 e.SourceElement 属性来获取打开 Tooltip 的元素。可以使用 GetUpdatedCacheRequest() 方法来获取 Tooltip 元素的缓存信息。例如:
var tooltipElement = e.SourceElement.GetUpdatedCacheRequest(cacheRequest);
var tooltipText = tooltipElement.GetCurrentPropertyValue(ValuePattern.ValueProperty) as string;
为了确保能够正确捕获 Tooltip 的信息,需要在代码中加入适当的延时或等待操作,以确保 Tooltip 已经完全打开并加载了其内容。
您可以尝试使用鼠标钩子(Mouse Hook)和控件提供的 MouseHover 事件来实现获取 Tooltip 文字信息的功能。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TooltipDemo
{
public partial class Form1 : Form
{
private IntPtr _tooltipHandle = IntPtr.Zero;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// 注册鼠标钩子
MouseHook.Start();
// 订阅 MouseHover 事件
dataGridView1.MouseHover += DataGridView1_MouseHover;
}
private void DataGridView1_MouseHover(object sender, EventArgs e)
{
if (_tooltipHandle != IntPtr.Zero)
{
// 获取 Tooltip 文字信息
string tooltipText = GetTooltipText(_tooltipHandle);
MessageBox.Show(tooltipText);
// 清空句柄
_tooltipHandle = IntPtr.Zero;
}
}
private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
// 获取单元格句柄
IntPtr cellHandle = GetCellHandle(e.ColumnIndex, e.RowIndex);
if (cellHandle != IntPtr.Zero)
{
// 获取 Tooltip 句柄
_tooltipHandle = GetTooltipHandle(cellHandle);
}
}
private IntPtr GetCellHandle(int columnIndex, int rowIndex)
{
// 获取单元格句柄
IntPtr handle = IntPtr.Zero;
if (dataGridView1[columnIndex, rowIndex].Displayed)
{
handle = dataGridView1[columnIndex, rowIndex].DataGridView.Handle;
handle = WinAPI.ChildWindowFromPointEx(handle, dataGridView1[columnIndex, rowIndex].ContentBounds.Left + 5,
dataGridView1[columnIndex, rowIndex].ContentBounds.Top + 5, WinAPI.CWP_SKIPINVISIBLE);
}
return handle;
}
private IntPtr GetTooltipHandle(IntPtr cellHandle)
{
// 获取 Tooltip 句柄
return WinAPI.SendMessage(cellHandle, WinAPI.TTM_GETTOOLINFOA, IntPtr.Zero, ref _tooltipInfo);
}
private string GetTooltipText(IntPtr tooltipHandle)
{
// 获取 Tooltip 文字信息
var buffer = new byte[256];
var tt = new WinAPI.TOOLINFO();
tt.cbSize = Marshal.SizeOf(tt);
tt.hwnd = dataGridView1.Handle;
var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(tt));
Marshal.StructureToPtr(tt, ptr, true);
try
{
var result = WinAPI.SendMessage(tooltipHandle, WinAPI.TTM_GETTEXTA, new IntPtr(255), ptr);
if (result != IntPtr.Zero)
{
tt = (WinAPI.TOOLINFO)Marshal.PtrToStructure(ptr, typeof(WinAPI.TOOLINFO));
Marshal.Copy(tt.lpszText, buffer, 0, 255);
}
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return System.Text.Encoding.Default.GetString(buffer).TrimEnd('\0');
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// 卸载鼠标钩子
MouseHook.Stop();
}
}
public static class MouseHook
{
private static IntPtr _hookId = IntPtr.Zero;
private static WinAPI.HookProc _hookProc = MouseHookProc;
public static void Start()
{
// 安装鼠标钩子
_hookId = WinAPI.SetWindowsHookEx(WinAPI.WH_MOUSE_LL, _hookProc, IntPtr.Zero, 0);
}
public static void Stop()
{
// 卸载鼠标钩子
WinAPI.UnhookWindowsHookEx(_hookId);
}
private static IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WinAPI.WM_MOUSEMOVE)
{
// 获取鼠标所在位置的句柄
var handle = WinAPI.WindowFromPoint(Cursor.Position);
// 检查句柄是否属于要处理的表格控件
if (handle != IntPtr.Zero && handle == MainForm.dataGridView1.Handle)
{
// 查询 Tooltip 是否显示
var tti = new WinAPI.TTTOOLINFO();
tti.cbSize = Marshal.SizeOf(tti);
tti.hwnd = MainForm.dataGridView1.Handle;
tti.uFlags = WinAPI.TTF_IDISHWND | WinAPI.TTF_SUBCLASS;
tti.uId = handle;
var tooltipHandle = WinAPI.SendMessage(MainForm._tooltipHandle, WinAPI.TTM_GETTOOLINFOA, IntPtr.Zero, ref tti);
if (tooltipHandle != IntPtr.Zero)
{
// 发送 WM_MOUSELEAVE 消息以关闭 Tooltip
WinAPI.SendMessage(tooltipHandle, WinAPI.WM_MOUSELEAVE, IntPtr.Zero, IntPtr.Zero);
}
}
}
return WinAPI.CallNextHookEx(_hookId, nCode, wParam, lParam);
}
}
public static class WinAPI
{
public const int WM_MOUSEMOVE = 0x200;
public const int WM_MOUSELEAVE = 0x2A3;
public const int WH_MOUSE_LL = 14;
public const int CWP_SKIPINVISIBLE = 0x0001;
public const int TTM_GETTOOLINFOA = 0x0400 + 13;
public const int TTM_GETTEXTA = 0x0400 + 45;
public const int TTF_IDISHWND = 0x0001;
public const int TTF_SUBCLASS = 0x0010;
[StructLayout(LayoutKind.Sequential)]
public struct TOOLINFO
{
public int cbSize;
public int uFlags;
public IntPtr hwnd;
public IntPtr uId;
public RECT rect;
public IntPtr hinst;
public IntPtr lpszText;
public IntPtr lParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref TOOLINFO lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr ChildWindowFromPointEx(IntPtr hWndParent, int x, int y, int uFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(System.Drawing.Point p);
}
}
在上述代码中,我们通过鼠标钩子(MouseHook)检测鼠标移动事件,并查询当前鼠标所在位置的句柄是否属于要处理的表格控件。如果 Tooltip 已经显示,则发送 WM_MOUSELEAVE 消息以关闭 Tooltip 并获取其文字信息。
注意,该代码仅提供基本思路,若有不懂的地方可以留言,看到了就会恢复哦
要自动化获取WinForm应用程序中的工具提示的文本信息,您可以使用UI自动化技术。
首先,您需要使用UI自动化API获取对表格单元格的UI元素的引用。然后,您可以使用UI元素的AutomationElement.ToolTipOpened事件来获取工具提示的UI元素。
一旦您有了工具提示的UI元素,您可以使用AutomationElement.Name属性获取工具提示中的文本信息。下面是一个示例代码片段,演示如何使用UI自动化获取工具提示的文本信息:
using System.Windows.Automation;
// 获取表格单元格的UI元素
AutomationElement cellElement = ...;
// 注册ToolTipOpened事件
Automation.AddAutomationEventHandler(
ToolTipOpenedEvent,
cellElement,
TreeScope.Element,
(sender, e) =>
{
// 获取工具提示的UI元素
AutomationElement tooltipElement = (AutomationElement)e.AutomationElement;
// 获取工具提示中的文本信息
string tooltipText = tooltipElement.Current.Name;
// 在控制台输出文本信息
Console.WriteLine("Tooltip text: " + tooltipText);
}
);
注意,您需要在UI自动化客户端应用程序中引用UI自动化API,以便使用Automation类和AutomationElement类。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
你可以使用 UI Automation API 的 Tooltip Control Type 来实现获取 tooltip 中的文本信息。以下是实现过程:
以下为示例代码:
using System.Windows.Automation;
// 获取被悬停控件的 AutomationElement 对象
AutomationElement element = AutomationElement.RootElement.FindFirst(
TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "目标控件名称"));
if (element != null)
{
// 获取该控件的 Tooltip Control Type.
AutomationElement tooltip = element.FindFirst(
TreeScope.Children,
new AndCondition(
new PropertyCondition(
AutomationElement.IsControlElementProperty, true),
new PropertyCondition(
AutomationElement.ControlTypeProperty,
ControlType.ToolTip)));
if (tooltip != null)
{
// 获取 tooltip 中的 Text 对应的 AutomationElement 对象.
AutomationElement text = tooltip.FindFirst(
TreeScope.Children,
new AndCondition(
new PropertyCondition(
AutomationElement.IsControlElementProperty, true),
new PropertyCondition(
AutomationElement.ControlTypeProperty,
ControlType.Text)));
if (text != null)
{
// 获取 tooltip 中的文本信息.
TextPattern pattern = text.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
string tooltipText = pattern.DocumentRange.GetText(-1);
// 输出 tooltip 信息.
Console.WriteLine(tooltipText);
}
}
}
注意:如果以上代码获取到的 tooltip 与目标控件之间存在深度结构,可能需要根据实际情况搭配 TreeScope 和 PropertyCondition 参数来搜索正确的 AutomationElement 对象。
希望以上信息对你有帮助!
如果我的回答解决了您的问题,请采纳!
您可以使用UIAutomation来捕获tooltip元素的信息。以下是捕获tooltip元素信息的示例代码:
AutomationElement element = //获取表格单元格元素
AutomationElement tooltip = null;
//获取tooltip元素
Condition condition = new PropertyCondition(AutomationElement.ClassNameProperty, "tooltips_class32");
AutomationElementCollection tooltips = element.FindAll(TreeScope.Descendants, condition);
if (tooltips.Count > 0)
{
tooltip = tooltips[0];
}
//获取tooltip文字信息
string tooltipText = tooltip.Current.Name;
首先,您需要获取表格单元格的AutomationElement对象。然后,使用ClassName为"tooltips_class32"的条件来查找tooltip元素。如果找到了tooltip元素,就可以获取它的Current.Name属性来获取文字信息。
请注意,这个示例代码只是一个参考,具体实现可能需要根据您的具体情况进行调整。