I've managed to get the code working, to achieve a drag-and-drop programmatically. You add it to the bottom of IDropTarget_Sample.ahk.
I tried to use the same code to drag-and-drop to an external program, namely the very small program spek.exe, but it didn't work. In case it's possible to fix this script, and drag-and-drop to external programs using AutoHotkeyMini.dll.
Code: Select all
#Persistent
;[get x64 and x32 versions of AutoHotkeyMini.dll]
;GitHub - HotKeyIt/ahkdll-v1-release: AutoHotkey_H v1 release
;https://github.com/HotKeyIt/ahkdll-v1-release
vDir := "C:\Program Files\AutoHotkey"
if (A_PtrSize = 8)
vPathDll := vDir "\AutoHotkeyMiniU64.dll"
else
vPathDll := vDir "\AutoHotkeyMiniU32.dll"
;==================================================
q::
WinGet, hWnd, ID, A
WinGet, vPID, PID, % "ahk_id " hWnd
WinGet, vPName, ProcessName, % "ahk_id " hWnd
if !(vPName = "spek.exe")
return
pDropTarget := DllCall("user32\GetProp", Ptr,hWnd, Str,"OleDropTargetInterface", Ptr)
MsgBox, % pDropTarget
vPaths := A_ScriptFullPath
vScript = ;continuation section
(`
pDropTarget := %pDropTarget%
pVTBLDT := NumGet(pDropTarget + 0, "UPtr")
vPaths := "%vPaths%"
;===============
;create hDrop
;GMEM_ZEROINIT := 0x40, GMEM_MOVEABLE := 0x2
hDrop := DllCall("GlobalAlloc", UInt,0x42, UPtr,20+(StrLen(vPaths)+2)*2, Ptr)
pDrop := DllCall("GlobalLock", Ptr,hDrop, Ptr)
;DROPFILES struct
NumPut(20, pDrop+0, 0, "UInt")
NumPut(1, pDrop+16, 0, "UInt")
;e.g. CF_HDROP with 3 paths: 'path1 null path2 null path3 null null'
vOffset := 20
Loop, Parse, vPaths, `n, `r
if !(A_LoopField = "")
vOffset += StrPut(A_LoopField, pDrop+vOffset, StrLen(A_LoopField)+1, "UTF-16")*2
;CF_HDROP := 0xF
DllCall("GlobalUnlock", Ptr,hDrop)
;===============
;TYMED_HGLOBAL := 0x1
VarSetCapacity(STGMEDIUM, A_PtrSize=8?24:12, 0)
NumPut(0x1, &STGMEDIUM, 0, "UInt") ;tymed
NumPut(hDrop, &STGMEDIUM, A_PtrSize=8?8:4, "Ptr")
;NumPut(0, &STGMEDIUM, A_PtrSize=8?16:8, "Ptr") ;*pUnkForRelease
;CF_HDROP := 0xF
;DVASPECT_CONTENT := 0x1
;TYMED_HGLOBAL := 0x1
VarSetCapacity(FORMATETC, A_PtrSize=8?32:20, 0)
NumPut(0xF, &FORMATETC, 0, "UShort") ;cfFormat
NumPut(0, &FORMATETC, A_PtrSize=8?8:4, "Ptr") ;*ptd
NumPut(0x1, &FORMATETC, A_PtrSize=8?16:8, "UInt") ;dwAspect
NumPut(-1, &FORMATETC, A_PtrSize=8?20:12, "Int") ;lindex
NumPut(0x1, &FORMATETC, A_PtrSize=8?24:16, "UInt") ;tymed
IID_IDataObject := "{0000010e-0000-0000-C000-000000000046}"
VarSetCapacity(IID, 16, 0)
DllCall("ole32\IIDFromString", WStr,IID_IDataObject, Ptr,&IID)
DllCall("shell32\SHCreateDataObject", Ptr,0, UInt,0, Ptr,0, Ptr,0, Ptr,&IID, PtrP,pDataObj)
pVTBL := NumGet(pDataObj + 0, "UPtr")
DllCall(NumGet(pVTBL+7*A_PtrSize, "UPtr"), Ptr,pDataObj, Ptr,&FORMATETC, Ptr,&STGMEDIUM, Int,1) ;SetData
;MK_LBUTTON := 0x1
VarSetCapacity(POINTL, 8, 0)
;NumPut(200, &POINTL, 0, "UInt")
;NumPut(200, &POINTL, 4, "UInt")
;DllCall(NumGet(pVTBLDT+6*A_PtrSize, "UPtr"), Ptr,pDropTarget, Ptr,pDataObj, UInt,0x1, Ptr,&POINTL, UInt,0) ;Drop
DllCall(NumGet(pVTBLDT+6*A_PtrSize, "UPtr"), Ptr,pDropTarget, Ptr,pDataObj, UInt,0x1, UInt64,0, UInt,0) ;Drop
return
)
;Clipboard := vScript
;MsgBox
rThread := InjectAhkDll(vPID, vPathDll)
rThread.Exec(vScript)
rThread := ""
return
;==================================================
;[original version of InjectAhkDll]
;[SOLVED]get other process's working dir - Page 3 - Ask for Help - AutoHotkey Community
;https://autohotkey.com/board/topic/85304-solvedget-other-processs-working-dir/page-3#entry544650
;[get x64 and x32 versions of AutoHotkeyMini.dll]
;GitHub - HotKeyIt/ahkdll-v1-release: AutoHotkey_H v1 release
;https://github.com/HotKeyIt/ahkdll-v1-release
;by HotKeyIt (modified version by jeeswg to not require _Struct.ahk)
InjectAhkDll(PID,dll="AutoHotkey.dll",script=0)
{
static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
,base:={__Call:"InjectAhkDll",__Delete:"InjectAhkDll"},FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
static TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))
if IsObject(PID)
{
if (dll!="Exec" && script)
return DllCall("MessageBox","PTR",0,"Str","Only Exec method can be used here!","STR","Error","UInt",0)
hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
if !hProc
return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID.PID,"STR","Error","UInt",0)
if (!script) ; Free Library in remote process (object is being deleted)
{
; Terminate the thread in ahkdll
hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
,DllCall("CloseHandle", "PTR", hThread)
; Free library in remote process
hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
return
}
nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
,StrPut(script,&nScript)
; Reserve memory in remote process where our script will be saved
if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
,DllCall("CloseHandle", "PTR", hProc)
; Write script to remote process memory
DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
; Start execution of code
hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
if !hThread
{
DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
,DllCall("CloseHandle", "PTR", hProc)
return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
}
; Wait for thread to finish
DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
if !lpExitCode
return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
DllCall("CloseHandle", "PTR", hThread)
,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
,DllCall("CloseHandle", "PTR", hProc)
return
}
else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
return DllCall("MessageBox","PTR",0,"Str","Could not find " dll " library.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
else
{
hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
DllCall("CloseHandle","PTR",hProc)
}
; Open Process to PID
hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
if !hProc
return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID,"STR","Error","UInt",0)
; Reserve some memory and write dll path (ANSI)
nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
,StrPut(dll,&nDir,"CP0")
; Reserve memory in remote process
if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
; Write dll path to remote process memory
DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)
; Start new thread loading our dll
hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
if !hThread
{
DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
,DllCall("CloseHandle", "PTR", hProc)
return DllCall("MessageBox","PTR",0,"Str","Could not load " dll " in remote process.","STR","Error","UInt",0)
}
; Wait for thread to finish
DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
; Get Exit code returned by thread (HMODULE for our dll)
DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)
; Close Thread
DllCall("CloseHandle", "PTR", hThread)
if (A_PtrSize=8)
{ ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
; Take a snapshot of all modules in the specified process.
hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
if ( hModuleSnap != INVALID_HANDLE_VALUE )
{
; reset hModule and set the size of the structure before using it.
NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &me32, 0, "UInt") ;dwSize ;W:1080:1064, A:564:548
; Retrieve information about the first module,
; and exit if unsuccessful
if ( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", &me32 ) )
{
; Free memory used for passing dll path to remote thread
DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
return false
}
; Now walk the module list of the process,and display information about each module
while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", &me32 ) )
if (StrGet(&me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
{
hModule := NumGet(me32, A_PtrSize=8?40:28, "Ptr") ;hModule
break
}
DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
}
}
hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
; Calculate pointer to ahkdll and ahkExec functions
ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll
if script
{
nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
,StrPut(script,&nScript)
; Reserve memory in remote process where our script will be saved
if !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
,DllCall("CloseHandle", "PTR", hProc)
; Write script to remote process memory
DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
}
else
pBufferScript:=0
; Run ahkdll function in remote thread
hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
if !hThread
{ ; could not start ahkdll in remote process
; Free memory used for passing dll path to remote thread
DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
DllCall("CloseHandle", "PTR", hProc)
return DllCall("MessageBox","PTR",0,"Str","Could not start ahkdll in remote process","STR","Error","UInt",0)
}
DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
; Release memory and handles
DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
DllCall("CloseHandle", "PTR", hThread)
DllCall("CloseHandle", "PTR", hProc)
if !lpExitCode ; thread could not be created.
return DllCall("MessageBox","PTR",0,"Str","Could not create a thread in remote process","STR","Error","UInt",0)
return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}
;==================================================