2016-08-18 1 views
0

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

код я использую:

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

    public static string GetText(IntPtr hwnd) 
    { 
     var text = new StringBuilder(1024); 

     if (SendMessageTimeoutText(hwnd, 0xd, 1024, text, 0x2, 5000, 0) != 0) 
     { 
      return text.ToString(); 
     } 

     MessageBox.Show(text.ToString()); 
     return ""; 
    } 
} 

Я называю этот код с помощью:

IntPtr MytestHandle = new IntPtr(0x00788600); 
HandleRef hrefHWndTarget = new HandleRef(null, MytestHandle); 

где 0x00788600 является примером одного из приложений, которые я бегу (я 100% уверен, что это главный дескриптор окна).

Мне нужно, чтобы текст из одного текстового поля внутри «другой» приложения, но когда я использую мой код он возвращает пустую строку каждый раз, когда

Предложения?

+0

Что именно все эти жестко закодированные магических чисел должны делать? Что заставляет вас думать, что номер, который вы используете как HWND, на самом деле является допустимым дескриптором окна? (Да, я читал * Я на 100% уверен *, но потому, что вы так говорите, не делает это правдой - что делает [IsWindow] (https://msdn.microsoft.com/en-us/library/windows/ desktop/ms633528 (v = vs.85) .aspx) say ?.) –

ответ

1

Я не вижу ошибок с кодом. Я предлагаю проверить правильность вашего дескриптора или нет.

Однако, чтобы получить текст TextBox, вам нужно будет использовать ручку фактического элемента управления. MainWindowHandle вернет только заголовок формы.

Я создал фиктивное приложение «WindowsFormsApplication1» с некоторыми элементами управления в ней и использовал следующий код, чтобы получить все тексты:

[Flags] 
internal enum SendMessageTimeoutFlags : uint 
{ 
    SMTO_NORMAL = 0x0, 
    SMTO_BLOCK = 0x1, 
    SMTO_ABORTIFHUNG = 0x2, 
    SMTO_NOTIMEOUTIFNOTHUNG = 0x8, 
    SMTO_ERRORONEXIT = 0x20 
} 

// Specific import for WM_GETTEXTLENGTH 
[DllImport("user32.dll", EntryPoint = "SendMessageTimeout", CharSet = CharSet.Auto)] 
internal static extern int SendMessageTimeout(
    IntPtr hwnd, 
    uint Msg,    // Use WM_GETTEXTLENGTH 
    int wParam, 
    int lParam, 
    SendMessageTimeoutFlags flags, 
    uint uTimeout, 
    out int lpdwResult); 

// Specific import for WM_GETTEXT 
[DllImport("user32.dll", EntryPoint = "SendMessageTimeout", SetLastError = true, CharSet = CharSet.Auto)] 
internal static extern uint SendMessageTimeoutText(
    IntPtr hWnd, 
    uint Msg,    // Use WM_GETTEXT 
    int countOfChars, 
    StringBuilder text, 
    SendMessageTimeoutFlags flags, 
    uint uTImeoutj, 
    out IntPtr result); 

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

// callback to enumerate child windows 
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr parameter); 

private static bool EnumChildWindowsCallback(IntPtr handle, IntPtr pointer) 
{ 
    // this method will be called foreach child window 
    // create a GCHandle from pointer 
    var gcHandle = GCHandle.FromIntPtr(pointer); 

    // cast pointer as list 
    var list = gcHandle.Target as List<IntPtr>; 

    if (list == null) 
     throw new InvalidCastException("Invalid cast of GCHandle as List<IntPtr>"); 

    // Adds the handle to the list. 
    list.Add(handle); 

    return true; 
} 

private static IEnumerable<IntPtr> GetChildWindows(IntPtr parent) 
{ 
    // Create list to store child window handles. 
    var result = new List<IntPtr>(); 

    // Allocate list handle to pass to EnumChildWindows. 
    var listHandle = GCHandle.Alloc(result); 

    try 
    { 
     // enumerates though the children 
     EnumChildWindows(parent, EnumChildWindowsCallback, GCHandle.ToIntPtr(listHandle)); 
    } 
    finally 
    { 
     // free unmanaged list handle 
     if (listHandle.IsAllocated) 
      listHandle.Free(); 
    } 

    return result; 
} 

internal static string GetText(IntPtr hwnd) 
{ 
    const uint WM_GETTEXTLENGTH = 0x000E; 
    const uint WM_GETTEXT = 0x000D; 
    int length; 
    IntPtr p; 

    var result = SendMessageTimeout(hwnd, WM_GETTEXTLENGTH, 0, 0, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5, out length); 

    if (result != 1 || length <= 0) 
     return string.Empty; 

    var sb = new StringBuilder(length + 1); 

    return SendMessageTimeoutText(hwnd, WM_GETTEXT, sb.Capacity, sb, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5, out p) != 0 ? 
      sb.ToString() : 
      string.Empty; 
} 

public static void Main(string[] args) 
{ 
    var p = Process.GetProcessesByName("WindowsFormsApplication1").First();    

    Console.WriteLine(GetText(p.MainWindowHandle)); // main window handle of form, returns "Form1" 
    Console.WriteLine(GetText(new IntPtr(0x70BA0))); // actual textbox handle, used Winspector, returns "quertz" 

    // iterate through dynamic handles of children 
    foreach (var hwnd in GetChildWindows(p.MainWindowHandle)) 
     Console.WriteLine($"{hwnd}:{GetText(hwnd)}"); 

    Console.ReadLine(); 
}  
+0

Вы AAAA-AMAZING! Большое вам спасибо, после того, как мы с Winspector (который вы написали в комментарии) жонглировали, он получил все, чтобы работать! Огромное спасибо :) – Merlijn