2011-09-27 104 views
2

我想扩展一些无法使用插件或外部程序的功能。所以我必须编写自己的应用程序,从该外部应用程序的文本框中读取文本并触发一些自己的操作。从外部应用程序文本框中读取文本

通过在user32.dll中使用FindWindow API,我已经抓住了外部应用程序的句柄。但现在我有点卡住了。通过从Visual Studio工具中使用Spy ++,我得到了我想从中读取的控件的类名是“WindowsForms10.EDIT.app.0.218f99c”的信息,但其中有几个。此外,每次外部应用程序启动时,它都会为我想要阅读的文本框创建一个新的控件ID。

我该如何设法识别某个文本框并读取其值?任何人都可以给我提示或建议吗?

回答

3

在绊倒了几页之后,我发现解决方案如何从外部应用程序的文本框中检索内容。我觉得这个代码可能是有用的人太多,所以这里是结果:

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()。子试图找到请求的窗口。如果窗口被找到,它开始收集在这个应用程序中找到的所有控件。回调检查找到的控件是否符合我的规范(文本框)并将文本存储在数组列表中。之后你只需要知道你的requestet文本框的索引并将其从数组列表中取出即可。而已。希望这也能帮助其他人。

4

代码在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 ""; 
    } 
} 
相关问题