使用 PInvoke 从 C# 获取工具提示文本

luv*_*ere 1 c# pinvoke tooltip sendmessage

我在 C# 中使用 PInvoke,尝试使用已知处理程序读取窗口中可见的工具提示,但是我尝试以这种方式检查的窗口应用程序因内存访问冲突错误而崩溃,或者根本不显示工具提示文本lpszText TOOLINFO 成员。

我正在使用回调调用EnumWindows,然后向该函数中的工具提示窗口发送一条消息:

public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);

static void Main(string[] args)
{
  callBackPtr = new CallBackPtr(Report);

  IntPtr hWnd = WindowFromPoint(<mouse coordinates point>);

  if (hWnd != IntPtr.Zero)
  {
        Console.Out.WriteLine("Window with handle " + hWnd +
                              " and class name " +
                              getWindowClassName(hWnd));

        EnumWindows(callBackPtr, hWnd);

        Console.Out.WriteLine();
  }


  public static bool Report(IntPtr hWnd, IntPtr lParam)
  {
        String windowClassName = getWindowClassName(hWnd);

        if (windowClassName.Contains("tool") &&
             GetParent(hWnd) == lParam)
        {
            string szToolText = new string(' ', 250);

            TOOLINFO ti = new TOOLINFO();
            ti.cbSize = Marshal.SizeOf(typeof(TOOLINFO));
            ti.hwnd = GetParent(hWnd);
            ti.uId = hWnd;
            ti.lpszText = szToolText;

            SendMessage(hWnd, TTM_GETTEXT, (IntPtr)250, ref ti);

            Console.WriteLine("Child window handle is " + hWnd + " and class name " + getWindowClassName(hWnd) + " and value " + ti.lpszText);
        }

        return true;
    }
Run Code Online (Sandbox Code Playgroud)

下面是我定义 TOOLINFO 结构的方式:

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    private int _Left;
    private int _Top;
    private int _Right;
    private int _Bottom;
}


struct TOOLINFO
{
    public int cbSize;
    public int uFlags;
    public IntPtr hwnd;
    public IntPtr uId;
    public RECT rect;
    public IntPtr hinst;

    [MarshalAs(UnmanagedType.LPTStr)]
    public string lpszText;

    public IntPtr lParam;
}
Run Code Online (Sandbox Code Playgroud)

TTM_GETTEXT 值

private static UInt32 WM_USER = 0x0400;
private static UInt32 TTM_GETTEXT = (WM_USER + 56);
Run Code Online (Sandbox Code Playgroud)

SendMessage重载

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref TOOLINFO lParam);
Run Code Online (Sandbox Code Playgroud)

那么,我的代码中是否遗漏了任何明显的错误,我应该更改什么才能解决这种情况?

编辑:是整个代码,所以你可以测试。

Ray*_*hen 5

您正在跨进程发送私人消息,这需要手动封送。这是关于同一主题的另一个 stackoverflow 问题。更好的是完全改变方向并使用专为此类事情设计的 Active Accessibility 和/或 UI 自动化。