Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > Visual Basic > VB 6 Visual Basic 6 > Pro VB 6
Password Reminder
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
Pro VB 6 For advanced Visual Basic coders working in version 6 (not .NET). Beginning-level questions will be redirected to other forums, including Beginning VB 6.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Pro VB 6 section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old November 1st, 2004, 10:40 AM
Friend of Wrox
Join Date: Jun 2003
Location: London, , United Kingdom.
Posts: 173
Thanks: 0
Thanked 3 Times in 3 Posts
Default Problems using MSHTML

Hi all,

I'm currently working on an application based in Excel's VBA which uses the little-documented MSHTML COM tlb. The app logs onto a webiste for me, navigates through various pages and then downloads certain information from the website and uploads the information into my spreadsheet.

The program used to run absolutely fine, looping through all the buttons on the download page until it found the desired download button and then telling the website that the button had been clicked by using htmlButton.Click(). However Windows XP SP 2 detects this sort of behaviour as programatic downloading, which is now specifically blocked. For various reasons I'd rather not modify my security settings such that this behaviour is no longer blocked.

So I came up with the idea of using Win API calls to move the mouse over the button and force a click (Interet Explorer can't distinguish this behaviour from user action and so this is not blocked). I have worked a solution where I position and size the Internet Explorer window on my screen such that I know which pixel location need to move the mouse to in order to find the download button. The problem is that the layout of the website might change.

I've had a look through the object browser and found the TransformPoint method of the IDisplayServices interface which would appear to give me the ability to get a run-time co-ordinate location of any webpage element. However, I can't initialise the IDisplayServices object and consequently can't use its methods. Could anyone point me in the right direction or suggest a better way round this?

NB the MSDN website seems to suggest I need to use the QueryInterface method on IHTMLDocument2 but I get a compile error: Interface method restricted when I try to use it.

Any help would be appreciated,
Reply With Quote
  #2 (permalink)  
Old November 3rd, 2004, 08:04 AM
Friend of Wrox
Join Date: Jun 2003
Location: London, , United Kingdom.
Posts: 173
Thanks: 0
Thanked 3 Times in 3 Posts

I'm not sure if anyone cares but for completenesses sake I thought I'd post the answer to my earlier query.

It looks like the IDisplayServices interface can't be accessed when scipting with VBA - you have to be using C / C++. There were sevral more obstacles to getting this done but in answer to my specific query I needed to use the getBoundingClientRect mthod on the HTMLInputElement.

Below is some sample code which demonstrates the desired method by opening an internet explorer window, navigating to Google, putting something in the search box, finding the location of the search button, moving the move over the button & simulating a mouse click.

To get the code running in a VBA project you'll need to add references to Microsoft HTML Object Library (MSHTML) & Microsoft Internet Controls (SHDocVW).

Anyway, enjoy ...
Option Explicit

Private Type myRECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Enum CoordType
End Enum

' User32 API functions used to determine screen resolution
Declare Function GetDesktopWindow Lib "User32" () As Long
Declare Function GetWindowRect Lib "User32" (ByVal hWnd As Long, rectangle As myRECT) As Long

' User32 API Mouse functions
Private Declare Sub mouse_event Lib "User32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

' Mouse Event Flags

Sub Test()

Dim IExp As SHDocVw.InternetExplorer

Dim hDoc As MSHTML.HTMLDocument
Dim hCol As MSHTML.IHTMLElementCollection
Dim hInp As MSHTML.HTMLInputElement
Dim hPoint As MSHTML.tagPOINT

    Set IExp = New SHDocVw.InternetExplorer
    IExp.Visible = True
    IExp.navigate "http://www.google.co.uk"

    Do Until IExp.Busy = False

    Set hDoc = IExp.document

    ' Find the "search for" input box on the page
    Set hCol = hDoc.getElementsByTagName("input")
    For Each hInp In hCol

        If hInp.Name = "q" Then
            hInp.Value = "Test" ' Put in something to look for
            Exit For
        End If

    Next hInp

    ' Find the search button on the page
    Set hCol = hDoc.getElementsByTagName("input")
    For Each hInp In hCol

        If hInp.DefaultValue = "Google Search" Then

            ' Scroll IE to top left hand corner
            hDoc.parentWindow.scroll 0, 0

            ' Get coordinate of button
            hPoint = GetCoord(hDoc, hInp, Absolute)

            ' Move mouse
            mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE, hPoint.X, hPoint.Y, 0, 0

            ' Simulate click
            mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
            mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0

            Exit For

        End If

    Next hInp

End Sub

Private Function GetCoord(hDoc As MSHTML.HTMLDocument, hEle As MSHTML.HTMLInputElement, Output As CoordType) As MSHTML.tagPOINT

Dim ScreenRes As MSHTML.tagPOINT
Dim Point As MSHTML.tagPOINT

    ' Get the screen resolution
    ScreenRes = GetScreenResolution

    Set hIRectEle = hEle.getBoundingClientRect

    ' Find middle of input element
    Point.X = (hIRectEle.Left + hIRectEle.Right) / 2
    Point.Y = (hIRectEle.Top + hIRectEle.Bottom) / 2

    ' Add in offset for where the internet explorer window is located on screen
    Point.X = Point.X + hDoc.parentWindow.screenLeft
    Point.Y = Point.Y + hDoc.parentWindow.screenTop

    ' Convert to absolute coords, if necessary
    If Output = Absolute Then
        Point.X = (Point.X / ScreenRes.X) * 65000
        Point.Y = (Point.Y / ScreenRes.Y) * 65000
    End If

    GetCoord = Point

End Function

Function GetScreenResolution() As MSHTML.tagPOINT

Dim R As myRECT
Dim hWnd As Long
Dim RetVal As Long

    ' Win API calls
    hWnd = GetDesktopWindow()
    RetVal = GetWindowRect(hWnd, R)

    GetScreenResolution.X = (R.Right - R.Left)
    GetScreenResolution.Y = (R.Bottom - R.Top)

End Function
Reply With Quote
  #3 (permalink)  
Old February 15th, 2006, 11:32 AM
Registered User
Join Date: Feb 2006
Location: , , .
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts

Hello Maccas,

First of, that was a great article, very useful to me. Thanks!

I'm having some problem with it which I was wondering if you could help me out with. I got the following exception when trying to get the parent window of the current document. Any ideas why? Your help is greatly appreciated.


Unhandled Exception: System.Runtime.InteropServices.COMException (0x80040154): Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
   at System.RuntimeType.ForwardCallToInvokeMember(Strin g memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
   at mshtml.HTMLDocumentClass.get_parentWindow()
   at ConsoleApplication1.Module1.GetCoord(HTMLDocument hDoc, HTMLInputElement hEle, CoordType Output) in C:\New\ConsoleApplication1\ConsoleApplication1\Mod ule1
.vb:line 95
   at ConsoleApplication1.Module1.Test() in C:\New\ConsoleApplication1\ConsoleApplication1\Mod ule1.vb:line 64
   at ConsoleApplication1.Module1.Main() in C:\New\ConsoleApplication1\ConsoleApplication1\Mod ule1.vb:line 110
Press any key to continue . . .
Reply With Quote

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
mshtml - how to get images baburman C# 4 June 9th, 2006 06:18 AM
How to use MSHTML in Visual Basic 6? raylynn Pro VB 6 1 November 18th, 2005 09:36 AM
mshtml COM script events daveyc Pro VB.NET 2002/2003 0 June 15th, 2005 01:44 PM
validate.asp problems and logon.asp problems p2ptolu Classic ASP Databases 0 February 16th, 2005 02:34 PM
Problem using MSHTML maccas Excel VBA 1 November 3rd, 2004 08:04 AM

All times are GMT -4. The time now is 07:27 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.