, your tweak may have made the problem somewhat lesser, but still not significant per my testing. and after further investigation, i think i have found the main cause of it. and attained hundred percent success rate (as far as the tooltip is shown.) the uia + the slowness (of my own machine) are just the small part of the problem, the bigger part of the problem (i just discovered) is that the SysDragImage Destroy Event doesn't get thru sometimes, somehow. (and hence, a possibility is, neither uia nor the slowness are involved at all, probably just the SysDragImage Create Event also doesn't get thru sometimes.)
so, here is the revised version of my code.
Code: Select all
; materials referenced mainly: https://stackoverflow.com/questions/2947139/how-to-know-user-is-dragging-something-when-the-cursor-is-not-in-my-window, https://www.autohotkey.com/board/topic/85231-lib-hook-winevents-to-catch-windows-creationdestruction/, https://stackoverflow.com/questions/13222689/how-do-i-insert-formatted-text-using-autohotkey, https://www.autohotkey.com/board/topic/74670-class-winclip-direct-clipboard-manipulations/, https://stackoverflow.com/questions/7894772/writing-unicode-to-rtf-file, https://www.autohotkey.com/boards/viewtopic.php?p=459451&sid=dde6b407875aadff59bc35e0864f63e4#p459451, https://www.autohotkey.com/boards/viewtopic.php?p=468059&sid=702a6e5619dce3f22bda11a2ec84c4eb#p468059
#Persistent
DetectHiddenWindows, On
OnExit, QUIT
global DragStamp := False
DllCall("CoInitialize", UInt,0)
hWinEventHook := DllCall("SetWinEventHook", UInt,0x8000, UInt,0x8001, UInt,0, UInt,RegisterCallback("WinEventHandler"), UInt,0, UInt,0, UInt,0, UInt) ; EVENT_OBJECT_CREATE:=0x8000, EVENT_OBJECT_DESTROY:=0x8001
Return
QUIT:
UnhookWinEvent(hWinEventHook)
ExitApp
WinEventHandler(hWinEventHook, event, hWnd, idObject, idChild, dwEventThread, dwmsEventTime) {
static LinkTitle, url
WinGetClass, wClass, ahk_id %hWnd%
If wClass = SysDragImage
If (event == 0x8000) ;drag started
If (A_TickCount - DragStamp > 29999) and (o := GetFocusedElement()) and not (o.Value = GetURL("A")) and SubStr(o.Value, 1, 8) = "https://"
{ LinkTitle := o.Name, url := o.Value, DragStamp := A_TickCount, ClipSave(True), Clipboard := "Drag & Drop Operation In Effect:`n`nTitle`t" LinkTitle "`n`nURL`t" url
SetTimer, MonitorLButton, -1
}Else{}
Else ;dropped
{ While, GetKeyState("LButton", "P")
Sleep, 100
Sleep, 500
ReplaceTheLink(LinkTitle, url)
}
Else If wClass = Static
{ WinGetTitle, wt, ahk_id %hWnd%
If SubStr(wt, 1, 29) = "Do you want to open this link"
If (event == 0x8000)
{ Send, n
If RegExMatch(wt, "https://.+$", url)
SetURL(StrReplace(url, "`n"), True, "ahk_exe msedge.exe")
}
}
}
ClipSave(Yes) {
static ClipSave
If Yes
ClipSave := ClipboardAll
Else Clipboard := ClipSave
}
MonitorLButton() {
static pX, pY, pT
If GetKeyState("LButton", "P")
{ MouseGetPos, x, y
If not (x "," y == pX "," pY)
{ ToolTip, Drag & Drop Operation In Effect
pX := x, pY := y, pT := A_TickCount
}Else If A_TickCount - pT > 500
{ ToolTip, %Clipboard%
pT := A_TickCount
}SetTimer, MonitorLButton, -100
}Else
{ Sleep, 500
RegExMatch(Clipboard, "Title\t\K[^\n]*(?=\n)", LinkTitle), RegExMatch(Clipboard, "URL\t\K[^\n]*$", url), ReplaceTheLink(LinkTitle, url)
ExitDragDrop()
}
}
ExitDragDrop() {
ToolTip
ClipSave(DragStamp := False)
}
ReplaceTheLink(LinkTitle, url) {
static priorStamp := False
If A_TickCount - priorStamp < 3000
Return
priorStamp := A_TickCount
MouseGetPos,,, wHwnd
WinGetTitle, wt, ahk_id %wHwnd%
If InStr(wt, " - WordPad")
{ Send, ^z
WinClip.Clear(), WinClip.SetRTF("{\rtf>>>{\field{\*\fldinst{HYPERLINK " url " }}{\fldrslt{" Conv4RTF(LinkTitle) "}}}<<<}"), WinClip.Paste()
Send, {Enter}
MsgBox,, Manipulation, Done, 1
}
}
UnhookWinEvent(hWinEventHook) {
DllCall("UnhookWinEvent", UInt,hWinEventHook)
DllCall("CoUninitialize")
}
GetURL(wTitle*) { ;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
NumPut(addressbarStrPtr := DllCall("oleaut32\SysAllocString", "wstr", "Address and search bar", "ptr"),(VarSetCapacity(addressbar,8+2*A_PtrSize)+NumPut(8,addressbar,0,"short"))*0+&addressbar,8,"ptr")
DllCall("oleaut32\SysFreeString", "ptr", addressbarStrPtr)
if (A_PtrSize = 4) {
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "int64", NumGet(addressbar, 0, "int64"), "int64", NumGet(addressbar, 8, "int64"), "ptr*", addressbarCondition) ; IUIAutomation::CreatePropertyCondition
} else {
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "ptr", &addressbar, "ptr*", addressbarCondition) ; IUIAutomation::CreatePropertyCondition
}
DllCall(NumGet(NumGet(elementMain+0)+5*A_PtrSize), "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", addressbarCondition, "ptr*", currentURLElement) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(currentURLElement+0)+10*A_PtrSize),"ptr",currentURLElement,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+¤tURL) ;IUIAutomationElement::GetCurrentPropertyValue
ObjRelease(currentURLElement)
ObjRelease(elementMain)
ObjRelease(IUIAutomation)
return StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
}
GetFocusedElement() { ;based on the script by Descolada (https://www.autohotkey.com/boards/viewtopic.php?p=459451&sid=dde6b407875aadff59bc35e0864f63e4#p459451)
IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
DllCall(NumGet(NumGet(IUIAutomation+0)+8*A_PtrSize), "ptr",IUIAutomation, "ptr*",element) ;IUIAutomation::GetFocusedElement
DllCall(NumGet(NumGet(element+0)+23*A_PtrSize), "ptr", element, "ptr*", name) ;IUIAutomationElement::CurrentName
DllCall(NumGet(NumGet(element+0)+10*A_PtrSize), "ptr", element, "uint",30045, "ptr", (VarSetCapacity(val,8+2*A_PtrSize)+NumPut(0,val,0,"short")+NumPut(0,val,8,"ptr"))*0+&val) ;IUIAutomationElement::GetCurrentPropertyValue
ObjRelease(element)
ObjRelease(IUIAutomation)
Return {"Name":StrGet(name,"utf-16"), "Value":StrGet(NumGet(val,8,"ptr"),"utf-16")}
}
Conv4RTF(t) {
Loop, Parse, t
Result .= Asc(A_LoopField) > 127 ? "\u" Asc(A_LoopField) "?" : A_LoopField
Return Result
}
SetURL(theURL, NewTab, 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
NumPut(addressbarStrPtr := DllCall("oleaut32\SysAllocString", "wstr", "Address and search bar", "ptr"),(VarSetCapacity(addressbar,8+2*A_PtrSize)+NumPut(8,addressbar,0,"short"))*0+&addressbar,8,"ptr")
DllCall("oleaut32\SysFreeString", "ptr", addressbarStrPtr)
if (A_PtrSize = 4) {
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "int64", NumGet(addressbar, 0, "int64"), "int64", NumGet(addressbar, 8, "int64"), "ptr*", addressbarCondition) ; IUIAutomation::CreatePropertyCondition
} else {
DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "ptr", &addressbar, "ptr*", addressbarCondition) ; IUIAutomation::CreatePropertyCondition
}
DllCall(NumGet(NumGet(elementMain+0)+5*A_PtrSize), "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", addressbarCondition, "ptr*", currentURLElement) ; IUIAutomationElement::FindFirst
DllCall(NumGet(NumGet(currentURLElement+0)+16*A_PtrSize),"ptr",currentURLElement,"int",10002,"ptr*",URLValuePattern) ; IUIAutomationElement::GetCurrentPattern
If NewTab
{ jswo := "javascript:window.open()"
DllCall(NumGet(NumGet(URLValuePattern+0)+3*A_PtrSize),"ptr",URLValuePattern,"ptr",&jswo) ; IUIAutomationValuePattern::SetValue
Send, {Enter}
Sleep, 500
}DllCall(NumGet(NumGet(URLValuePattern+0)+3*A_PtrSize),"ptr",URLValuePattern,"ptr",&theURL) ; IUIAutomationValuePattern::SetValue
Send, {Enter}
DllCall(NumGet(NumGet(currentURLElement+0)+10*A_PtrSize),"ptr",currentURLElement,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+¤tURL) ; IUIAutomationElement::GetCurrentPropertyValue
ObjRelease(URLValuePattern)
ObjRelease(currentURLElement)
ObjRelease(elementMain)
ObjRelease(IUIAutomation)
return StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
}
#Include WinClipAPI.ahk
#Include WinClip.ahk
2022-06-20 fixed a careless bug, and refined the method for handling "sysdragimage destroy event sometimes failed to callback".