Чтение текста из текстового поля внешнего приложения - PullRequest
2 голосов
/ 27 сентября 2011

Я пытаюсь расширить некоторые функции внешней программы, которая не может использовать плагины или что-то еще.Поэтому я должен написать свое собственное приложение, которое читает текст из текстового поля из этого внешнего приложения и запускает некоторые собственные действия.

Используя API FindWindow в user32.dll, я уже догнал дескриптор для внешнего приложения.,Но сейчас я застрял.Используя Spy ++ из Visual Studio Tools, я получил информацию о том, что имя класса из элемента управления, из которого я хотел бы прочитать, - «WindowsForms10.EDIT.app.0.218f99c», но их несколько.Кроме того, каждый раз, когда внешнее приложение запускается, оно создает новый идентификатор элемента управления для текстового поля, которое я хочу прочитать.

Как мне заставить его идентифицировать определенное текстовое поле и прочитать его значение?Кто-нибудь может дать мне подсказку или совет?

Ответы [ 2 ]

4 голосов
/ 04 января 2012

код в C #

public static class ModApi
{
    [DllImport("user32.dll", EntryPoint = "FindWindowA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

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

    [DllImport("user32.dll", EntryPoint = "SendMessageTimeout", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern uint SendMessageTimeoutText(IntPtr hWnd, int Msg, int countOfChars, StringBuilder text, uint flags, uint uTImeoutj, uint result);

    [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    static internal extern bool EnumChildWindows(IntPtr hWndParent, funcCallBackChild funcCallBack, IntPtr lParam);

    public delegate bool funcCallBackChild(IntPtr hWnd, IntPtr lParam);


    public static ArrayList TextBoxStrings = new ArrayList();
    public static void ParseWindowControls(string WindowTitle)
    {
        IntPtr hWnd = FindWindow(null, WindowTitle);
        TextBoxStrings.Clear();


        funcCallBackChild MyCallBack = EnumChildWindowsProc;
        EnumChildWindows(hWnd, MyCallBack, IntPtr.Zero);
    }

    private static bool EnumChildWindowsProc(IntPtr hWndParent, IntPtr lParam)
    {
        var buffer = new StringBuilder(256);
        long Retval = GetClassName(hWndParent, buffer, buffer.Capacity);
        if (buffer.ToString() == "Edit" || buffer.ToString() == "Static")
        {
            TextBoxStrings.Add(GetText(hWndParent));
        }

        return true;
    }

    private static string GetText(IntPtr hwnd)
    {
        var text = new StringBuilder(1024);
        if (SendMessageTimeoutText(hwnd, 0xd, 1024, text, 0x2, 1000, 0) != 0)
        {
            return text.ToString();
        }

        return "";
    }
}
3 голосов
/ 27 сентября 2011

Пройдя несколько страниц, я нашел решение, как извлечь содержимое из текстового поля из внешнего приложения.Я думаю, что этот код может быть полезен и для других, так что вот результат:

Module modApi

    Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    Private Declare Function SendMessageTimeoutString Lib "user32.dll" Alias "SendMessageTimeoutA" (ByVal hwnd As IntPtr, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As String, ByVal fuFlags As Long, ByVal uTimeout As Long, ByVal lpdwResult As Long) As Long
    Friend Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal funcCallBack As funcCallBackChild, ByVal lParam As IntPtr) As Boolean

    Public Delegate Function funcCallBackChild(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean

    Public TextBoxStrings As ArrayList = New ArrayList

    Public Sub ParseWindowControls(ByVal WindowTitle As String)
        Dim hWnd As IntPtr = FindWindow(vbNullString, WindowTitle)
        TextBoxStrings.Clear()
        If hWnd Then
            Dim MyCallBack As New funcCallBackChild(AddressOf EnumChildWindowsProc)
            EnumChildWindows(hWnd, MyCallBack, IntPtr.Zero)
        Else
            MsgBox("Could not find window!", vbOKOnly + vbExclamation, "Error")
        End If
    End Sub

    Private Function EnumChildWindowsProc(ByVal hWndParent As IntPtr, ByVal lParam As IntPtr) As Boolean
        Dim Buffer As String = Space(256)
        Dim Retval As Long = GetClassName(hWndParent, Buffer, Len(Buffer))
        If Left(Buffer, Retval) = "WindowsForms10.EDIT.app.0.218f99c" Then
            TextBoxStrings.Add(GetText(hWndParent))
        End If
        EnumChildWindowsProc = True
    End Function

    Private Function GetText(ByVal hwnd As IntPtr) As String
        Dim sText As String = Space(1024)
        If SendMessageTimeoutString(hwnd, &HD, 1024, sText, &H2, 1000, 0) <> 0 Then
            GetText = Left(sText, InStr(sText, vbNullChar) - 1)
            Exit Function
        End If
        GetText = ""
    End Function

End Module

Вы можете передать заголовок окна подпрограмме ParseWindowControls().Подпрограмма пытается найти запрошенное окно.Если окно найдено, оно начинает собирать все элементы управления, найденные в этом приложении.Обратный вызов проверяет найденный элемент управления на соответствие моим спецификациям (текстовое поле) и сохраняет текст в массиве списков.Позже вам просто нужно узнать индекс вашего текстового поля requesttet и вытащить его из массива.Вот и все.Надеюсь, это поможет и другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...