VBA/VB.Net/VB6–Click Open/Save/Cancel Button on IE Download window – PART II


EDIT

I have stopped updating this blog. This link can also be found in my Website.

http://www.siddharthrout.com/2012/02/02/vbavb-netvb6click-opensavecancel-button-on-ie-download-window-part-ii/

 

This is in continuation to my previous post where I showed you on how to click the “Open/Cancel Button”.

I am quite surprised by the number of hits that I am getting on that post. So I have decided to go ahead and post the code for “Save” button as well.

But before we go ahead, let me show you something interesting. If you have Spy ++ or uuSpy then you can see what I mean.

Our first impression is that once we click the “Save” button then it will be easy to populate the filename in the “Save As dialog” box. Well that is not that easy because it depends on the nesting windows. See these two examples. The first one is for IE6 and the other is for IE 8/9.

image

In the below code, I have used lot’s of Message Boxes and Wait so that you can actually step through the code or see how the code executes.

Paste this in a Module

Option Explicit

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 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 SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long

Private Declare Sub SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As _
Long, ByVal cy As Long, ByVal wFlags As Long)

Private Declare Function SetCursorPos Lib "user32" _
(ByVal X As Integer, ByVal Y As Integer) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Declare Sub mouse_event Lib "user32.dll" (ByVal dwFlags As Long, _
ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

'~~> Constants for pressing left button of the mouse
Const MOUSEEVENTF_LEFTDOWN As Long = &H2
'~~> Constants for Releasing left button of the mouse
Const MOUSEEVENTF_LEFTUP As Long = &H4
Const WM_SETTEXT As Long = &HC
Const BM_CLICK = &HF5
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2
Const SWP_NOACTIVATE = &H10
Const SWP_SHOWWINDOW = &H40

Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Dim Ret As Long, OpenRet As Long, FlDwndHwnd As Long
Dim ChildRet As Long
Dim strBuff As String, ButCap As String
Dim pos As RECT

'~~> Use this if you want to specify your own name in the Save As Window
Const FileSaveAsName = "C:\MyFile.xls"

Private Sub CommandButton1_Click()
    On Error GoTo Whoa

    Ret = FindWindow(vbNullString, "File Download")

    If Ret <> 0 Then
        MsgBox "Main Window Found"

        '~~> Get the handle of the Button's "Window"
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Button", vbNullString)

        If ChildRet = 0 Then
            MsgBox "Child Window Not Found"
            Exit Sub
        End If

        '~~> Get the caption of the child window
        strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
        GetWindowText ChildRet, strBuff, Len(strBuff)
        ButCap = strBuff

        '~~> Loop through all child windows
        Do While ChildRet <> 0
            '~~> Check if the caption has the word "Save"
            If InStr(1, ButCap, "Save") Then
                '~~> If this is the button we are looking for then exit
                OpenRet = ChildRet
                Exit Do
            End If

            '~~> Get the handle of the next child window
            ChildRet = FindWindowEx(Ret, ChildRet, "Button", vbNullString)
            '~~> Get the caption of the child window
            strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
            GetWindowText ChildRet, strBuff, Len(strBuff)
            ButCap = strBuff
        Loop

        '~~> Check if we found it or not
        If OpenRet = 0 Then
            MsgBox "The Handle of Save Button was not found"
            Exit Sub
        End If

        '~~> Retrieve the dimensions of the bounding rectangle of the
        '~~> specified window. The dimensions are given in screen
        '~~> coordinates that are relative to the upper-left corner of the screen.
        GetWindowRect OpenRet, pos

        '~~> Move the cursor to the specified screen coordinates.
        SetCursorPos (pos.Left - 10), (pos.Top - 10)
        '~~> Suspends the execution of the current thread for a specified interval.
        '~~> This give ample amount time for the API to position the cursor
        Sleep 100
        SetCursorPos pos.Left, pos.Top
        Sleep 100
        SetCursorPos (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2

        '~~> Set the size, position, and Z order of "File Download" Window
        SetWindowPos Ret, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE
        Sleep 100

        '~~> Simulate mouse motion and click the button
        '~~> Simulate LEFT CLICK
        mouse_event MOUSEEVENTF_LEFTDOWN, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0
        Sleep 700
        '~~> Simulate Release of LEFT CLICK
        mouse_event MOUSEEVENTF_LEFTUP, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0

        Wait 10

        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' START OF SAVEAS ROUTINE '
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        Ret = FindWindow(vbNullString, "Save As")

        If Ret = 0 Then
            MsgBox "Save As Window Not Found"
            Exit Sub
        End If

        '~~> UNCOMMENT this if using IE6 and COMMENT the code for "DUIViewWndClassName"
        '~~> "DirectUIHWND" and "FloatNotifySink"

' '~~> Get the handle of the Main ComboBox
' ChildRet = FindWindowEx(Ret, ByVal 0&, "ComboBoxEx32", "")
'
' If ChildRet = 0 Then
' MsgBox "ComboBoxEx32 Window Not Found"
' Exit Sub
' End If

        ChildRet = FindWindowEx(Ret, ByVal 0&, "DUIViewWndClassName", "")
        If ChildRet = 0 Then
            MsgBox "DUIViewWndClassName Not Found"
            Exit Sub
        End If

        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "DirectUIHWND", "")
        If ChildRet = 0 Then
            MsgBox "DirectUIHWND Not Found"
            Exit Sub
        End If

        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "FloatNotifySink", "")
        If ChildRet = 0 Then
            MsgBox "FloatNotifySink Not Found"
            Exit Sub
        End If

        '~~> Get the handle of the Main ComboBox
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "ComboBox", "")

        If ChildRet = 0 Then
            MsgBox "ComboBox Window Not Found"
            Exit Sub
        End If

        '~~> Get the handle of the Edit
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "Edit", "")

        If ChildRet = 0 Then
            MsgBox "Edit Window Not Found"
            Exit Sub
        End If

        '~~> COMMENT the below 3 lines if you do not want to specify a filename
        Wait 10
        SendMess FileSaveAsName, ChildRet
        Wait 10

        '~~> Get the handle of the Save Button in the Save As Dialog Box
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Button", vbNullString)

        '~~> Check if we found it or not
        If ChildRet = 0 Then
            MsgBox "Save Button in Save As Window Not Found"
            Exit Sub
        End If

        '~~> Get the caption of the child window
        strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
        GetWindowText ChildRet, strBuff, Len(strBuff)
        ButCap = strBuff

        '~~> Loop through all child windows
        Do While ChildRet <> 0
            '~~> Check if the caption has the word "Save"
            If InStr(1, ButCap, "Save") Then
                '~~> If this is the button we are looking for then exit
                OpenRet = ChildRet
                Exit Do
            End If

            '~~> Get the handle of the next child window
            ChildRet = FindWindowEx(Ret, ChildRet, "Button", vbNullString)
            '~~> Get the caption of the child window
            strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
            GetWindowText ChildRet, strBuff, Len(strBuff)
            ButCap = strBuff
        Loop

        '~~> Check if we found it or not
        If OpenRet = 0 Then
            MsgBox "The Handle of Save Button in Save As Window was not found"
            Exit Sub
        End If

        '~~> Save the file
        SendMessage OpenRet, BM_CLICK, 0, ByVal 0&

        Wait 10
    Else
        MsgBox "File Download Window Not found"
    End If
    Exit Sub
Whoa:
    MsgBox Err.Description
End Sub

Sub Wait(nSec As Double)
    nSec = nSec + Timer
    While nSec > Timer
        DoEvents
    Wend
End Sub

Sub SendMess(Message As String, hwnd As Long)
    Call SendMessage(hwnd, WM_SETTEXT, False, ByVal Message)
End Sub

To convert the above code to VB6 or VB.Net, refer to my previous post where I have already given an example.

If you understand the basic structure on how to get the handle of a window then the above task will look like a piece of cake.

UPDATE: 25/7/2012

NOTE: For people using IE9, depending on the link that you pass to the browser, you may or may not see the Info Security Bar. If you see the Info security bar then I suggest seeing this link where I have attached an exe file which you can use to bypass the IE9 Info Security Bar.


Advertisements

9 responses to “VBA/VB.Net/VB6–Click Open/Save/Cancel Button on IE Download window – PART II

  1. illninogiggs February 5, 2012 at 9:45 am

    Try this

    Sub test()
    Dim oHttp, objStream
    Set oHttp = CreateObject(“Microsoft.XMLHTTP”)
    oHttp.Open “GET”, “http://www.example.com/abc.zip”, False
    oHttp.send

    Set objStream = CreateObject(“ADODB.Stream”)
    objStream.Type = 1
    objStream.Open
    objStream.Write oHttp.ResponseBody
    objStream.Savetofile “C:\abc.zip”, 2
    objStream.Close

    End Sub

  2. kavithas May 9, 2012 at 9:43 pm

    Siddharth – Thanks for the above. I need some help with downloading an Excel from an ASP.net page. The page masks the direct URL to the Excel and I am having to simulate IE button clicks to submit the form. However I get an HRESULT error. The website is

    http://tebb.elpaso.com/ebbmasterpage/Capacity/OperAvailAutoTable.aspx?code=TGP&name=Operationally+Available+Capacity&status=Cap&sParam2=M&sParam3=5%2f2%2f2012&sParam8=S

    and i click the “Summary Download” button to download excel. Any inputs? Thanks.

  3. Jeff Stevens June 14, 2012 at 1:41 am

    The article mentions IE9, but IE9 has a different download manager (the yellow ribbon at the bottom of the screen). Does this code have a method to control the new IE9 method? It does not have a Title to locate the “File Download” string (as in IE8) and it crashes at that point.

  4. ishwar June 29, 2012 at 7:37 am

    Ultimate Solution !!!!!!!!!!!!.
    Thank you siddhart.This Solution save my lot of time .

  5. John Houghton August 14, 2012 at 8:10 pm

    Hi there,
    This is a wonderful solution as I’ve always had to perform this activity using Sendkeys (and leave the PC unlocked). However, I’m really struggling with your response in part 1 when someone said it didn’t work when the screen was locked. You said it was because the parent was now the desktop, and to work from there. That’s the bit I’m having problems with, I can’t find the hWnd of the desktop, I suspect I’m making it over complicated. Any help would be most appreciated.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: