AutoHotKey script to get the path to the selected file

Discuss and share scripts and script files...
Post Reply
d.romeo
Posts: 37
Joined: 08 Oct 2021 23:22

AutoHotKey script to get the path to the selected file

Post by d.romeo »

How can I get the path to the selected file in Xyplorer in AutoHotKey?
For explorer there is the function:

Code: Select all

Explorer_GetSelection() {
   WinGetClass, winClass, % "ahk_id" . hWnd := WinExist("A")
   if !(winClass ~= "^(Progman|WorkerW|(Cabinet|Explore)WClass)$")
      Return

   shellWindows := ComObjCreate("Shell.Application").Windows
   if (winClass ~= "Progman|WorkerW") ; IShellWindows::Item:    https://goo.gl/ihW9Gm
      ; IShellFolderViewDual:   https://goo.gl/gnntq3
      shellFolderView := shellWindows.Item( ComObject(VT_UI4 := 0x13, SWC_DESKTOP := 0x8) ).Document
   else {
      for window in shellWindows ; ShellFolderView object: https://tinyurl.com/yh92uvpa
         if (hWnd = window.HWND) && (shellFolderView := window.Document)
            break
   }
   for item in shellFolderView.SelectedItems
      result .= (result = "" ? "" : "`n") . item.Path
   ;~ if !result
   ;~ result := shellFolderView.Folder.Self.Path
   Return result
}
Thank you

highend
Posts: 13327
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: AutoHotKey script to get the path to the selected file

Post by highend »

By sending a script to XY that sends back the current selected file to the script's window. WM_COPYDATA / RECEIVE...
One of my scripts helped you out? Please donate via Paypal

d.romeo
Posts: 37
Joined: 08 Oct 2021 23:22

Re: AutoHotKey script to get the path to the selected file

Post by d.romeo »

I found a script in this thread viewtopic.php?t=15121, but it doesn't seem to work, i just get empty msgboxe

highend
Posts: 13327
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: AutoHotKey script to get the path to the selected file

Post by highend »

And now you want us to guess which of those scripts you've used?
One of my scripts helped you out? Please donate via Paypal

d.romeo
Posts: 37
Joined: 08 Oct 2021 23:22

Re: AutoHotKey script to get the path to the selected file

Post by d.romeo »

Sorry, I forgot to specify which one:

Code: Select all

/*
    XYGetPath()     - paths of target window's selected items
    XYGetAll()      - paths of all items in the target window's folder
    XYGetSelected() - path of target window's folder

    example:
        F1::
            path := XYGetPath()
            all := XYGetAll()
            sel := XYGetSelected()
            MsgBox % path
            MsgBox % all
            MsgBox % sel
        return

*/

; Get our own HWND (we have no visible window)
DetectHiddenWindows, On
G_OwnHWND := WinExist("Ahk_PID " DllCall("GetCurrentProcessId"))
G_OwnHWND += 0

; Get messages back from XYplorer
OnMessage(0x4a, "Receive_WM_COPYDATA")

F1::
    path := XYGetPath()
    all  := XYGetAll()
    sel  := XYGetSelected()
    MsgBox % path
    MsgBox % all
    MsgBox % sel
return


XYGetPath()
{
    return XY_Get()
}


XYGetAll()
{
   return XY_Get(true)
}


XYGetSelected()
{
   return XY_Get(, true)
}


XY_Get(bAll:=false, bSelection:=false)
{
    global dataReceived, G_OwnHWND

    xyQueryScript =
    ( LTrim Join
        ::
        if (!%bAll% && !%bSelection%) {
            $return = "<curpath>";
        } elseif (%bAll%) {
            $return = listpane(, , , "<crlf>");
        } elseif (%bSelection%) {
            $return = get("SelectedItemsPathNames", "<crlf>");
        }
        copydata %G_OwnHWND%, "$return", 2;
    )

    Send_WM_COPYDATA(xyQueryScript)

    return dataReceived
}


GetXYHWND() {
    IfWinActive, ahk_class ThunderRT6FormDC
    {
        WinGet, xyHwnd, ID, ahk_class ThunderRT6FormDC
    } else {
        WinGet, xyHwnd, List, ahk_class ThunderRT6FormDC
        if (xyHwnd)
            xyHwnd := xyHwnd1
    }

    return xyHwnd
}


Send_WM_COPYDATA(message) {
   xyHwnd := GetXYHWND()

   if !(xyHwnd)
       return

   size := StrLen(message)
   if !(A_IsUnicode) {
      VarSetCapacity(data, size * 2, 0)
      StrPut(message, &data, size, "UTF-16")
   } else {
      data := message
   }
   VarSetCapacity(COPYDATA, A_PtrSize * 3, 0)
   NumPut(4194305, COPYDATA, 0, "Ptr")
   NumPut(size * 2, COPYDATA, A_PtrSize, "UInt")
   NumPut(&data, COPYDATA, A_PtrSize * 2, "Ptr")
   result := DllCall("User32.dll\SendMessageW", "Ptr", xyHWND, "UInt", 74, "Ptr", 0, "Ptr", &COPYDATA, "Ptr")
   return
}


Receive_WM_COPYDATA(wParam, lParam) {
   global dataReceived

   stringAddress := NumGet(lParam + 2 * A_PtrSize)
   copyOfData := StrGet(stringAddress)
   cbData := NumGet(lParam + A_PtrSize) / 2
   StringLeft, dataReceived, copyOfData, cbData

   return
}

highend
Posts: 13327
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: AutoHotKey script to get the path to the selected file

Post by highend »

That one works 100% fine here...

Reduce it, send a simple text "hello" to XY with it?
One of my scripts helped you out? Please donate via Paypal

d.romeo
Posts: 37
Joined: 08 Oct 2021 23:22

Re: AutoHotKey script to get the path to the selected file

Post by d.romeo »

I put the code in an empty script and it works, it's probably a compatibility issue with my other scripts

Norn
Posts: 417
Joined: 24 Oct 2021 16:10

Re: AutoHotKey script to get the path to the selected file

Post by Norn »

I'm trying to convert to AHK V2. . .

Code: Select all

#Requires AutoHotkey v2.0.2

; Get our own HWND (we have no visible window)
DetectHiddenWindows 1
G_OwnHWND := WinExist("Ahk_PID " DllCall("GetCurrentProcessId"))
G_OwnHWND += 0

; Get messages back from XYplorer
OnMessage(0x4a, "Receive_WM_COPYDATA")

F1::
{
    path := XYGetPath()
    all  := XYGetAll()
    sel  := XYGetSelected()
    MsgBox path
    MsgBox all
    MsgBox sel
return
}


XYGetPath()
{
    return XY_Get()
}


XYGetAll()
{
   return XY_Get(true)
}


XYGetSelected()
{
   return XY_Get(, true)
}


XY_Get(bAll:=false, bSelection:=false)
{
    global dataReceived, G_OwnHWND

    xyQueryScript :=
    ( LTrim Join
        ::
        if (!%bAll% && !%bSelection%) {
            $return = "<curpath>";
        } elseif (%bAll%) {
            $return = listpane(, , , "<crlf>");
        } elseif (%bSelection%) {
            $return = get("SelectedItemsPathNames", "<crlf>");
        }
        copydata %G_OwnHWND%, "$return", 2;
    )

    Send_WM_COPYDATA(xyQueryScript)

    return dataReceived
}


GetXYHWND() {
    If WinActive("ahk_class ThunderRT6FormDC")
    {
        xyHwnd := WinGetID("ahk_class ThunderRT6FormDC")
    } else {
        xyHwnd := WinGetList("ahk_class ThunderRT6FormDC")
        if (xyHwnd)
            xyHwnd := "xyHwnd1"
    }

    return xyHwnd
}


Send_WM_COPYDATA(message) {
   xyHwnd := GetXYHWND()

   if !(xyHwnd)
       return

   size := StrLen(message)
   if !(StrLen(Chr(0xFFFF))) {
      VarSetStrCapacity(&data, size * 2, 0)
      StrPut(message, &data, size, "UTF-16")
   } else {
      data := message
   }
   VarSetStrCapacity(&COPYDATA, A_PtrSize * 3, 0)
   NumPut(4194305, COPYDATA, 0, "Ptr")
   NumPut(size * 2, COPYDATA, A_PtrSize, "UInt")
   NumPut(&data, COPYDATA, A_PtrSize * 2, "Ptr")
   result := DllCall("User32.dll\SendMessageW", "Ptr", xyHWND, "UInt", 74, "Ptr", 0, "Ptr", &COPYDATA, "Ptr")
   return
}


Receive_WM_COPYDATA(wParam, lParam) {
   global dataReceived

   stringAddress := NumGet(lParam + 2 * A_PtrSize)
   copyOfData := StrGet(stringAddress)
   cbData := NumGet(lParam + A_PtrSize) / 2
   dataReceived := StringLeft(copyOfData, cbData)

   return
}
Win10, Win11 @100% 2560x1440 22H2

highend
Posts: 13327
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: AutoHotKey script to get the path to the selected file

Post by highend »

and?
One of my scripts helped you out? Please donate via Paypal

Horst
Posts: 1091
Joined: 24 Jan 2021 12:27
Location: Germany

Re: AutoHotKey script to get the path to the selected file

Post by Horst »

And what will be the benefit using AHK v2.
Its almost incompatible with existing scripts
and you will not found many users of it which can help you.
Windows 11 Home x64 Version 23H2 (OS Build 22631.3447)
Portable XYplorer (actual version, including betas)
Everything 1.5.0.1372a (x64), Everything Toolbar 1.3.3, Listary Pro 6.3.0.73

GreetingsFromPoland
Posts: 224
Joined: 29 Sep 2022 14:20
Location: Win10 @125%

Re: AutoHotKey script to get the path to the selected file

Post by GreetingsFromPoland »

Norn wrote: 25 Feb 2023 19:20 I'm trying to convert to AHK V2. . .
hi! i have a few AHK scripts that i wrote and use with XY. i upgraded to AHKv2, but continue to compile into EXE for v1 (set the Base as v1). i did find this converter on their forums - https://github.com/mmikeww/AHK-v2-script-converter/ and used QuickConvertorV2.ahk to create v2-versions of my scripts and it worked really well for mine (not super complicated scripts).

it may help you out as well !

Norn
Posts: 417
Joined: 24 Oct 2021 16:10

Re: AutoHotKey script to get the path to the selected file

Post by Norn »

I knew nothing about programming, scripting before using XYplorer, I'm trying to learn more about scripting, AHK v2 looks easier to remember than v1.
i upgraded to AHKv2, but continue to compile into EXE for v1 (set the Base as v1). i did find this converter on their forums - [url wrote:https://github.com/mmikeww/AHK-v2-script-converter/[/url] and used QuickConvertorV2.ahk to create v2-versions of my scripts and it worked really well for mine (not super complicated scripts).
Yep, this helps convert the little bit I learned in v1, thanks. For this complex script it fails to convert, a lot of errors:

Code: Select all

#Requires AutoHotkey v2.0.2

; Get our own HWND (we have no visible window)
DetectHiddenWindows(true)
G_OwnHWND := WinExist("Ahk_PID " DllCall("GetCurrentProcessId"))
G_OwnHWND += 0

; Get messages back from XYplorer
OnMessage(0x4a, Receive_WM_COPYDATA)

F1::
{ ; V1toV2: Added bracket
    path := XYGetPath()
    all  := XYGetAll()
    sel  := XYGetSelected()
    MsgBox(path)
    MsgBox(all)
    MsgBox(sel)
return
} ; Added bracket before function


XYGetPath()
{
    return XY_Get()
}


XYGetAll()
{
   return XY_Get(true)
}


XYGetSelected()
{
   return XY_Get(, true)
}


XY_Get(bAll:=false, bSelection:=false)
{
    global dataReceived, G_OwnHWND

    xyQueryScript := "
    ( LTrim Join
        ::
      {
        if (!bAll && !bSelection) {
            $return = "<curpath>";
        } elseif (bAll) {
            $return = listpane(, , , "<crlf>");
        } elseif (bSelection) {
            $return = get("SelectedItemsPathNames", "<crlf>");
        }
        copydata G_OwnHWND, "$return", 2;
	  }
    )"

    Send_WM_COPYDATA(xyQueryScript)

    return dataReceived
}


GetXYHWND() {
    if WinActive("ahk_class ThunderRT6FormDC")
    {
        xyHwnd := WinGetID("ahk_class ThunderRT6FormDC")
    } else {
        oxyHwnd := WinGetList("ahk_class ThunderRT6FormDC")
        axyHwnd := Array()
        xyHwnd := oxyHwnd.Length
        For v in oxyHwnd
        {
		    axyHwnd.Push(v)
        }
        if (axyHwnd.Length)
            xyHwnd := axyHwnd[1]
    }

    return xyHwnd
}


Send_WM_COPYDATA(message) {
   xyHwnd := GetXYHWND()

   if !(xyHwnd)
       return

   size := StrLen(message)
   if !(StrLen(Chr(0xFFFF))) {
      data := Buffer(size * 2, 0) ; V1toV2: if 'data' is a UTF-16 string, use 'VarSetStrCapacity(&data, size * 2)'
      StrPut(message, &data, size, "UTF-16")
   } else {
      data := message
   }
   COPYDATA := Buffer(A_PtrSize * 3, 0) ; V1toV2: if 'COPYDATA' is a UTF-16 string, use 'VarSetStrCapacity(&COPYDATA, A_PtrSize * 3)'
   NumPut("Ptr", 4194305, COPYDATA, 0)
   NumPut("UInt", size * 2, COPYDATA, A_PtrSize)
   NumPut("Ptr", &data, COPYDATA, A_PtrSize * 2)
   result := DllCall("User32.dll\SendMessageW", "Ptr", xyHwnd, "UInt", 74, "Ptr", 0, "Ptr", COPYDATA, "Ptr")
   return
}


Receive_WM_COPYDATA(wParam, lParam) {
   global dataReceived

   stringAddress := NumGet(lParam + 2 * A_PtrSize, "UPtr")
   copyOfData := StrGet(stringAddress)
   cbData := NumGet(lParam + A_PtrSize, "UPtr") / 2
   dataReceived := SubStr(copyOfData, 1, cbData)

   return
}
I install two versions and can run two versions of the script, but for beginners like me, it seems that there is no need to continue learning the syntax of v1.

For AHK v2:

Code: Select all

#Requires AutoHotkey v2.0.2

; Get our own HWND (we have no visible window)
DetectHiddenWindows(true)
G_OwnHWND := WinExist("Ahk_PID " DllCall("GetCurrentProcessId"))
G_OwnHWND += 0


; Get messages back from XYplorer
OnMessage(0x4a, Receive_WM_COPYDATA)

global dataReceived := ""

F1::
{
    path := XYGetPath()
    all  := XYGetAll()
    sel  := XYGetSelected()
    MsgBox path
    MsgBox all
    MsgBox sel
return
}


XYGetPath()
{
    return XY_Get()
}


XYGetAll()
{
   return XY_Get(true)
}


XYGetSelected()
{
   return XY_Get(, true)
}


XY_Get(bAll:=false, bSelection:=false)
{
    xyQueryScript := '::if (!' bAll ' && !' bSelection ') {$return = "<curpath>"`;} elseif (' bAll ') {$return = listpane(, , , "<crlf>")`;} elseif (' bSelection ') {$return = get("SelectedItemsPathNames", "<crlf>")`;} copydata ' G_OwnHWND ', "$return", 2`;'

    Send_WM_COPYDATA(xyQueryScript)

    return dataReceived
}


GetXYHWND() {
	static xyClass := 'ahk_class ThunderRT6FormDC'

	if hwnd := WinActive(xyClass)
		return hwnd
	else if WinExist(xyClass)
		return WinGetList(xyClass)[1]
}


Send_WM_COPYDATA(message) {
   xyHwnd := GetXYHWND()

   if !(xyHwnd)
       return

   size := StrLen(message)
   if !(StrLen(Chr(0xFFFF))) {
      data := Buffer(size * 2, 0)
      StrPut(message, &data, size, "UTF-16")
   } else {
      data := message
   }

   COPYDATA := Buffer(A_PtrSize * 3)
   NumPut("Ptr", 4194305, COPYDATA, 0)
   NumPut("UInt", size * 2, COPYDATA, A_PtrSize)
   NumPut("Ptr", StrPtr(data), COPYDATA, A_PtrSize * 2)

   return DllCall("User32.dll\SendMessageW", "Ptr", xyHwnd, "UInt", 74, "Ptr", 0, "Ptr", COPYDATA, "Ptr")
}


Receive_WM_COPYDATA(wParam, lParam, *) {
	global dataReceived := StrGet(
		NumGet(lParam + 2 * A_PtrSize, 'Ptr'), ; COPYDATASTRUCT.lpData, ptr to a str presumably
		NumGet(lParam + A_PtrSize, 'UInt') / 2 ; COPYDATASTRUCT.cbData, count bytes of lpData, /2 to get count chars in unicode str
	)
}
Win10, Win11 @100% 2560x1440 22H2

elbitjusticiero
Posts: 32
Joined: 11 Mar 2018 20:57

Re: AutoHotKey script to get the path to the selected file

Post by elbitjusticiero »

If you want to do this while the XYplorer window is active, you can just save the clipboard, send Ctrl+P, read the clipboard (it will contain the full path and filename) and restore the clipboard.

If you want to do this while the XYplorer window is not active, you can try using CtrlSend to send the Ctrl+P combo to XYplorer.

Norn
Posts: 417
Joined: 24 Oct 2021 16:10

Re: AutoHotKey script to get the path to the selected file

Post by Norn »

Make it work on Floating Preview.

Code: Select all

; Function : XYplorer Get Selection (AHK v2)

#Requires AutoHotkey v2.0.2

; Get our own HWND (we have no visible window)
G_OwnHWND := A_ScriptHwnd + 0


; Get messages back from XYplorer
OnMessage(0x4a, Receive_WM_COPYDATA)

global dataReceived := ""

F1::
{
    path := XYGetPath()
    all  := XYGetAll()
    sel  := XYGetSelected()
    MsgBox path
    MsgBox all
    MsgBox sel
return
}


XYGetPath()
{
    return XY_Get()
}


XYGetAll()
{
   return XY_Get(true)
}


XYGetSelected()
{
   return XY_Get(, true)
}


XY_Get(bAll:=false, bSelection:=false)
{
    xyQueryScript := '::if (!' bAll ' && !' bSelection ') {$return = "<curpath>"`;} elseif (' bAll ') {$return = listpane(, , , "<crlf>")`;} elseif (' bSelection ') {$return = get("SelectedItemsPathNames", "<crlf>")`;} copydata ' G_OwnHWND ', "$return", 2`;'

    Send_WM_COPYDATA(xyQueryScript)

    return dataReceived
}


GetXYHWND() {
    static xyClass := 'ahk_class ThunderRT6FormDC'

    if WinExist(xyClass) {
        for xyid in WinGetList(xyClass)
            for ctrl in WinGetControls(xyid)
                if A_Index = 10                ; The Floating Preview has only a few controls
                   return xyid
    }
}


Send_WM_COPYDATA(message) {
   xyHwnd := GetXYHWND()

   if !(xyHwnd)
       return

   size := StrLen(message)

   COPYDATA := Buffer(A_PtrSize * 3)
   NumPut("Ptr", 4194305, COPYDATA, 0)
   NumPut("UInt", size * 2, COPYDATA, A_PtrSize)
   NumPut("Ptr", StrPtr(message), COPYDATA, A_PtrSize * 2)

   return DllCall("User32.dll\SendMessageW", "Ptr", xyHwnd, "UInt", 74, "Ptr", 0, "Ptr", COPYDATA, "Ptr")
}


Receive_WM_COPYDATA(wParam, lParam, *) {
	global dataReceived := StrGet(
		NumGet(lParam + 2 * A_PtrSize, 'Ptr'),   ; COPYDATASTRUCT.lpData, ptr to a str presumably
		NumGet(lParam + A_PtrSize, 'UInt') / 2   ; COPYDATASTRUCT.cbData, count bytes of lpData, /2 to get count chars in unicode str
	)
}
Win10, Win11 @100% 2560x1440 22H2

Post Reply