This code reproduces the issue:
Code: Select all
#Requires AutoHotkey v2.0
Persistent
excel := ComObject("Excel.Application")
excel.Visible := true
HotIf((*) => excel.Visible)
Hotkey("a", (key) => MsgBox(key))
I noted during testing, HotIf conditions specified in JavaScript through the ahk-jk project work perfectly as expected. I don't understand all of the code in the integration layer, but I suspect it's to do with how AHK implements JsRT rather than working by IDispatch directly.
This is the original Python code I am trying to make work, using thqby's AutoHotkey.dll. You'll note, hotkey a works great but hotkey b triggers an exception dialog.
Code: Select all
import ctypes
import pythoncom
import win32com.client
import win32com.server.policy
class AhkFuncObjectProxy(win32com.server.policy.DynamicPolicy):
_com_interfaces_ = [pythoncom.IID_IDispatch]
def __init__(self, target):
self._wrap_(self)
self.target = target
def _dynamic_(self, name, lcid, wFlags, args):
from inspect import signature
if name == "MinParams" and (wFlags & pythoncom.DISPATCH_PROPERTYGET):
return len(signature(self.target).parameters)
if name == "MaxParams" and (wFlags & pythoncom.DISPATCH_PROPERTYGET):
return len(signature(self.target).parameters)
if name == "_value_" and (wFlags & pythoncom.DISPATCH_METHOD):
return self.target(*args)
return 0
o = ctypes.CDLL("./AutoHotkey64.dll")
o.ahkFunction.restype = ctypes.c_wchar_p
thread = o.NewThread("""
Persistent
NumPut("Int64", 0x20400, "Int64", 0x46000000000000c0, IID_IDispatch := Buffer(16))
marshal(name) => (DllCall("ole32\CoMarshalInterThreadInterfaceInStream", "ptr", IID_IDispatch, "ptr", ObjPtr(%name%), "ptr*", &pstm := 0, "int"), pstm)
""", 0, 0)
def retrieve(name):
pstream = o.ahkFunction("marshal", name, 0, 0, 0, 0, 0, 0, 0, 0, 0, thread)
stream = pythoncom.ObjectFromAddress(int(pstream), pythoncom.IID_IStream)
dispatch = pythoncom.CoGetInterfaceAndReleaseStream(stream, pythoncom.IID_IDispatch)
return win32com.client.__WrapDispatch(dispatch)
def ahkFunction(func):
return pythoncom.WrapObject(
AhkFuncObjectProxy(func),
pythoncom.IID_IDispatch,
pythoncom.IID_IDispatch
)
ahk_Hotkey = retrieve("Hotkey")
ahk_HotIf = retrieve("HotIf")
def hotkey(keyname):
def hotkey_decorator(func):
ahk_Hotkey(keyname, ahkFunction(func))
return func
return hotkey_decorator
@hotkey('a')
def onA(name):
print('Handling', name)
ahk_HotIf(ahkFunction(lambda name: False))
@hotkey('b')
def onB(name):
print('Handling', name)
while True:
pythoncom.PumpWaitingMessages()
Code: Select all
#Requires AutoHotkey v2.0
Persistent
Condition(name) => true
NumPut("Int64", 0x20400, "Int64", 0x46000000000000c0, IID_IDispatch := Buffer(16))
lResult := DllCall("OleAcc\LresultFromObject", "Ptr", IID_IDispatch, "Ptr", 0, "Ptr", ObjPtr(Condition), "Ptr")
exec := ComObject("WScript.Shell").Exec('"' A_AhkPath '" * ' lResult)
exec.StdIn.Write "
(
NumPut("Int64", 0x20400, "Int64", 0x46000000000000c0, IID_IDispatch := Buffer(16))
DllCall("oleacc\ObjectFromLresult", "Ptr", A_Args[1], "Ptr", IID_IDispatch, "Ptr", 0, "Ptr*", &pObj := 0)
condition := ComValue(9, pObj)
HotIf(condition)
HotKey("a", (key) => MsgBox(key))
)"
exec.StdIn.Close