Finding child by its first word
Hey guys :)
I got a situation where i have the first word only of a a child window and the rest of the name changes. I need to find this child window using findwindowex i think by not knowing the full name.
Searching the processes wont work since it is a child.
Tnx alot ^^
Re: Finding child by its first word
Enum all child windows (getting their handles) and send GetWindowText to each one. You can then see if the returned strings contain the first part.
http://www.vbforums.com/showpost.php...30&postcount=6
Re: Finding child by its first word
Re: Finding child by its first word
It is giving me example these values:
201e4
20208
201b0
1002c
I appreciate your help alot but i might be needing some spoon feeding here cause im not expert in the subject yet ;)
Re: Finding child by its first word
No problem. This whole thing may seem complicated but in reality FindWindowEx is performing the same thing. It is a Windows functions that first sends a WM_GETTEXTLENGTH, then a WM_GETTEXT message to all child windows. We do the same thing, because we need a partial match only.
WM_GETTEXTLENGTH tells us the number of chars in the title. We then create a StringBuilder with enough capacity to hold those chars and use WM_GETTEXT to actually fill the StringBuilder.
Since I don't know what program you are interested in, the example below is using Windows Calculator to find the handle of the label 'Degrees' by searching for 'degr'. Just make sure that Calculator is running and in scientific mode (View -> Scientific).
Code:
'APIs needed to get the Handles of all child windows
Private Declare Auto Function FindWindowEx Lib "user32" _
(ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, _
ByVal ClassName As String, ByVal WindowTitle As String) As IntPtr
Private Declare Auto Function EnumChildWindows Lib "user32" _
(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
ByVal lParam As IntPtr) As Boolean
Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, _
ByVal Parameter As IntPtr) As Boolean
'----------------------------------------------------------------------
'APIs needed to get a WindowTitle
Private Declare Auto Function SendMessageSTRINGlength Lib "user32" Alias "SendMessage" _
(ByVal hwnd As IntPtr, ByVal wMsg As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Private Declare Auto Function SendMessageSTRINGget Lib "user32" Alias "SendMessage" _
(ByVal hwnd As IntPtr, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As IntPtr
Private Const WM_GETTEXTLENGTH As Integer = &HE
Private Const WM_GETTEXT As Integer = &HD
'----------------------------------------------------------------------
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
'let's use Windows Calculator as an example
Dim MainHandle As IntPtr
MainHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "SciCalc", "Calculator")
Dim ChildHandles() As IntPtr = GetChildWindows(MainHandle)
'for visual confirmation
For i As Integer = 0 To ChildHandles.Length - 1
ListBox1.Items.Add(i & ": " & System.Convert.ToString(ChildHandles(i).ToInt32, 16))
Next
'here we go through all the window titles
For i As Integer = 0 To ChildHandles.GetUpperBound(0)
'get the length of the text
Dim txtLength As IntPtr
txtLength = SendMessageSTRINGlength(ChildHandles(i), WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero)
'create buffer for the returned string
Dim returnedText As New System.Text.StringBuilder(txtLength.ToInt32 + 1)
'get the window text. Length + 1 because of the null termination
SendMessageSTRINGget(ChildHandles(i), WM_GETTEXT, txtLength.ToInt32 + 1, returnedText)
'here we look for the first part of a window title
If returnedText.ToString.Contains("Degr") Then
'ChildHandles(i) is the handle we need
MessageBox.Show(System.Convert.ToString(ChildHandles(i).ToInt32, 16) & _
" is a handle to a child window" & vbCrLf & "whose title contains degr")
'no need to search for more since we just found we need
Exit For
End If
Next
End Sub
Public Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
Dim ChildrenList As New List(Of IntPtr)
Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
Try
EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
Finally
If ListHandle.IsAllocated Then ListHandle.Free()
End Try
Return ChildrenList.ToArray
End Function
Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
Dim ChildrenList As List(Of IntPtr) = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
ChildrenList.Add(Handle)
Return True
End Function
Re: Finding child by its first word
Tnx alot bro
Very helpful :)
Re: Finding child by its first word
What are you trying to achieve? Are you checking to see if the child form is already open?