Javascript Wrapper (similar to Node.js)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Aurelain
Posts: 34
Joined: 02 Sep 2014, 15:37

Javascript Wrapper (similar to Node.js)

02 Sep 2014, 16:54

In order to add FileSystem access (and more) to Javascript, I wanted to use AutoHotkey as a proxy. In my view, this would open up a whole new universe of opportunities :).
The problem is I'm stuck at communicating synchronously between the browser (ActiveX IE) and the wrapper (AHK).

Firstly, I know we can react to events inside the browser using the ComObjConnect method. See the bare minimum code below:

Upon user event:

Code: Select all

Gui Add, ActiveX, w800 h600 vwb, Shell.Explorer
wb.Navigate("about:blank")
wb.document.write("<input type='button' id='btn' value='Say Hi!'>")
btn := wb.document.All.btn
ComObjConnect(btn, "btn_")
btn_onclick() {
     MsgBox, AHK says Hi!
}
Gui Show
Upon browser events, optionally triggered by Javascript:

Code: Select all

Gui Add, ActiveX, w800 h600 vwb, Shell.Explorer
wb.Navigate("about:blank")
ComObjConnect(wb, new wb_events)
wb.document.write("<script>document.location.href='#hello';</script>")
class wb_events {
   __Call(p*) {
		if (p[1] == "BeforeNavigate2") { 
			 MsgBox, AHK says Hi!
		}
   }
}
Gui Show
However, what I want is a more direct connection to AHK from Javascript code, so as not to rely on events (asynchronous), but on direct function calls (synchronous).
That would allow the following code in Javascript:
line 1: window.test = 1;
line 2: API.callAHK(); // here AHK applies a change of value on "window.test"
line 3: alert(window.test); // JS outputs a different value (not 1)


Things I have tried:
  1. Triggering a browser event (let's say "BeforeNavigate2") and hoping AHK catches it before the next line of code in JS. It did't, it caught it after a few miliseconds.
  2. Manually triggering the "click" event of an element that AHK has hooked. I had high hopes for this, because in Javascript the events are triggered instantaneously, even before the next line of code is processed. However, the manual trigger DID NOT arrive in AHK! See sample code below, which uses the modern IE engine:

    Code: Select all

    FixIE(true)
    Gui Add, ActiveX, w800 h600 vwb, Shell.Explorer
    wb.Navigate("about:blank")
    blob =
    (
        <script>
            function manualTrigger(){
                var evt = document.createEvent('MouseEvents');
                evt.initEvent("click", true, true);
                document.getElementById('btn').dispatchEvent(evt);
            }
        </script>
        <input type='button' id='btn' onclick='alert("JS says Hi!")' value='BUTTON'>
        <input type='button' onclick='manualTrigger()' value='BUTTON'>
    )
    wb.document.write(blob)
    btn := wb.document.All.btn
    ComObjConnect(btn, "btn_")
    btn_onclick() {
        MsgBox, AHK says Hi!
    }
    Gui Show
    
    
    ;http://www.autohotkey.com/board/topic/93660-embedded-ie-shellexplorer-render-issues-fix-force-it-to-use-a-newer-render-engine/
    FixIE(Apply=True, Version="", ExeName="")
    {
    static Key := "Software\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
    , Versions := {7:7000, 8:8888, 9:9999, 10:10001, 11:11001}
    if !(Version := Versions[Version])
    Version := 0 ; Disable browser emulation
    if !ExeName
    {
    if A_IsCompiled
    ExeName := A_ScriptName
    else
    SplitPath, A_AhkPath, ExeName
    }
    if Apply
    RegWrite, REG_DWORD, HKCU, %Key%, %ExeName%, %Version%
    else
    RegDelete, HKCU, %Key%, %ExeName%
    }
    
3. Just for laughs, I tried assigning to a Javascript Function (referenced by AHK as a COM object) the value of an AHK Function. I know, a naive way of looking at things :)... It obviously didn't work.

Code: Select all

Gui Add, ActiveX, w800 h600 vwb, Shell.Explorer
wb.Navigate("about:blank")
wb.document.write("<script>window.test = function(){alert('JS says Hi!');}</script><input type='button' onclick='test()' value='Say Hi!'>")
wb.document.parentwindow.test := Func("hello")
hello(){
    MsgBox, AHK says Hi!
}
Gui Show
Sooo... any ideas?
Aurelain
Posts: 34
Joined: 02 Sep 2014, 15:37

It works!

03 Sep 2014, 01:46

Thanks Lexikos and Coco!
I think I have everything I need to get started. I'll post a new thread if something worthwhile gets produced.
The final working sample is below:

Code: Select all

#Include ComDispatch.ahk
#Include ComDispTable.ahk
#Include ComVar.ahk
#SingleInstance, Force
Gui Add, ActiveX, w800 h600 vwb, Shell.Explorer
wb.Navigate("about:blank")
blob =
(
<script>
	var ahk; // store ComDispatch() object here
	function test(){
		window.testValue = 1;
		alert("Before AHK: " + window.testValue)
		ahk.Message(2);
		alert("After AHK: " + window.testValue);
	}
</script>
<input type='button' onclick='test()' value='Run test()'>
)
wb.document.write(blob)
wb.document.parentWindow.ahk := ComDispatch("", "Message")
Message(this, msg) {
	global wb
	wb.document.parentWindow.testValue := msg
}
Gui Show
return
GuiClose:
ExitApp
For the libraries, get them from Coco's thread.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Joey5 and 229 guests