GETTEXT返回空值(Class-TSortGrid)

时间:2017-08-06 06:43:19

标签: c# winforms pinvoke autoit

我一直在尝试获取gridview的文本。我使用自动工具来获取视图的实例和类https://i.stack.imgur.com/oyev3.png

我以前用来获取TsortGrid实例的代码如下

      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Globalization;
      using System.Linq;
      using System.Runtime.InteropServices;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;

    namespace ConsoleApplication3
 {
class Program
{

    private static ArrayList GetAllWindows()
    {
        var windowHandles = new ArrayList();
        EnumedWindow callBackPtr = GetWindowHandle;
        EnumWindows(callBackPtr, windowHandles);

        foreach (IntPtr windowHandle in windowHandles.ToArray())
        {
            EnumChildWindows(windowHandle, callBackPtr, windowHandles);
        }

        return windowHandles;
    }

    private delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr window, EnumedWindow callback, ArrayList lParam);

    private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
    {
        windowHandles.Add(windowHandle);
        return true;
    }

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

    /// <summary>
    /// Returns a list of child windows
    /// </summary>
    /// <param name="parent">Parent of the windows to return</param>
    /// <returns>List of child windows</returns>
    public static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    /// <summary>
    /// Callback method to be used when enumerating windows.
    /// </summary>
    /// <param name="handle">Handle of the next window</param>
    /// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
    /// <returns>True to continue the enumeration, false to bail</returns>
    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        //  You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }

    /// <summary>
    /// Delegate for the EnumChildWindows method
    /// </summary>
    /// <param name="hWnd">Window handle</param>
    /// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
    /// <returns>True to continue enumerating, false to bail.</returns>
    public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
          public static string isIEServerWindow(IntPtr hWnd)
    {
        int nRet;
        // Pre-allocate 256 characters, since this is the maximum class name length.
        StringBuilder ClassName = new StringBuilder(256);
        //Get the window class name
        nRet = GetClassName(hWnd, ClassName, ClassName.Capacity);
        if (nRet != 0)
        {
            if (ClassName.ToString() == "TSortGrid")
            {
                GetWindowText(hWnd);
                Console.WriteLine(ClassName + " - " + hWnd);
            }

            return ClassName.ToString();
        }
        else
        {
            return "";
        }
        return "";
    }


    static void Main(string[] args)
    {

       isIEServerWindow(new IntPtr(394872));


       ArrayList test=  GetAllWindows();
       foreach (IntPtr tesst in test)
       {
           isIEServerWindow(tesst);

       }
      //  GetChildWindows(new IntPtr(394872));
    }
}

}

这里我能够获取tsortgrid和hwnd的实例,但是当我试图获取内容(不是标题或长度,但文本行和列名称以及原因列的单元格内容)时,它返回我的空值。我用这段代码来获取syslistview32文本

    public static object GetWindowText(IntPtr hWnd)
    {
        string StrData = "";
        object obj2 = "";
        if (hWnd.Equals(IntPtr.Zero))
        {
            return "";
        }
        SendMessage(hWnd, 0x111, (IntPtr)0x81eb, IntPtr.Zero);
        StrData = StrData + Clipboard.GetText();
        SendMessage(hWnd, 0x307, IntPtr.Zero, IntPtr.Zero);
        return obj2;
    }

但是这段代码没有检索到TSortGrid的文本。你能告诉我我哪里出错吗?提前致谢

1 个答案:

答案 0 :(得分:2)

此控件是Delphi控件,不提供自动化功能。它不会响应那些窗口消息,并且它不会通过UI自动化提供任何内容。

您的选择包括:

  • 屏幕抓取和OCR。
  • 将Delphi代码注入外部进程以本机读取控件内容。
  • 反向设计控件的数据结构并使用ReadProcessMemory读取内容。

这些都不是很有吸引力。