-
Find Window handle by Partial Caption
I didnt see any code in here yet for this so here it is.
It will find the first window handle that contains the string passed.
For ex. if you want to find a window handle of Outlook but you dont know
which folder is currently being viewed (the folder name preceds ' - Microsoft
Outlook') you can go and pass " - Microsoft Outlook" and it will find Outlooks
handle if it is running.
Code:
Option Explicit
'<VB/OUTLOOK GURU 01/30/2004 - CODE TO FIND WINDOW HANDLE BASED ON PARTIAL WINDOW CAPTION>
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Const GW_HWNDNEXT = 2
Private Sub Command1_Click()
Dim lhWndP As Long
If GetHandleFromPartialCaption(lhWndP, " - Microsoft Outlook") = True Then
MsgBox "Found Window Handle: " & lhWndP, vbOKOnly + vbInformation
Else
MsgBox "Window ' - Microsoft Outlook' not found!", vbOKOnly + vbExclamation
End If
End Sub
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
sStr = Left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
-
Re: Find Window handle by Partial Caption
-
Re: Find Window handle by Partial Caption
I hadn't seen that code yet. I will check it out later when I get some time.
Probably similar logic though, oh well. :(
-
Re: Find Window handle by Partial Caption
Hi RobDog888,
The solution you suggested works #1 for me - Thanks. I have a question for you now tho. Once I've found the window I want, I am now interested in doing the same procedure, but now I want to find CONTROLS handle inside that window, based on a partial caption.
Ex.: The window in question has 4 buttons, always with different restaurant names as captions. I'd need to find the button that has, for exemple, "Burger" in the button caption. I used WinInspector to watch the window and I can see the buttons captions correctly.
Do you have an idea on how I could achieve that?
Thanks a lot.
-
Re: Find Window handle by Partial Caption
There is a property called a Control ID. This is the ID of the control and doesnt change. If you can see it with WinInspector then there is an API call to get it - GetDlgCtrlID.
-
Re: Find Window handle by Partial Caption
If I got that right, I need to use the GetDlgCtrlID API to get the control ID? If so, then I won't need to use it since Winspector Spy gives me that ID number, and you were right, it never changes - thanks for the tip.
But now, I guess I'd need some of your professionnal help on how to use that ID number. I will need to check the caption of that button (that I will extract and use in a variable).
Afterward, when all of this is working well, I will need to click that button. I normally use mouse_event MOUSEEVENTF_MOVE (considering I have the X,Y coordinates) to click those buttons, but it'd be great if an API could click it for me. That way it wouldn't move my mouse on the screen and I could work at the same time.
The Control ID I want to extract the caption and click is "4001".
Thanks for your very useful help
-
Re: Find Window handle by Partial Caption
Yes, you can SendMessage with the BM_CLICK parameter to do the button click without moving your mouse at all.
Not exactly, but the way it works is to enumerate the child windows checking each's DlgCtlID for a match of "4001". When you find the match then you use that handle to GetWindowText to retrieve the button text. Then that same handle can be used to SendMessage to click it.
:)
-
Re: Find Window handle by Partial Caption
I played with this quite a bit and things are progressing - thanks.
I got a small problem.
I am pretty sure you can easily point me in the right direction again on that one. You suggested to use SendMessage and BM_CLICK to click the buttons. That worked well, but only on SOME controls. Winspector detects some controls with the "Button" class name and these are working pretty good.
BUT there are some other buttons I want to click that are using the "AfxWnd42" class name. BM_CLICK doesn't work on those. Any idea on how to click those?
btw, thank you for replying my posts so quickly - I'm progressing a whole lot more faster.
-
Re: Find Window handle by Partial Caption
Sometimes I find that I have to send the bm_click message 2x but dont try on some buttons that do an action other then a close or cancle. ;)
I came across this
Quote:
Those Afx window classes were custom classes distributed with early versions of MFC, before the "Common Controls" concept was introduced.
Many people have tried to "read" text from them but you CAN'T, not with messages anyway!
They're almost certainly owner-drawn - the text is not delivered by messages, it's "hand-drawn" into the window's DC
And that may well be the reason. :(
About the only thing I see here is with subclassing the pother program which is aloot of work. Here i a good article on subclassing that may lead you to either dispare or guidence to a possible solution.
http://www.codeproject.com/system/ap..._unleashed.asp
Good luck as this is about as much help on it that I think I can give. ;)
-
Re: Find Window handle by Partial Caption
Strange because I WAS able to read the button caption of a Afx window class using GetText. ...And clicking the control twice or more didn't help neither.
So if there's no other solution I have no choice but to stick with those mouse_event MOUSEEVENTF_MOVE & CLICK methods. Sure it would have been better to use SendMessage/BM_CLICK and free my mouse mouvements. In that matter, would there be any api to "fake/simulate" a click to X,Y coords without affecting my mouse?
-
Re: Find Window handle by Partial Caption
You could also send a WM_LBUTTONDOWN and WM_LBUTTONUP on the button to simulate a left mouse click without moving the mouse.
-
Re: Find Window handle by Partial Caption
SendMessage wasn't working - PostMessage made the trick.
With winspector, along with all properties (ID, name, etc) there's a "Class specific" property which is set to "checked" or "unchecked". Do you have an idea on how to retrieve that information?
Thanks.
-
Re: Find Window handle by Partial Caption
Sorry but nope. Maybe a new thread in the API forum on this will get more input as members may think your just having issues with this code when its more about this special case. ;)
-
Re: Find Window handle by Partial Caption
Rob thank u for sharing this code. coul u tell me how to bring the window that we suppli its caption to front . I mean bring it to frong if it is behind windows explorers or other windows .thank
-
Re: Find Window handle by Partial Caption
How would i go about doing this in .NET 2005 ? this is what iv got so far having some trouble though.
VB Code:
Option Strict Off
Option Explicit On
Public Class Form1
'<VB/OUTLOOK GURU 01/30/2004 - CODE TO FIND WINDOW HANDLE BASED ON PARTIAL WINDOW CAPTION>
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Const GW_HWNDNEXT = 2
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim lhWndP As Long
If GetHandleFromPartialCaption(lhWndP, " - Microsoft Outlook") = True Then
MsgBox("Found Window Handle: " & lhWndP, vbOKOnly + vbInformation)
Else
MsgBox("Window ' - Microsoft Outlook' not found!", vbOKOnly + vbExclamation)
End If
End Sub
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText(lhWndP, sStr, Len(sStr))
sStr = Left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
End Class
-
Re: Find Window handle by Partial Caption
-
Re: Find Window handle by Partial Caption
this is what it looks like on my end
http://img180.imageshack.us/img180/7987/codesnipjq8.png
seem to be having trouble with these 2 lines
VB Code:
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
sStr = Left$(sStr, Len(sStr) - 1)
-
Re: Find Window handle by Partial Caption
VB Code:
sStr = sStr.PadRight(GetWindowTextLength(lhWndP) + 1, Chr(0))
:)
-
Re: Find Window handle by Partial Caption
ok almost there i think but im getting this now on the new code that you gave me
"A call to PInvoke function 'WindowsApplication1!WindowsApplication1.Module1::GetWindowTextLength' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."
http://img235.imageshack.us/img235/2615/ffffsvd5.jpg
Module
VB Code:
Module Module1
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, _
ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Const GW_HWNDNEXT = 2
Public Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = sStr.PadRight(GetWindowTextLength(lhWndP) + 1, Chr(0))
GetWindowText(lhWndP, sStr, Len(sStr))
sStr = sStr.Length - 1
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
End Module
call function
VB Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lhWndP As Long
If GetHandleFromPartialCaption(lhWndP, "window looking") = True Then
MsgBox("Found Window Handle: " & lhWndP, vbOKOnly + vbInformation)
Else
MsgBox("Window ' - Microsoft Outlook' not found!", vbOKOnly + vbExclamation)
End If
End Sub
-
Re: Find Window handle by Partial Caption
Ok, just noticed that you are using the VB 6 version of the API calls. You need to use the VB.NET syntax.
VB Code:
Option Explicit On
Option Strict On
Imports System.Runtime.InteropServices
Module Module1
Inherits System.Windows.Forms.Form
<DllImport("user32", EntryPoint:="GetWindowTextLength")> _
Private Shared Function GetWindowTextLength ( _
ByVal hwnd As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="FindWindow")> _
Private Shared Function FindWindow ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindowText")> _
Private Shared Function GetWindowText ( _
ByVal hwnd As Int32, _
ByVal lpString As String, _
ByVal cch As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindow")> _
Private Shared Function GetWindow ( _
ByVal hwnd As Int32, _
ByVal wCmd As Int32) As Int32
End Function
Private Const GW_HWNDNEXT As Int32 = 2
'...
-
Re: Find Window handle by Partial Caption
ok this is what im getting now
thanks so much for your help
http://img131.imageshack.us/img131/7910/ujujzt5.png
VB Code:
Module Module1
Private Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" ( _
ByVal hwnd As Int32) As Int32
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Int32
Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" ( _
ByVal hwnd As Int32, _
ByVal lpString As String, _
ByVal cch As Int32) As Int32
Private Declare Function GetWindow Lib "user32.dll" ( _
ByVal hwnd As Int32, _
ByVal wCmd As Int32) As Int32
Private Const GW_HWNDNEXT As Int32 = 2
Public Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = sStr.PadRight(GetWindowTextLength(lhWndP) + 1, Chr(0))
GetWindowText(lhWndP, sStr, Len(sStr))
sStr = sStr.Length - 1
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
End Module
-
Re: Find Window handle by Partial Caption
lol just saw that you updated the code sorry let me try that now see if it helps thanks so much for your time
-
Re: Find Window handle by Partial Caption
Change the dimensioning of the sStr var like so.
VB Code:
Dim sStr As String = String.Empty
-
Re: Find Window handle by Partial Caption
ok i got the code to run in debug but its not picking up my window i know the partial caption is right its same as the one i have for VB6 and it works..... its doing the else line like if it didnt find the window at all and im sure its there.
VB Code:
Option Explicit On
Option Strict Off
Imports System.Runtime.InteropServices
Module Module1
Private Const GW_HWNDNEXT As Int32 = 2
<DllImport("user32", EntryPoint:="GetWindowTextLength")> _
Public Function GetWindowTextLength( _
ByVal hwnd As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="FindWindow")> _
Public Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindowText")> _
Public Function GetWindowText( _
ByVal hwnd As Int32, _
ByVal lpString As String, _
ByVal cch As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindow")> _
Public Function GetWindow( _
ByVal hwnd As Int32, _
ByVal wCmd As Int32) As Int32
End Function
Public Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String = String.Empty
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = sStr.PadRight(GetWindowTextLength(lhWndP) + 1, Chr(0))
GetWindowText(lhWndP, sStr, Len(sStr))
sStr = sStr.Length - 1
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
End Module
VB Code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lhWndP As Long
If GetHandleFromPartialCaption(lhWndP, "Play money") = True Then
MsgBox("Found Window Handle: " & lhWndP, vbOKOnly + vbInformation)
Else
MsgBox("Window ' - Microsoft Outlook' not found!", vbOKOnly + vbExclamation)
End If
End Sub
End Class
-
Re: Find Window handle by Partial Caption
Step through the "GetHandleFromPartialCaption" procedure checking the values of each var.
-
Re: Find Window handle by Partial Caption
ok iv'e run over and over this and cant get it to work the same function in VB6 works fine the code runs in debug fine but GetHandleFromPartialCaption is always false here is what i have so far i put it all in the form thinkin the module was messing it up some how but it still does the same thing im pulling my hair out :eek2: ok here it is tell me what you think
VB Code:
Option Explicit On
Option Strict Off
Imports System.Runtime.InteropServices
Public Class Form1
Inherits System.Windows.Forms.Form
<DllImport("user32", EntryPoint:="GetWindowTextLength")> _
Private Shared Function GetWindowTextLength( _
ByVal hwnd As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="FindWindow")> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindowText")> _
Private Shared Function GetWindowText( _
ByVal hwnd As Int32, _
ByVal lpString As String, _
ByVal cch As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindow")> _
Private Shared Function GetWindow( _
ByVal hwnd As Int32, _
ByVal wCmd As Int32) As Int32
End Function
Private Const GW_HWNDNEXT As Int32 = 2
Private Function GetHandleFromPartialCaption(ByRef lWnd As Int32, ByVal sCaption As String) As Boolean
Dim lhWndP As Long
Dim sStr As String = String.Empty
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
Do While lhWndP <> 0
sStr = sStr.PadRight(GetWindowTextLength(lhWndP) + 1, Chr(0))
GetWindowText(lhWndP, sStr, Len(sStr))
sStr = sStr.Length - 1
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lhWndP As Long
GetHandleFromPartialCaption(lhWndP, "look window")
MsgBox("HANDLE.. " & lhWndP, vbOKOnly + vbInformation)
End Sub
End Class
-
Re: Find Window handle by Partial Caption
Are you sure sStr.PadRight is the right way to go? It seems like the only change that was made, and reading the description (and not knowing .Net) it seems like it doesn't do the same as the VB6 code...
-
Re: Find Window handle by Partial Caption
Thanks for the reply..... im not real sure of what im doing wrong i was hoping maybe robdog could help maybe he has been busy :blush: or just has not come up with a fix just yet, either way i dont have a problem waiting :)