Link to home
Start Free TrialLog in
Avatar of DRJ
DRJ

asked on

Help with enumerating child windows

I am trying to loop through all the controls on an external application window. I have the handle for that window but am not able to get the EnumChildWindows to work for me.

So basically I want to start with a handle and loop through all the child controls and return the text.

This is for VB.Net

Thanks
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

Avatar of DRJ
DRJ

ASKER

I saw some of these, couldn't get any of them to work right.

I had some examples working in Excel but when I tried in visual studio I am getting an error, but think I am getting closer.

The error is: 'AddressOf; expression cannot be converted to 'Long' because 'Long' is a delegate type.

Public Class Form1

    Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
        As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _
       ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

    Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
    Declare Function FindWindowX Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
    Public Declare Function APIGetTopWindow Lib "user32" Alias "GetTopWindow" (ByVal hwnd As Integer) As Integer
    Public Declare Function APIGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Integer

    Public Const WM_GETTEXT = &HD

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim Hwnd

        Hwnd = APIGetTopWindow(APIGetDesktopWindow)
        Call EnumChildWindows(Hwnd, AddressOf EnumChildWindow, 0&)

    End Sub

    Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Long

        Dim wClass As String, wText As String
        Dim j As Integer

        wClass = Space(64)
        j = GetClassName(hChild, wClass, 63)
        wClass = Microsoft.VisualBasic.Left(wClass, j)

        wText = Space(256)
        j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
        wText = Microsoft.VisualBasic.Left(wText, j)

        EnumChildWindow = 1  ' Continue enumeration

    End Function

End Class
Your code looks more like VB5/VB6 code.
This thing will not work in VB.NET, you will need delegates here.

This is not the solution, but you can try this to eliminate your current error.
Add:
Delegate Function EnumChildWindProc(ByVal hWnd As Long, _
            ByVal lParam As Long) As Boolean

Change:
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
        As Long, ByVal lpEnumFunc As EnumWindProc, ByVal lParam As Long) As Long


Another change:
  Dim proc As New EnumWindProc(AddressOf EnumChildWindow)
  Hwnd = APIGetTopWindow(APIGetDesktopWindow)
  Call EnumChildWindows(Hwnd, proc, 0&)

All handles should be Int32, as the calls are of Win32 API.
Avatar of DRJ

ASKER

I think it is closer, this compiles now, but when I run it nothing happens. As I step through, EnumChildWindow never runs.

Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

    Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
    Declare Function FindWindowX Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
    Public Declare Function APIGetTopWindow Lib "user32" Alias "GetTopWindow" (ByVal hwnd As Integer) As Integer
    Public Declare Function APIGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Integer

    Public Const WM_GETTEXT = &HD

    Delegate Function EnumChildWindProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
    Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As EnumChildWindProc, ByVal lParam As Long) As Long

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim Hwnd As Int32

        Dim proc As New EnumChildWindProc(AddressOf EnumChildWindow)
        Hwnd = APIGetTopWindow(APIGetDesktopWindow)
        Call EnumChildWindows(Hwnd, proc, 0&)

    End Sub

    Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Boolean

        Dim wClass As String, wText As String
        Dim j As Integer

        wClass = Space(64)
        j = GetClassName(hChild, wClass, 63)
        wClass = Microsoft.VisualBasic.Left(wClass, j)

        wText = Space(256)
        j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
        wText = Microsoft.VisualBasic.Left(wText, j)

        EnumChildWindow = 1  ' Continue enumeration

    End Function
Avatar of DRJ

ASKER

Just as a simple example of what I am trying to do.

Let's say I wanted to get the text from the textbox in calc.exe. And I already have found the handle for calc.exe.

From that how can I loop through all the children windows and find the textbox and return the text. And example returning all the text from any child windows would be sufficient for my purposes.

Thanks
I hope you found the calculator handle somehow, and then the children  can be further enumerated as given in the code.
This code is not perfect, but it should work.

Public Class Form1
    Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

    Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As System.Text.StringBuilder) As Long

    Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
    Public Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hwnd As Int32, ByVal sText As System.Text.StringBuilder, ByVal iVal As Int32) As Long

    Declare Function FindWindowX Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
    Public Declare Function APIGetTopWindow Lib "user32" Alias "GetTopWindow" (ByVal hwnd As Integer) As Integer
    Public Declare Function APIGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Integer

    Public Const WM_GETTEXT = &HD

    Delegate Function EnumChildWindProc(ByVal hWnd As Int32, ByVal lParam As Long) As Boolean
    Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Int32, ByVal lpEnumFunc As EnumChildWindProc, ByVal lParam As Long) As Long

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            Dim Hwnd As Int32

            Dim proc As New EnumChildWindProc(AddressOf EnumChildWindow)
            'Hwnd = APIGetTopWindow(APIGetDesktopWindow)
            Hwnd = FindWindow("SciCalc", "Calculator")
            Call EnumChildWindows(Hwnd, proc, 0&)
        Catch ex As Exception
            ex = ex
        End Try
    End Sub

    Function EnumChildWindow(ByVal hChild As Int32, ByVal lParam As Long) As Boolean

        Dim wText As New System.Text.StringBuilder(255)
        Dim j As Long

        j = GetWindowText(hChild, wText, 255)
        j = j
        If j > 0 Then MessageBox.Show(wText.ToString)

        EnumChildWindow = 1  ' Continue enumeration

    End Function
End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of DRJ
DRJ

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
no objections