1

Тема: AHK: Передача файла в приложение методом Drag&Drop

На рабочем столе лежит файл 1.txt. Открыт блокнот.
При запуске кода пишет "не удается найти указанный файл"
После строки

VarSetCapacity( DROPFILES,20,32)

В переменной DROPFILES появляются лишние символы. Так и должно быть?

SetTitleMatchMode, 2

DropFilesA(A_Desktop "\1.txt", "ahk_class Notepad")

DropFilesA( FileList, wTitle="", Ctrl="", X=0, Y=0, NCA=0 ) {
 StringReplace, FileList, FileList, `r`n, `n , All
 VarSetCapacity( DROPFILES,20,32)
 DROPFILES.=FileList "`n`n"
 nSize:=StrLen(DROPFILES)
 StringReplace, DROPFILES,DROPFILES, `n,`n, UseErrorLevel
 Loop %ErrorLevel%
   NumPut( 0, DROPFILES, InStr(DROPFILES,"`n",0,0)-1, "Char" )
 pDP:=&DROPFILES
 NumPut(20,pDP+0)
 NumPut(X,pDP+4)
 NumPut(Y,pDP+8)
 NumPut(NCA,pDP+12)
 NumPut(0,pDP+16)
 hDrop := DllCall( "GlobalAlloc", UInt,0x42, UInt,nSize )
 pData := DllCall( "GlobalLock", UInt,hDrop )
 DllCall( "RtlMoveMemory", UInt,pData, UInt,pDP, UInt,nSize )
 DllCall( "GlobalUnlock", UInt,hDrop )
 PostMessage, 0x233, hDrop, 0, %Ctrl%, %wTitle% ; WM_DROPFILES := 0x233
}

2

Re: AHK: Передача файла в приложение методом Drag&Drop

С кодом подробно не разбирался, но после строки

VarSetCapacity( DROPFILES,20,32)

в каждый байт переменной DROPFILES помещается число 32 (0x20), которое соответствует пробелу в ANSI либо знаку "†" в юникоде (0x2020). Отсюда "лишние" симолы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3 (изменено: InFlames, 2012-05-13 21:41:00)

Re: AHK: Передача файла в приложение методом Drag&Drop

Всё верно. Несколько символов † появляется. На офф. форуме, где я брал скрипт, писали, что он работает. Но у меня не получается получить результат.
Видимо этот код писался для AHK Basic и в переменной должны быть пробелы. Попробовал запустить на AHK Basic, скрипт заработал.
К сожалению знаний не хватает, что бы понять, как поправить для AHK_L.
Видимо дело в вызываемых функциях.
И как записать пробелы в переменную Dropfiles вместо крестов?

4

Re: AHK: Передача файла в приложение методом Drag&Drop

Для начала, как конкретно он должен работать?
...
А, уже понял, посмотрю.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: Передача файла в приложение методом Drag&Drop

Примерно так:

DropFilesA(A_Desktop "\1.txt", "ahk_class Notepad")

DropFilesA( FileList, wTitle="", Ctrl="", X=0, Y=0, NCA=0 )
{
   offset := 20
   VarSetCapacity( DROPFILES, StrLen(FileList) + offset + 2)
   Loop, parse, FileList, `n, `r
   {
      StrPut(A_LoopField, &DROPFILES + offset, StrLen(A_LoopField), "CP0")
      offset += StrLen(A_LoopField) + 4
      NumPut(0, &DROPFILES + offset - 4, "UInt")   ; разделяем нулями пути
   }
   NumPut(0, &DROPFILES + offset, "UInt")   ; завершиться должно 2-мя нулями подряд
   nSize := offset + 4
   pDP:=&DROPFILES
   NumPut(20, pDP+0, "UInt")
   NumPut(X, pDP+4, "UInt")
   NumPut(Y, pDP+8, "UInt")
   NumPut(NCA, pDP+12, "UInt")
   NumPut(0, pDP+16, "UInt")
   hDrop := DllCall( "GlobalAlloc", UInt, 0x42, UInt, nSize, Ptr )
   pData := DllCall( "GlobalLock", Ptr, hDrop, Ptr )
   DllCall( "RtlMoveMemory", Ptr, pData, Ptr, pDP, UInt, nSize )
   DllCall( "GlobalUnlock", Ptr, hDrop )
   PostMessage, 0x233, hDrop, 0, %Ctrl%, %wTitle% ; WM_DROPFILES := 0x233
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

6 (изменено: Irbis, 2012-05-14 00:50:22)

Re: AHK: Передача файла в приложение методом Drag&Drop

AHK_L работает нормально, если не запускать скрипт, а скомпилировать через AHK2EXE  как ANSI версию. (Это про скрипт из поста #1)
Хотя это, наверное, и так понятно, что проблема в Unicode.

Upd: teadrinker как всегда на высоте http://resources.pokerstrategy.com/2011/10/16/applo.gif

7

Re: AHK: Передача файла в приложение методом Drag&Drop

Спасибо. Работает отлично.
Не совсем понял, почему 32 в юникоде это †? Номер 32 с 0x2020 никак не соотносится.

8

Re: AHK: Передача файла в приложение методом Drag&Drop

32 это 0x20, в unicode-версии AHK строки записываются в память в кодировке UTF-16, в которой на каждый символ приходится 2 байта, соответственно считывается 0x2020.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

9

Re: AHK: Передача файла в приложение методом Drag&Drop

Не могу понять в чём причина —

Gui +LastFound
DropFilesA("123`n234")
return

GuiDropFiles:
    MsgBox % A_GuiEvent
    ExitApp

более одного «файла» не удаётся передать.

10 (изменено: serzh82saratov, 2013-05-11 02:15:36)

Re: AHK: Передача файла в приложение методом Drag&Drop

creature.ws

DropFilesA("123``n234")

Upd:
Сорри, поспешил

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

11 (изменено: creature.ws, 2013-05-11 14:49:31)

Re: AHK: Передача файла в приложение методом Drag&Drop

Вопрос снят
Нужно было использовать один \0 в качестве разделителя в списке файлов.

12

Re: AHK: Передача файла в приложение методом Drag&Drop

creature.ws пишет:

Вопрос снят
Нужно было использовать один \0 в качестве разделителя в списке файлов.

А это как?

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

13

Re: AHK: Передача файла в приложение методом Drag&Drop

   VarSetCapacity( DROPFILES, StrLen(FileList) + offset + 2)
   Loop, parse, FileList, `n, `r
   {
      StrPut(A_LoopField, &DROPFILES + offset, StrLen(A_LoopField), "CP0")
      offset += StrLen(A_LoopField) + 4
      NumPut(0, &DROPFILES + offset - 4, "UInt")   ; разделяем нулями пути
   }

Так:

    VarSetCapacity(dropFiles, StrPut(fileList) + offset + 2, 0)

    loop parse, fileList, `n, `r
        StrPut(A_LoopField, &dropFiles + offset, StrLen(A_LoopField), "CP0")
        , offset += StrLen(A_LoopField) + 1

14

Re: AHK: Передача файла в приложение методом Drag&Drop

Работает. Раньше приходилось передавать по одному.
То есть функция в исправленном виде выглядит:


DropFilesA( FileList, wTitle="", Ctrl="", X=0, Y=0, NCA=0 )
{
    offset := 20
    VarSetCapacity(dropFiles, StrPut(fileList) + offset + 2, 0)
    loop parse, fileList, `n, `r
        StrPut(A_LoopField, &dropFiles + offset, StrLen(A_LoopField), "CP0")
        , offset += StrLen(A_LoopField) + 1
    NumPut(0, &DROPFILES + offset, "UInt")   ; завершиться должно 2-мя нулями подряд
    nSize := offset + 4
    pDP:=&DROPFILES
    NumPut(20, pDP+0, "UInt")
    NumPut(X, pDP+4, "UInt")
    NumPut(Y, pDP+8, "UInt")
    NumPut(NCA, pDP+12, "UInt")
    NumPut(0, pDP+16, "UInt")
    hDrop := DllCall( "GlobalAlloc", UInt, 0x42, UInt, nSize, Ptr )
    pData := DllCall( "GlobalLock", Ptr, hDrop, Ptr )
    DllCall( "RtlMoveMemory", Ptr, pData, Ptr, pDP, UInt, nSize )
    DllCall( "GlobalUnlock", Ptr, hDrop )
    PostMessage, 0x233, hDrop, 0, %Ctrl%, %wTitle% ; WM_DROPFILES := 0x233
}
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

15 (изменено: creature.ws, 2013-05-11 15:40:02)

Re: AHK: Передача файла в приложение методом Drag&Drop

DropFiles(ByRef fileList, windowTitle := "", ctrl := "", x := 0, y := 0, NC := 0) {
    offset := 20
    VarSetCapacity(dropFiles, StrLen(fileList) + offset + 2, 0)
    pDropFiles := &dropFiles

    loop parse, fileList, `n, `r
        StrPut(A_LoopField, pDropFiles + offset, StrLen(A_LoopField), "CP0")
        , offset += StrLen(A_LoopField) + 1

    NumPut(20, pDropFiles + 0, "UInt")
    NumPut(x,  pDropFiles + 4, "UInt")
    NumPut(y,  pDropFiles + 8, "UInt")
    NumPut(NC, pDropFiles + 12, "UInt")
    NumPut(0,  pDropFiles + 16, "UInt")

    size := offset + 1
    hDrop := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", size, "Ptr")
    pData := DllCall("GlobalLock", "Ptr", hDrop, "Ptr")
    DllCall("RtlMoveMemory", "Ptr", pData, "Ptr", pDropFiles, "UInt", size)
    DllCall("GlobalUnlock", "Ptr", hDrop)

    PostMessage 0x233, hDrop, 0, %ctrl%, %windowTitle%
}

Или так, но 3 байта, кажется, не значат много

16

Re: AHK: Передача файла в приложение методом Drag&Drop

Обновлённая версия с поддержкой юникода.

На окно - замечательно работает. А как перетянуть файлы не на окно, а на определённый контрол окна?
Есть утилитка EncryptCare, она принимает файлы только при перетаскивании на TListView1. Пытаюсь сделать так:
DropFiles( FileList, "ahk_exe EncryptCare.exe", "TListView1" )
Не работает.

17

Re: AHK: Передача файла в приложение методом Drag&Drop

Там же координаты есть. Попробуйте указать координаты внутри контрола, отличные от 0.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

18 (изменено: Aslan, 2018-09-15 20:14:22)

Re: AHK: Передача файла в приложение методом Drag&Drop

teadrinker пишет:

Там же координаты есть. Попробуйте указать координаты внутри контрола, отличные от 0.

Пробовал так:
DropFiles( FileList, "ahk_exe EncryptCare.exe", "TListView1", 100, 100 )
Пробовал указать координаты внутри всего окна:
DropFiles( FileList, "ahk_exe EncryptCare.exe",, 300, 300 )
Не срабатывает.

Пробовал предварительно ControlFocus, ControlClick делать, определять Hwnd контрола и передавать его... безрезультатно.

Многие программы умеют принимать файлы при перетаскивании на любое место окна. Но если для них указываю определённый контрол, то файлы тоже не принимаются.
Или эта возможность в функции вообще недоделана и не работает (или и не должна работать) или я что-то неправильно записываю?

19

Re: AHK: Передача файла в приложение методом Drag&Drop

Трудно сказать, не имея вашей программы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20

Re: AHK: Передача файла в приложение методом Drag&Drop

Aslan, посмотрите через spy++, что отправляется окну при перетаскивани.
Раз это ListView, то возможно отправляется LVM_INSERTITEM.

21 (изменено: Aslan, 2018-09-16 02:23:39)

Re: AHK: Передача файла в приложение методом Drag&Drop

teadrinker пишет:

Трудно сказать, не имея вашей программы.

Как я написал выше - безрезультатно пробовал передачу файлов на контролы разных программ (указываю wTitle - всё работает, указываю wTitle и Ctrl - не работает).

Подскажите по тем программам, которые у вас есть.
В какой-нибудь программе (ссылочку на неё или название) работает передача файлов скриптом на определённый контрол этой программы? И как выглядит правильная запись передачи файлов именно на контрол? (примеров с подобным использованием функции не нашёл, свои тщетные попытки записи выложил выше).

Malcev пишет:

Aslan, посмотрите через spy++, что отправляется окну при перетаскивани.
Раз это ListView, то возможно отправляется LVM_INSERTITEM.

Для разных программ генерируются разное во время отпускания перетаскиваемого файла. Именно такой записи в логах не встретил.
На всякий случай попробовал заменять в функции 0x233 на те коды сообщений, которые отправляются во время отпускания файла - не сработало.

22

Re: AHK: Передача файла в приложение методом Drag&Drop

Попробую.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

23 (изменено: teadrinker, 2018-09-16 03:35:35)

Re: AHK: Передача файла в приложение методом Drag&Drop

Функция у меня работает, хоть и составлена не совсем корректно. Мой вариант:

DropFiles(fileList, windowTitle := "", ctrl := "", x := 0, y := 0, NC := 0, isUnicodeFiles := 0)  {
   fileList := Trim( RegExReplace(fileList, "\R", "`n"), " `t`r`n" ), RegExReplace(fileList, "\R", "", count)
   VarSetCapacity(DROPFILES, size := 20 + StrLen(fileList) + count + 2, 0)
   NumPut(20, DROPFILES)
   NumPut(x, DROPFILES, 4)
   NumPut(y, DROPFILES, 8)
   NumPut(NC, DROPFILES, 12)
   NumPut(isUnicodeFiles, DROPFILES, 16)
   
   prevLen := 0
   Loop, parse, fileList, `n
      prevLen += StrPut( A_LoopField, &DROPFILES + 20 + prevLen + A_Index - 1, StrLen(A_LoopField), "CP0" )
   
   hDrop := DllCall("GlobalAlloc", UInt, 0x42, Ptr, size, Ptr)
   pData := DllCall("GlobalLock", Ptr, hDrop, Ptr)
   DllCall("RtlMoveMemory", Ptr, pData, Ptr, &DROPFILES, Ptr, size)
   DllCall("GlobalUnlock", Ptr, hDrop)
   PostMessage, WM_DROPFILES := 0x233, hDrop,, % ctrl, % windowTitle
}

Для проверки запустите сначала такой скрипт:

WM_DROPFILES := 0x233, WS_EX_ACCEPTFILES := 0x10

Gui, +AlwaysOnTop
Gui, Margin, 10, 10
Gui, Font, s12 q5, calibri
Gui, Add, Text, y70 h70 Border +E%WS_EX_ACCEPTFILES%, % "   ↓ Перетащите сюда файлы ↓   "
OnMessage(0x233, "WM_DROPFILES")
Gui, Show, y100, Drop Files Test
Return

GuiClose:
   ExitApp

WM_DROPFILES(hDrop)  {
   countFiles := DllCall("Shell32\DragQueryFile", Ptr, hDrop, UInt, 0xFFFFFFFF, Ptr, 0, UInt, 0)
   Loop % countFiles  {
      size := DllCall("Shell32\DragQueryFile", Ptr, hDrop, UInt, A_Index - 1, Ptr, 0, UInt, 0)
      VarSetCapacity(buff, size + 1, 0)
      DllCall("Shell32\DragQueryFile", Ptr, hDrop, UInt, A_Index - 1, Ptr, &buff, UInt, size + 1)
      fileNames .= (fileNames = "" ? "" : "`r`n") . StrGet(&buff, "CP0")
   }
   DllCall("Shell32\DragFinish", Ptr, hDrop)
   timer := Func("ShowFileNames").Bind(fileNames)
   SetTimer, % timer, -10
}

ShowFileNames(fileNames)  {
   MsgBox, % fileNames
}

В появившееся окно можно перетаскивать файлы вручную, если опускать их в выделенную область, в ответ будет появляться Message Box со списком файлов.
Не завершая первый скрипт, запустите такой:

fileList =
(
%A_WinDir%
%A_ProgramFiles%
%A_Temp%
)

DropFiles(fileList, "Drop Files Test", "Static1")

DropFiles(fileList, windowTitle := "", ctrl := "", x := 0, y := 0, NC := 0, isUnicodeFiles := 0)  {
   fileList := Trim( RegExReplace(fileList, "\R", "`n"), " `t`r`n" ), RegExReplace(fileList, "\R", "", count)
   VarSetCapacity(DROPFILES, size := 20 + StrLen(fileList) + count + 2, 0)
   NumPut(20, DROPFILES)
   NumPut(x, DROPFILES, 4)
   NumPut(y, DROPFILES, 8)
   NumPut(NC, DROPFILES, 12)
   NumPut(isUnicodeFiles, DROPFILES, 16)
   
   prevLen := 0
   Loop, parse, fileList, `n
      prevLen += StrPut( A_LoopField, &DROPFILES + 20 + prevLen + A_Index - 1, StrLen(A_LoopField), "CP0" )
   
   hDrop := DllCall("GlobalAlloc", UInt, 0x42, Ptr, size, Ptr)
   pData := DllCall("GlobalLock", Ptr, hDrop, Ptr)
   DllCall("RtlMoveMemory", Ptr, pData, Ptr, &DROPFILES, Ptr, size)
   DllCall("GlobalUnlock", Ptr, hDrop)
   PostMessage, WM_DROPFILES := 0x233, hDrop,, % ctrl, % windowTitle
}

Первый скрипт должен показать список указанных папок.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

24

Re: AHK: Передача файла в приложение методом Drag&Drop

Aslan пишет:

Именно такой записи в логах не встретил.

А она может быть и не такой.
Смотрите по хексу.
https://www.geoffchappell.com/studies/w … /index.htm

Aslan пишет:

На всякий случай попробовал заменять в функции 0x233 на те коды сообщений

Так не получится, так как передаваемые структуры разные.

25

Re: AHK: Передача файла в приложение методом Drag&Drop

Спасибо за информацию, буду разбираться.
Похоже, всё сложнее, чем казалось, разные программы по разному принимают файлы.