Each path needs to be terminated by a null character, with another null character at the end to terminate the list. Since AutoHotkey uses null characters to mark "end of string", none of AutoHotkey's string functions will work for this. We need to either:[*:2ps8ekaz]Copy the whole string to the allocated memory, then replace (using a Loop, NumGet and NumPut) each delimiter character with a null character; or
[*:2ps8ekaz]Use a parsing loop to copy each sub-string into the allocated memory, leaving a null character between each.The following uses the latter method:
FileToClipboard(PathToCopy)
{
; Expand to full paths:
Loop, Parse, PathToCopy, `n, `r
Loop, %A_LoopField%, 1
temp_list .= A_LoopFileLongPath "`n"
PathToCopy := SubStr(temp_list, 1, -1)
; Allocate some movable memory to put on the clipboard.
; This will hold a DROPFILES struct and a null-terminated list of
; null-terminated strings.
; 0x42 = GMEM_MOVEABLE(0x2) | GMEM_ZEROINIT(0x40)
hPath := DllCall("GlobalAlloc","uint",0x42,"uint",StrLen(PathToCopy)+22)
; Lock the moveable memory, retrieving a pointer to it.
pPath := DllCall("GlobalLock","uint",hPath)
NumPut(20, pPath+0) ; DROPFILES.pFiles = offset of file list
pPath += 20
; Copy the list of files into moveable memory.
Loop, Parse, PathToCopy, `n, `r
{
DllCall("lstrcpy","uint",pPath+0,"str",A_LoopField)
pPath += StrLen(A_LoopField)+1
}
; Unlock the moveable memory.
DllCall("GlobalUnlock","uint",hPath)
DllCall("OpenClipboard","uint",0)
; Empty the clipboard, otherwise SetClipboardData may fail.
DllCall("EmptyClipboard")
; Place the data on the clipboard. CF_HDROP=0xF
DllCall("SetClipboardData","uint",0xF,"uint",hPath)
DllCall("CloseClipboard")
}
The input should be a new-line (`n or `r`n) delimited list of paths.
Edit: Now expands relative paths for a list of paths (before it would only expand one.)