2011-09-27 107 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 ""; 
    } 
} 
相關問題