从其他窗口控制名称

时间:2012-10-07 10:02:38

标签: sendmessage spy++ findwindow getwindowlong

我需要从其他窗口读取文本值并将该值查询到另一个应用程序(我的问题将围绕第一个任务)...所以, 我正在“监视”其他窗口(我们使用的第三方应用程序与我们的产品相关)并等待“接受”按钮被单击以从文本框中读取值。另一个应用程序,即对话框,有多个文本框和命令按钮。 我做了一个鼠标钩子,我在这个应用程序外观上激活它。我正在阅读这个窗口矩形内的所有鼠标移动;文本,标题,子窗口ID,矩形,抓住左/右/中/轮点击。我可以点击“接受”按钮;我可以看到按钮标题,我可以阅读该窗口,获取文本并确定点击了什么按钮等。现在...... 我可以读取所有EDIT类值,获取它们的窗口句柄,矩形等,但我不能将它们识别为类集合中的唯一项目:我需要专门读取我想要的文本框值。幸运的是,当我从EDIT类循环中读取文本时,我感兴趣的文本框总是首先出现在我的循环中。但是我想更具体一点;确保我正在阅读带有NAME的文本框。我知道。在开发过程中,我可以阅读NAME并在程序中对其进行硬编码。我怀疑控件名称是不是保存在二进制代码中。我的理解是控件ID,窗口句柄是在创建窗口时创建的,并且绝对没有引用控件名称(例如:txtOrderNumber)。如果按钮我可以是特定的,因为按钮标题(所以,我可以确定点击了什么按钮)我用EDIT类项目锁定,并在读取值时抛出幸运的第一个猜测。 我的问题是: 如何从另一个窗口获取控件名称,对于此任务,我有兴趣了解EDIT类实例名称。 以下是项目中的一些代码(缩写):

Dim hWnd As IntPtr = FindWindow(Nothing,_windowText)

'API:FindWindowEx 'API:SendMessage 'API:GetClassName 'API:GetWindowTextLength 'API:GetWindowText 'API:WM_GETTEXT

Public Shared Function GetClassValues(_controlClass As String, _hWindow As IntPtr) As List(Of String)

    Dim cl As New List(Of String)

    'First control handle in that class
    Dim hc As IntPtr = FindWindowEx(_hWindow, IntPtr.Zero, _controlClass, vbNullString)
    Do
        Dim sv As String = GetWindowValue(hc)
        cl.Add(sv)

        'Next control (after hc) handle
        hc = FindWindowEx(_hWindow, hc, _controlClass, vbNullString)
    Loop Until hc = 0
    Return cl
End Function
Public Shared Function GetWindowValue(_hWindow As IntPtr) As String
    If _hWindow = IntPtr.Zero Then Return String.Empty
    Dim sz As Integer = 256
    Dim bf As IntPtr = Marshal.AllocHGlobal(sz)
    Dim pt As IntPtr = SendMessage(_hWindow, WM_GETTEXT, sz, bf)
    Dim rs As String = Marshal.PtrToStringUni(bf)
    Marshal.Release(bf)
    Return rs.Trim
End Function
Public Shared Function GetWindowClassName(_hWindow As IntPtr) As String
    Dim ln As Integer = 256
    Dim sb As New System.Text.StringBuilder("", ln)
    GetClassName(_hWindow, sb, ln)
    Return sb.ToString()
End Function
Public Shared Function GetWindowText(_hWindow As IntPtr) As String
    Dim ln As Integer
    If _hWindow.ToInt32 <= 0 Then Return String.Empty
    ln = GetWindowTextLength(_hWindow)
    If ln = 0 Then Return String.Empty
    Dim sb As New System.Text.StringBuilder("", ln + 1)
    GetWindowText(_hWindow, sb, sb.Capacity)
    Return sb.ToString()
End Function

我已经看过GetWindowLong和GetDlgCtrlID API并且已经尝试了大部分标志,但到目前为止还没有成功......

任何提示,线索,方向都表示赞赏。 谢谢

1 个答案:

答案 0 :(得分:0)

我做了一个全局鼠标钩子,这不是问题,GetWindowText和WM_GETTEXT工作正常。事实上,该程序在这一点上运行良好和功能。 在检测到目标窗口时,我使用EnumChildWindows API保存列表集合中的子窗口句柄,并仅过滤EDIT类窗口(与上面发布的GetClassValues函数的修改版本一起使用。此函数的参数是第一个EDIT类窗口句柄)。无论如何,我任意访问我想要的文本框的方式是使用保存的列表用于此类窗口并按列表索引访问。正如我之前提到的,幸运的是,Windows按照一致的顺序创建了这个孩子的窗口。所以,在我的情况下,这个EDIT类窗口,即文本框“object”,总是列表中的第一个,尽管主窗口中有很多。 我想得到文本框“对象”的名称,比如前面提到的“txtAccountNumber”...