Post your working scripts, libraries and tools
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica


29 Nov 2014, 07:11

Dynamically put or delete(see remarks) a property in the window(HTMLWindow) object's global namespace
Edit: I just realized that this can also be used for COM objects that implement IDispatchEx - should be renamed to something like DispEx_PutProperty or similar... :)

ScriptControl has the AddObject method which is very handy(esp. when using ComDispatch/ComDispatch0). This is similar to the AddObject method.

Syntax: dispid := HTMLWindow_PutVar( window, name [ , value ] )
  • Requires ComDispatch/ComDispatch0 if value is an AHK object.
edit: (fixed) value is now set after calling InvokeEx

Code: Select all

HTMLWindow_PutVar(window, name, value*)
	DISPID := "" ;// for #Warn
	;// Query window object for IDispatchEx interface -
	if pIDispatchEx := ComObjQuery(window, "{A6EF9860-C720-11D0-9337-00A0C90DCAA9}") ;// IID_IDispatchEx
		GetDispID := NumGet(NumGet(pIDispatchEx + 0) + 7*A_PtrSize) ;//
		if !DllCall(GetDispID, "Ptr", pIDispatchEx, "Str", name, "UInt", 2, "Int*", DISPID) ;// fdexNameEnsure:=0x00000002
			arr := ComObjArray(0xC, 1) ;// VT_VARIANT:=0xC
			pVARIANTARG := NumGet(ComObjValue(arr) + 12 + (A_PtrSize == 8 ? 4 : 0)) ;// + padding
			; OR VarSetCapacity(VARIANTARG, 8 + 2*A_PtrSize, 0) ;//

			VarSetCapacity(DISPPARAMS, 16, 0) ;
			NumPut(1, NumPut(pVARIANTARG, DISPPARAMS), A_PtrSize, "UInt") ; *rgvarg, cArgs

			InvokeEx := NumGet(NumGet(pIDispatchEx + 0) + 8*A_PtrSize) ;//
			if !DllCall(InvokeEx, "Ptr", pIDispatchEx, "Int", DISPID
			          , "UInt", 1024, "UShort", 4, "Ptr", &DISPPARAMS ;// DISPATCH_PROPERTYPUT:=0x4 | DISPATCH_PROPERTYPUTREF:=0x8
			          , "Ptr", 0, "Ptr", 0, "Ptr", 0, "UInt")
			&& value[A_AhkVersion < "2" ? "MaxIndex" : "Length"]()
				window[name] := value[1]
	return DISPID
Syntax: bSuccess := HTMLWindow_DelVar( window, name [ , cs := false ] )
  • cs - case sensitivity
  • Somehow HRESULT returns S_FALSE which indicates that the member exists but cannot be deleted. I need to investigate further on this

Code: Select all

HTMLWindow_DelVar(window, name, cs:=false)
	pIDispatchEx := ComObjQuery(window, "{A6EF9860-C720-11D0-9337-00A0C90DCAA9}")
	DeleteMemberByName := NumGet(NumGet(pIDispatchEx + 0) + 9*A_PtrSize)
	grfdex := cs ? 0x00000001 : 0x00000008 ;// fdexNameCaseSensitive : fdexNameCaseInsensitive
	HRESULT := DllCall(DeleteMemberByName, "Ptr", pIDispatchEx, "WStr", name, "UInt", grfdex) ;//
	return !HRESULT ;// S_OK=0, S_FALSE=1

Code: Select all

#Include <HTMLWindow_PutVar>

Gui New
Gui Margin, 0, 0
Gui Add, ActiveX, w600 h400 vWB, Shell.Explorer

while (WB.ReadyState != 4)
	Sleep 10

html := "
<!DOCTYPE html>
<meta http-equiv='X-UA-Compatible' content='IE=edge'/>
<script type='text/javascript'></script>
<h1>Hello World</h1>

document := WB.Document, document.write(html), document.close()

window := document.parentWindow
HTMLWindow_PutVar(window, "Hello", "Hello World")

Gui Show

MsgBox %  window.Hello ;// show the value of the added property
Last edited by Coco on 06 Dec 2014, 02:07, edited 4 times in total.
User avatar
Posts: 8589
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada

Re: HTMLWindow_(Put|Del)Var()

29 Nov 2014, 12:05

Very nice!
Posts: 8577
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: HTMLWindow_(Put|Del)Var()

06 Dec 2014, 01:48

If GetDispID fails, your function fails to release pIDispatchEx.

What's CWebDisp()?

DelVar probably isn't very useful.
JScript has a delete operator which does not work at all like C++'s delete operator. Rather, JScript's delete operator removes an expando field from an object. It's pretty useless actually, because doing so does not free up any memory beyond simply clearing the field. Why not? Because implementers must ensure that if the property is re-added that it gets the same dispatch identifier the second time; someone might be caching the dispid. That means that the property bucket and its name has to be kept around, and worse, that every property bucket needs a flag that marks whether it's deleted or not. (The implementer must also ensure that property enumeration continues to work even if the enumerator -- see below -- is presently sitting on a property that was just deleted.) Use DeleteMemberByName or DeleteMemberByDispID in the unlikely event that you want to use this feature.
Source: Wherefore IDispatchEx? - Fabulous Adventures In Coding - Site Home - MSDN Blogs
For adding variables to a window object, I tend to do things like window.execScript("var Hello"), window.Hello := ..., or just design around it (i.e. avoid the need to add variables from outside JScript). I wrote a function like yours years ago, but never actually used it. It's outdated now.
Posts: 771
Joined: 29 Sep 2013, 20:37
GitHub: cocobelgica

Re: HTMLWindow_(Put|Del)Var()

06 Dec 2014, 01:57

lexikos wrote:If GetDispID fails, your function fails to release pIDispatchEx.
Oops, thanks for spotting that one.
lexikos wrote:What's CWebDisp()?
That shouldn't be in there, copy-paste artifact. :)

Thanks for the reference on JScript's delete operator...

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 30 guests