(COM Standard Library required)
The COM Standard Library allows us to drill deeply into COM objects. The function below may make that a bit easier for you to use. It parses the "dotted-path" of a COM object (using COM_Invoke to obtain the appropriate pointer to each parent, where objects in a hierarchy are separated by "."). In this example,pBody2 := COM_InvokeDeep(pweb, "document.frames[1].document.body")pBody2 returns a pointer to the body portion of the HTML document located in the second frame of the loaded web page, where pweb is a pointer to the parent IID_IHTMLWindow2.
COM_InvokeDeep can make both method calls - for example, document.getElementsByTagName[span] - and element[item] calls - for example, document.childNodes[1]
For the last loop (the element after the last period), one can pass up to 8 additional arguments to the COM_Invoke command (Note: one can pass up to 10 arguments to a COM object with COM_Invoke, but COM_InvokeDeep will consume up to two of those arguments).
Rules for use:
a) If there's a period in an element's name, don't use that name. Instead, refer to it by its element ordinal. So, for example, one will occasionally find frames in web pages that are named like the following: this.isanoddly.named.frame . Since COM_InvokeDeep (obviously) parses on the periods, returned pointers will be invalid. Instead, identify the frame by its ordinal: document.frames[0] (for first frame in the document)
Don't use parentheses () inside the "dotted-path" - use square brackets [] instead.
c) Don't put quotes (single or double) inside the brackets when passing a parameter to a COM object's method:
bad: document.getElementsByTagName["span"] or document.getElementsByTagName['span']
good: document.getElementsByTagName[span][/list]Sean's COM_Invoke runs the guts of this function. COM_InvokeDeep was developed by lots of folks in the AHK community in this thread (wOxxOm, daonlyfreez, Lexikos, me). Hope it's helpful to you.
; Usage: ; res := COM_InvokeDeep(res, dotted-path, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) ; Example: ; pBody2 := COM_InvokeDeep(pweb, "document.frames[1].document.body") ; (returns pointer to the body portion of the HTML document located in the second frame on the ; loaded web page, where pweb is a pointer to the parent IID_IHTMLWindow2. COM_InvokeDeep(obj, path, arg1="vT_NoNe", arg2="vT_NoNe", arg3="vT_NoNe", arg4="vT_NoNe", arg5="vT_NoNe", arg6="vT_NoNe", arg7="vT_NoNe", arg8="vT_NoNe") { res := obj COM_AddRef(res) ; compensate for loop's Release() PathCt := 0 Loop, Parse, Path, . { PathCt++ } Loop, Parse, Path, ., ] { prop := A_LoopField value = StringGetPos, i, A_LoopField, [ IfEqual, ErrorLevel, 0 ; contains index { StringLeft, prop, A_LoopField, %i% StringMid, value, A_LoopField, % i+2 } If (value != "") ; contains index or parameter passed to a method, enclosed in "[]" { If (prop = "item") or (RegExMatch(value, "^[0-9]+$") = false) ; "item" already specified, or method call { If (A_Index < PathCt) propobj := COM_Invoke(res, prop, value) Else propobj := COM_Invoke(res, prop, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) COM_Release(res) res := propobj } Else { propobj := COM_Invoke(res, prop) If (A_Index < PathCt) itemobj := COM_Invoke(propobj, "Item", value) Else itemobj := COM_Invoke(propobj, "Item", value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) COM_Release(res) COM_Release(propobj) res := itemobj } } Else { If (A_Index < PathCt) propobj := COM_Invoke(res, prop) Else propobj := COM_Invoke(res, prop, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) COM_Release(res) res := propobj } if !res ; no sense in continuing - object not found (returns 0 or null) break } Return res }