|
-
Jan 18th, 2013, 11:10 PM
#1
Thread Starter
Lively Member
Help with FindWindow & SendMessage for username & pw text boxes
I'm needing a little help with using FindWindow, FindWindowEx, and SendMessage in order to pass a username and password to a login dialogue box from another application.
I am trying to pass a username & password to an application, and make it hit the "ok" button. The issue that I am having is that both of the text boxes used for username & password have the class of "Edit" and are both blank.
How do i determine which textbox is which, and send the correct login info to them?
I had this working with another application, but when I tried it with Internet Explorer login prompt, and with another app, I get an error message. Here is the code that I'm using, but I get a debug error.
I have to say that I'm not super efficient in coding, but I can normally adapt simple code to my needs, but I don't understand why I'm getting an error. All help is much appreciated!
Code:
Option Explicit
'Run the control.exe in the app.path and execute this code.
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
'Used here to retrive the child windows from a given parent window
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
'used here to obtain the top position of the Text Boxes in the Screen.
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'Used to get the Class names of the controls
Private Const WM_SETTEXT = &HC
Private Const GW_HWNDNEXT = 2
Private Const GW_CHILD = 5
Private Type RECT 'GetWindowRect use this structure to store the values it ritrive.
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private StrClass As String * 255
Code:
Private Sub Command1_Click()
Dim lhnd As Long 'parent window handle
Dim lhndChild As Long 'child window handle
Dim TxtUnameHnd As Long 'The user name text box handle
Dim txtPassHnd As Long 'the password text box handle
Dim lngresult As Long
Dim i As Integer 'Used with instr() To manipulate the class text returned.
Dim StrClassName As String 'GetClassName used this buffer to store the class name
Dim rec As RECT
Dim strItems(1, 1) As Long 'Initializing a two Diamensional Array to hold the Handles and RECT's Top value of the two text boxes.
Dim p As Integer 'Used with arry element position.
lhnd = FindWindow(vbNullString, "User Logon") 'Returns the specified windows Handle
lhndChild = GetWindow(lhnd, GW_CHILD) 'Retrieves handles of the child windows in the 'user logon' window....not sure why this is needed.
Do
lhndChild = GetWindow(lhndChild, GW_HWNDNEXT) 'Get text of the fist child window
If lhndChild = 0 Then Exit Do 'IF no more child window to ritrive, then exit.
Call GetClassName(lhndChild, StrClass, 255) 'get class name of the first child window
i = InStr(1, StrClass, Chr$(0)) 'trim the Null Charactors of strClass buffer
If Left$(StrClass, i - 1) = "Edit" Then 'Check weather the contol class name is a TextBox (ThunderRT6TextBox).
GetWindowRect lhndChild, rec 'Get that windows screen top position.
strItems(p, 0) = lhndChild 'store the handle in the arrys. <------Run Time Error 9 Subscript out of range.
strItems(p, 1) = rec.Top ' Strore the top value in the arry.
p = p + 1
End If
Loop
'Find the Username text box by Manipulating the top positions of the two text boxes.
If strItems(0, 1) < strItems(1, 1) Then
TxtUnameHnd = strItems(0, 0) 'assign the handle
txtPassHnd = strItems(1, 0)
Else
TxtUnameHnd = strItems(1, 0) 'assign the handle
txtPassHnd = strItems(0, 0)
End If
lngresult = SendMessage(TxtUnameHnd, WM_SETTEXT, 0&, ByVal "Test")
lngresult = SendMessage(txtPassHnd, WM_SETTEXT, 0&, ByVal "Password")
End Sub
Last edited by jwetzler; Jan 18th, 2013 at 11:16 PM.
-
Jan 19th, 2013, 12:17 AM
#2
Re: Help with FindWindow & SendMessage for username & pw text boxes
Have you tried dimensioning p As Long? Try tracking the values of the strItems array by stepping through the Do..Loop (press F8) and see at which point you get the "Subscript out of range" error. You may also use a UDT array instead of a 2-dimensional array for faster access.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 19th, 2013, 12:29 AM
#3
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
 Originally Posted by Bonnie West
Have you tried dimensioning p As Long? Try tracking the values of the strItems array by stepping through the Do..Loop (press F8) and see at which point you get the "Subscript out of range" error. You may also use a UDT array instead of a 2-dimensional array for faster access.
I tried to Dim 'p' as Long but still gave me the same debug error message.
It keeps on erroring out at:
strItems(p, 0) = lhndChild 'store the handle in the arrys.
when hitting F8 and stepping through it.
-
Jan 19th, 2013, 12:51 AM
#4
Re: Help with FindWindow & SendMessage for username & pw text boxes
That's probably because you've declared the strItems array as:
Code:
Dim strItems(0 To 1, 0 To 1) As Long
There are two dimensions in the array, but each dimension is limited to only 2 elements (from 0 to 1). Perhaps, you may find it easier if you use a UDT array instead, sort of like this:
Code:
Private Type WindowInfo
hWnd As Long
Top As Long
End Type
Private Sub Command1_Click()
Dim strItems() As WindowInfo
. . .
ReDim strItems(0 To 0) As WindowInfo
. . .
If . . .
strItems(p).hWnd = lhndChild
strItems(p).Top = rec.Top
p = p + 1
ReDim Preserve strItems(0 To p) As WindowInfo
End If
. . .
End Sub
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 19th, 2013, 10:34 AM
#5
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
 Originally Posted by Bonnie West
That's probably because you've declared the strItems array as:
Code:
Dim strItems(0 To 1, 0 To 1) As Long
There are two dimensions in the array, but each dimension is limited to only 2 elements (from 0 to 1). Perhaps, you may find it easier if you use a UDT array instead, sort of like this:
Code:
Private Type WindowInfo
hWnd As Long
Top As Long
End Type
Private Sub Command1_Click()
Dim strItems() As WindowInfo
. . .
ReDim strItems(0 To 0) As WindowInfo
. . .
If . . .
strItems(p).hWnd = lhndChild
strItems(p).Top = rec.Top
p = p + 1
ReDim Preserve strItems(0 To p) As WindowInfo
End If
. . .
End Sub
Bonnie, I haven't used a UDT array before, infact I'm pretty new when it comes to arrays.
What part of my code do I need to strip out, and replace with the UDT array, and what parts of my code do I need to leave in?
What's weird is that the original code works fine if I create an .exe that has two textboxes...but when I try testing it on the real production app it doesn't work for some reason.
-
Jan 19th, 2013, 11:01 AM
#6
Re: Help with FindWindow & SendMessage for username & pw text boxes
You probably need to familiarize yourself first with the concepts of Arrays and UDTs. However, if you're in a hurry, then you just need to replace all instances of strItems(p, 0) with strItems(p).hWnd and strItems(p, 1) with strItems(p).Top. BTW, the strItems array name doesn't quite describe what that array really is. Perhaps, udtTxtBoxes might be more meaningful?
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 19th, 2013, 11:11 AM
#7
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
 Originally Posted by Bonnie West
You probably need to familiarize yourself first with the concepts of Arrays and UDTs. However, if you're in a hurry, then you just need to replace all instances of strItems(p, 0) with strItems(p).hWnd and strItems(p, 1) with strItems(p).Top. BTW, the strItems array name doesn't quite describe what that array really is. Perhaps, udtTxtBoxes might be more meaningful?
I just realized that there are 3 textboxes on the login dialogue box. The very first textbox is disabled, and I didn't think that it would go into our equation. But I just realized that VB doesn't care if that textbox is disabled or not, it will still find it.
So that must be why it was erroring out in the array, because we need one that will support 3 values instead of 2 right? Is there an easy way to tell it to disregard the disabled text box? Or is there any easy way to modify the code to only pass the login info to the bottom two text boxes?
-
Jan 19th, 2013, 11:22 AM
#8
Re: Help with FindWindow & SendMessage for username & pw text boxes
You may test if a textbox is disabled through the IsWindowEnabled API function.
Code:
Private Declare Function IsWindowEnabled Lib "user32.dll" (ByVal hWnd As Long) As Long
You may ignore the disabled textbox if that function returns zero.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 20th, 2013, 08:50 AM
#9
Re: Help with FindWindow & SendMessage for username & pw text boxes
Why are you trying to login to a Supervisor workstation?
Are you a supervisor?
-
Jan 20th, 2013, 11:17 AM
#10
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
 Originally Posted by Hack
Why are you trying to login to a Supervisor workstation?
Are you a supervisor?
No I'm not a supervisor, I'm just the guy that supports them. ha.
The screen shot is actually of an application that our supervisors use in our call center. The app shows the state of all of the call center reps that are logged into their phone. So it will show them Hold Time, Schedule Adherence, Length of Calls, etc etc. Basically is used by the supervisors to see which reps are on long calls, or have had their customers on hold too long, that way they can go help the rep and reduce the length of their call.
I've been tasked with finding a way to get this to display on all of the TV's in our call center (which is complete). I just have to come up with a way to automate the logon process for this app, so that we don't have to do it manually every morning. The PC is in our locked data center, and I have setup a generic login for the IEX software.
I just need to make an app to pass the generic login info to IEX now.
Any thoughts? I tried switching my code up like bonnie suggested, but couldn't get the grasp of it.
-
Jan 20th, 2013, 11:42 AM
#11
Re: Help with FindWindow & SendMessage for username & pw text boxes
In the User Logon dialog box, what happens when you press Alt-N and Alt-P? I suppose the respective textboxes gets the focus, don't they? If so, then you may be able to employ the SendKeys statement to programmatically type the login info.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 20th, 2013, 11:50 AM
#12
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
 Originally Posted by Bonnie West
In the User Logon dialog box, what happens when you press Alt-N and Alt-P? I suppose the respective textboxes gets the focus, don't they? If so, then you may be able to employ the SendKeys statement to programmatically type the login info.
Yeah SendKeys would work, I was just hoping to do it using send message instead. That way it will pass the correct info even with out focus.
I could probably do something like AppActivate("User Logon") and then use SendKeys to have it either tab to the username field or use Alt-N/P.
-
Jan 20th, 2013, 12:01 PM
#13
Re: Help with FindWindow & SendMessage for username & pw text boxes
You may also set the focus to the dialog box with either the SetForegroundWindow or SetFocus APIs.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 20th, 2013, 12:28 PM
#14
Thread Starter
Lively Member
Re: Help with FindWindow & SendMessage for username & pw text boxes
Bonnie, when using UDT arrays...do I have to specify how many elements I need, or is it dynamic?
The main problem I have for my original code is that the array appears to be setup to only store the handles of 2 text boxes.
And now I need to be able to store the handles of 3 text boxes. When it finds the 3rd text box it's throwing an error b/c the array isn't setup for 3.
-
Jan 20th, 2013, 12:44 PM
#15
Re: Help with FindWindow & SendMessage for username & pw text boxes
UDT arrays are just like any other arrays; they can be fixed size or dynamic.
Dimension your original array as:
Code:
Dim strItems(0 To 2, 0 To 1) As Long
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|