i was stuck with the same problem, this thread has the solution. and my project can proceed now. thank you.
here is an extract of my code, i hope it has gone a little bit further by eliminating the excessive triggers of the event (text selection changed).
Code: Select all
#Persistent
theHandle := IUIAutomationEventHandler_new()
SubscribeTextSelectionChangedEvent(theHandle, "ahk_exe msedge.exe")
OnExit("ButtWiping")
Return
ButtWiping() {
global theHandle
UnsubscribeTextSelectionChangedEvent(theHandle, "ahk_exe msedge.exe")
ObjRelease(theHandle)
}
; ☟ ☟ ☟ ☟ ☟ written by qwerty12 (https://www.autohotkey.com/boards/viewtopic.php?p=170967#p170967)
IUIAutomationEventHandler_new() {
vtbl := IUIAutomationEventHandler_Vtbl()
evt := DllCall("GlobalAlloc", "UInt", 0x0000, "Ptr", A_PtrSize + 4, "Ptr")
if (!evt)
return 0
NumPut(vtbl, evt+0,, "Ptr")
NumPut(1, evt+0, A_PtrSize, "UInt") ; thanks, just me
return evt
}
IUIAutomationEventHandler_Vtbl(ByRef vtblSize := 0) {
static vtable
if (!VarSetCapacity(vtable)) {
extfuncs := ["QueryInterface", "AddRef", "Release", "HandleAutomationEvent"]
VarSetCapacity(vtable, extfuncs.Length() * A_PtrSize)
for i, name in extfuncs
NumPut(RegisterCallback("IUIAutomationEventHandler_" . name), vtable, (i-1) * A_PtrSize)
}
if (IsByRef(vtblSize))
vtblSize := VarSetCapacity(vtable)
return &vtable
}
IUIAutomationEventHandler_QueryInterface(this_, riid, ppvObject) {
static IID_IUnknown, IID_IUIAutomationEventHandler
if (!VarSetCapacity(IID_IUnknown))
VarSetCapacity(IID_IUnknown, 16), VarSetCapacity(IID_IUIAutomationEventHandler, 16)
,DllCall("ole32\CLSIDFromString", "WStr", "{00000000-0000-0000-C000-000000000046}", "Ptr", &IID_IUnknown)
,DllCall("ole32\CLSIDFromString", "WStr", "{146c3c17-f12e-4e22-8c27-f894b9b79c69}", "Ptr", &IID_IUIAutomationEventHandler)
if (DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IUIAutomationEventHandler) || DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IUnknown)) {
NumPut(this_, ppvObject+0, "Ptr")
IUIAutomationEventHandler_AddRef(this_)
return 0 ; S_OK
}
NumPut(0, ppvObject+0, "Ptr")
return 0x80004002 ; E_NOINTERFACE
}
IUIAutomationEventHandler_AddRef(this_) {
NumPut((_refCount := NumGet(this_+0, A_PtrSize, "UInt") + 1), this_+0, A_PtrSize, "UInt")
return _refCount
}
IUIAutomationEventHandler_Release(this_) {
_refCount := NumGet(this_+0, A_PtrSize, "UInt")
if (_refCount > 0) {
_refCount -= 1
NumPut(_refCount, this_+0, A_PtrSize, "UInt")
if (_refCount == 0)
DllCall("GlobalFree", "Ptr", this_, "Ptr")
}
return _refCount
}
IUIAutomationEventHandler_HandleAutomationEvent(this_, sender, eventId) {
; ☝ ☝ ☝ ☝ ☝ written by qwerty12 (https://www.autohotkey.com/boards/viewtopic.php?p=170967#p170967)
global EventOccupied := False
If EventOccupied
Return
Else SetTimer, EliminateStubbornExcess, -1
}
EliminateStubbornExcess() {
static priorStamp, priorText
global EventOccupied
EventOccupied := True
While, GetKeyState("LButton", "P")
Sleep, 100
If ((theText := GetTheText()) = priorText) and A_TickCount - priorStamp < 1000
Return
ActualHandling(theText) ; actual work to do upon selection changed
priorText := theText
priorStamp := A_TickCount
EventOccupied := False
}
GetTheText() {
; ☟ quick-n-dirty code (yet quite reliable)
ClipSave(True)
Clipboard := ""
Send, ^c
Sleep, 300
theText := Clipboard
ClipSave(False)
Return theText
}
ClipSave(Yes) {
static ClipSave
If Yes
ClipSave := ClipboardAll
Else Clipboard := ClipSave
}
ActualHandling(theText) { ; actual work to do upon selection changed
If StrLen(theText)
ToolTip, >>>%theText%<<<
Else ToolTip
}
SubscribeTextSelectionChangedEvent(theHandle, wTitle*) { ;based on the script written by Descolada (https://www.autohotkey.com/boards/viewtopic.php?p=459451&sid=dde6b407875aadff59bc35e0864f63e4#p459451)
ErrorLevel := 0
if !(wId := WinExist(wTitle*)) {
ErrorLevel := 1
return
}
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", wId, "ptr*", elementMain) ; IUIAutomation::ElementFromHandle
DllCall(NumGet(NumGet(IUIAutomation+0)+32*A_PtrSize), "ptr", IUIAutomation, "int", 20014, "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", 0, "ptr", theHandle) ; IUIAutomation::AddAutomationEventHandler
ObjRelease(elementMain)
ObjRelease(IUIAutomation)
}
UnsubscribeTextSelectionChangedEvent(theHandle, wTitle*) { ;based on the script written by Descolada (https://www.autohotkey.com/boards/viewtopic.php?p=459451&sid=dde6b407875aadff59bc35e0864f63e4#p459451)
ErrorLevel := 0
if !(wId := WinExist(wTitle*)) {
ErrorLevel := 1
return
}
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", wId, "ptr*", elementMain) ; IUIAutomation::ElementFromHandle
DllCall(NumGet(NumGet(IUIAutomation+0)+33*A_PtrSize), "ptr", IUIAutomation, "int", 20014, "ptr", elementMain, "ptr", theHandle) ; IUIAutomation::RemoveAutomationEventHandler
ObjRelease(elementMain)
ObjRelease(IUIAutomation)
}
cheers.