Fog Creek Software
Discussion Board




Run embedded scripts with DHTML Object Model

Sorry - did search Google high and low, but could not find an answer to this question:

I have a web page with a <script></script> block containing a function Test().

I open this page with a WebBrowser control (Internet Explorer Automation) in my Application.

How do I execute Test()?

DarenThomas
Tuesday, January 20, 2004

If I remember correctly, you can just get hold of the document object from the WebBrowser control, QueryInterface it for IDispatch and then call your function using IDispatch::Invoke.

R1ch
Tuesday, January 20, 2004

hm... does this translate (in VB) into following code:

CallByName WebBrowser, "Test", VbMethod, Empty

(doesn't work, tried WebBrowser.Document as well...)

I am beginning to wonder if it's supported at all...

DarenThomas
Tuesday, January 20, 2004

Following python (in interactive shell) doesn't work either - I believe it does the same as above since I haven't run makepy for Microsoft Internet controls etc.

from win32com.client import *
ie = Dispatch("InternetExplorer.Application")
ie.Navigate("C:\Projects\Test\Test.html")
doc = ie.Document
doc.Test()

DarenThomas
Tuesday, January 20, 2004

I'd have thought so, but I don't know VB I'm afraid.
You could also try the slightly more hacky method of:
WebBrowser.navigate "javascript:test()"

R1ch
Tuesday, January 20, 2004

It looks like IDispatch is the right way to do it from C++

http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q185/1/27.asp&NoWebContent=1

I don't know why CallByName doesn't work tho.

R1ch
Tuesday, January 20, 2004

Once I wrote code which was calling JS functions in IE control. Unfortunately I can't find it now (never made it to production), but I remember that it was important for some reason to declare the IE object with events:

Private WithEvents oIE As InternetExplorer ' IE control

After that I was able to do

oIE.Test

which apparently used the IDispatch interface.

Alexander Chalucov (http://www.alexlechuck.com)
Tuesday, January 20, 2004

In javascript, you can call it from a gui with: onChange="test()"  or onClick="test()", the heading will be <SCRIPT language="javascript">
function test() {

}
</SCRIPT>.
Google for: javascript tutorial DOM function

Barry Sperling
Tuesday, January 20, 2004

the test method isn't on the browser object, but rather on the MSHTML object contained by the browser object.

so WebBrowser.Document.Test() should work, while WebBrowser.Test() should not.

mb
Tuesday, January 20, 2004

You can run things by using CallByName with the Window object.  Here is a function from a class that I built to mirror the MS Script Control, but for the WebBrowser:

Public Function Run(ProcedureName As String, ParamArray Parameters() As Variant) As Variant
   
    On Error GoTo ProcErr
   
    Select Case UBound(Parameters())
    Case -1
        Run = CallByName(Window, ProcedureName, VbMethod)
    Case 0
        Run = CallByName(Window, ProcedureName, VbMethod, Parameters(0))

    ....


Here is also another function of the same class that makes it easy to expose internal objects (even if they're private classes) to the WebBrowser's script:

Public Sub AddObject( _
    Name As String, _
    Object As Object, _
    Optional lFlags As WSRTAppObjFlagEnum = wscrObjKeepAlive)
   
    If FlagSet(lFlags, wscrObjKeepAlive) Then
    '  This object is for the currenlty loaded URL only add it to the script if we can keep it.
        ObjKeep Name, Object, lFlags
    End If
   
    If StateFlag(wscrStateLoaded) Then
    '  This object is not going to be kept alive, just add it to the script.
        ObjAddToScript Name, Object
    End If
   
End Sub

Wayne
Tuesday, January 20, 2004

Sorry, that last function "AddObject" doesn't do anything but call the real method which is this:

Private Sub ObjAddToScript( _
    Name As String, _
    Object As Object _
)
    On Error GoTo ProcErr
   
    Dim sCode$
   
    sCode = _
        "var " & Name & " = null;" & vbCrLf & _
        "function _InitObj(oObj){ " & Name & " = oObj; }"
   
'  NOTE: Doesn't matter which language is used to add the object,
'  it will be available to both languages.
    Window.execScript sCode, LANG_JS_STRING
    Me.Run "_InitObj", Object

...

(The ObjKeep method simply caches the object in a collection so when the browser navigates to a new page, it can re-add it using ObjAddToScript.)

Wayne
Tuesday, January 20, 2004

For the record: I followed the above linke to the C++ way of doing things. Translation to VB:

Call webBrowser.Document.Script.Test()

does the trick...

DarenThomas
Wednesday, January 21, 2004

Can this be done dynamically.  I am writing an IE scripting tool against webbrowser and need to either find out why <SELECT> onchange events are not being fired or manually firing the javascript.  I got it to work using the wb.document.script.nameofscript.  But I do not want to hard code the script name.

Thoughts!

S Mummert
Wednesday, February 18, 2004

Would call by name not do it at that level?

CallByName(WebBrowser.Document.Script, "nameoffunc", vbWhutever, strParams)

Alex Butler
Thursday, April 29, 2004

*  Recent Topics

*  Fog Creek Home