1

Тема: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Задача довольно простая. Нужно выделенный файл или папку поместить в плейлист плеера. Я это сделал с помощью Key Manager v.1.5 (видео https://www.youtube.com/watch?v=AxXKymI … 14ym_lvccp)
Key Manager имитирует нажатие правой кнопки мыши и продвигается по контекстному меню до строчки add to playlist.
Но тут возникает ряд проблем:
1. Программа платная
2. В зависимости от того, что мы хотим добавить - файл или папку, контекстное меню будет выглядеть по-разному.
Вроде бы, в AHK можно как-то привязаться к процессу, вызываемому add to playlist
Какие есть предложения?

2

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Можно выполнить пункт меню файла в папке, используя COM. Пункт меню должен содержать знак & перед буквой с подчёркиванием, если оно имеется.
Активируем окно, выделяем нужный файл, нажимаем F11.

MenuItem := "&Add to Playlist..."  ; нужно указать точное название пункта меню, перед буквой с подчёркиванием знак &
Return

F11::
   WinGet, ID,, A
   WinGetClass, Class, A
   if !(Class ~= "(Cabinet|Explore)WClass")
   {
      MsgBox, Окно не является папкой!
      Return
   }

   oShell := ComObjCreate("Shell.Application")
   Loop % oShell.Windows.Count
   {
      oIE := oShell.Windows.Item(A_Index - 1)
      Sleep, 10
   } Until oIE.HWND = ID

   oFolderItems := oIE.Document.SelectedItems
   if oFolderItems.Count = 0
   {
      MsgBox, Ничего не выделено!
      oShell := oIE := oFolderItems := ""
      Return
   }

   found := ""
   for Item in oFolderItems
      for verb in Item.Verbs
         if (verb.Name = MenuItem)
         {
            Item.InvokeVerb(verb.Name), found := 1
            Break 2
         }
         
   if !found
      MsgBox, Не найден указанный пункт меню!

   oShell := oIE := oFolderItems := ""
   Return

Пункты меню, содержащие вложенные меню, не определяются.

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

3 (изменено: Malcev, 2012-02-14 04:28:37)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Там только вложенное меню.
Тогда так.

f11::
clipboard =
Send, ^{vk43}   ; Ctrl + C
ClipWait, 2
if ErrorLevel
{
   MsgBox, Буфер обмена пуст!
   Return
}
Loop, parse, clipboard, `n, `r
{
   run C:\Program Files\AIMP3\AIMP3.exe /INSERT %A_LoopField%
}

4

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

teadrinker, Malcev мегаспасибо за быстрый ответ. Malcev скрипт прекрасно заработал . Как я понял, происходит копирование файла/папки в буфер обмена, с дальнейшим помещением его в плейлист. Все супер, единственный минус - приходится задействовать буфер обмена.

Можно выполнить пункт меню файла в папке, используя COM. Пункт меню должен содержать знак & перед буквой с подчёркиванием, если оно имеется.
Активируем окно, выделяем нужный файл, нажимаем F11.

У меня не завелся, пишет "Не найден указанный пункт меню!" Возможно, это из-за того, что меню русскоязычное? Я проверял на меню без вложений.

Пункты меню, содержащие вложенные меню, не определяются.

Это можно как-то обойти? А если переместить это подменю в корневую часть? 

PS1: система win7 64 бит.
PS2: Что такое COM (встречалось на англояз. форуме)?

5

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu
Копируются не файл и папка, а пути к ним. COM

6 (изменено: Malcev, 2012-02-14 10:47:22)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Если не хочешь забивать буфер обмена, то соедини мой скрипт вот с этим
http://www.autohotkey.com/forum/viewtopic.php?t=65707

Пункты меню, содержащие вложенные меню, не определяются.

Кстати, а почему?

7

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

У меня не завелся, пишет "Не найден указанный пункт меню!"

Значит, неправильно указан пункт меню. Возможно, амперсанд пропустил. Приведи свой вариант кода, в каком виде ты его запускал.

Malcev пишет:

Кстати, а почему?

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

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

8

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Malcev пишет:

Если не хочешь забивать буфер обмена, то соедини мой скрипт вот с этим
http://www.autohotkey.com/forum/viewtopic.php?t=65707

Спасибо за ссылку. Там представлены 2 библиотеки:первая от Rapte_Of_Suzaku (требуется AHK_L), вторая версия от a4u  для основной AHK. Только я не понял, как это совместить с твоим скриптом, и как в итоге будет работать алгоритм в обход буфера обмена.

teadrinker пишет:

Значит, неправильно указан пункт меню. Возможно, амперсанд пропустил.

Я пробывал прописывать следующее: воспроизвести в Winamp, MediaInfo, с амперсандом и без него. 

teadrinker пишет:

Приведи свой вариант кода, в каком виде ты его запускал.

Запускал с помощью контекстного меню -> Run Script
Буду пробывать еще...

9

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Пока не работает. (сообщения заменил на англ., т.к. по-русски выводит символами @$#)

MenuItem := "&Добавить в список Winamp"  ; нужно указать точное название пункта меню, перед буквой с подчёркиванием знак &
Return
 
F11::
   WinGet, ID,, A
   WinGetClass, Class, A
   if !(Class ~= "(Cabinet|Explore)WClass")
   {
      MsgBox, the window is not a folder!
      Return
   }
 
   oShell := ComObjCreate("Shell.Application")
   Loop % oShell.Windows.Count
   {
      oIE := oShell.Windows.Item(A_Index - 1)
      Sleep, 10
   } Until oIE.HWND = ID
 
   oFolderItems := oIE.Document.SelectedItems
   if oFolderItems.Count = 0
   {
      MsgBox, nothing is selected!
      oShell := oIE := oFolderItems := ""
      Return
   }
 
   found := ""
   for Item in oFolderItems
      for verb in Item.Verbs
         if (verb.Name = MenuItem)
         {
            Item.InvokeVerb(verb.Name), found := 1
            Break 2
         }
 
   if !found
      MsgBox, menu item not found!
 
   oShell := oIE := oFolderItems := ""
   Return

10

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Если у вас AHK_L Unicode, то сохраняйте скрипт в UTF-8. Иначе русский текст, даже в комментариях, будет рождать баги.

11

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Советую пользоваться AHK_L Unicode

f11::
         path := Explorer_GetPath()
         all := Explorer_GetAll()
         sel := Explorer_GetSelected()
Loop, parse, sel, `n, `r
{
   run C:\Program Files\AIMP3\AIMP3.exe /INSERT %A_LoopField%
}
return



Explorer_GetPath(hwnd="")
{
   if !(window := Explorer_GetWindow(hwnd))
      return ErrorLevel := "ERROR"
   if (window="desktop")
      return A_Desktop
   path := window.LocationURL
   path := RegExReplace(path, "ftp://.*@","ftp://")
   StringReplace, path, path, file:///
   StringReplace, path, path, /, \, All
   
   ; thanks to polyethene
   Loop
      If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex)
         StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
      Else Break
   return path
}
Explorer_GetAll(hwnd="")
{
   return Explorer_Get(hwnd)
}
Explorer_GetSelected(hwnd="")
{
   return Explorer_Get(hwnd,true)
}

Explorer_GetWindow(hwnd="")
{
   ; thanks to jethrow for some pointers here
    WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
    WinGetClass class, ahk_id %hwnd%
   
   if (process!="explorer.exe")
      return
   if (class ~= "(Cabinet|Explore)WClass")
   {
      for window in ComObjCreate("Shell.Application").Windows
         if (window.hwnd==hwnd)
            return window
   }
   else if (class ~= "Progman|WorkerW")
      return "desktop" ; desktop found
}
Explorer_Get(hwnd="",selection=false)
{
   if !(window := Explorer_GetWindow(hwnd))
      return ErrorLevel := "ERROR"
   if (window="desktop")
   {
      ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
      if !hwWindow ; #D mode
         ControlGet, hwWindow, HWND,, SysListView321, A
      ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
      base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop
      Loop, Parse, files, `n, `r
      {
         path := base "\" A_LoopField
         IfExist %path% ; ignore special icons like Computer (at least for now)
            ret .= path "`n"
      }
   }
   else
   {
      if selection
         collection := window.document.SelectedItems
      else
         collection := window.document.Folder.Items
      for item in collection
         ret .= item.path "`n"
   }
   return Trim(ret,"`n")
}

12

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

YMP пишет:

Если у вас AHK_L Unicode, то сохраняйте скрипт в UTF-8. Иначе русский текст, даже в комментариях, будет рождать баги.

Извиняюсь за ламерский вопрос, как мне сохранить скрипт из блокнота в формате UTF-8, или это проделывается через дугую прогу?

Malcev пишет:

Советую пользоваться AHK_L Unicode

Поставил AHK_L.
Malcev, твой скрипт работает просто Шикарно. Many thanks!

13

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Там в диалоге сохранения файла можно выбрать UTF-8.

14

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

YMP пишет:

Там в диалоге сохранения файла можно выбрать UTF-8.

Да, я уже догнал, просто потом меняем расширение на .ahk

15

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

Malcev, твой скрипт работает просто Шикарно. Many thanks!

На самом деле это не так, при выборе нескольких папок и файлов приложение AIMP3.exe будет запущено несколько раз, командой Run не предусмотрено ожидание завершения первой запущенной копии, что приводит к зависанию плеера (проверял на старенькой версии AIMP v2.60).Я это немного исправил посредством команды RunWait.


/*
AHK: Размещение выделенных файлов и папок
http://forum.script-coding.com/viewtopic.php?id=6024

Get paths of selected items in an explorer window
http://www.autohotkey.com/forum/topic65707.html

Список поддерживаемых команд в AIMP3
http://www.aimp.ru/forum/index.php?topic=19232.msg179881#msg179881

AIMP3 Plugins API
http://www.aimp.ru/forum/index.php?topic=30328.0
*/

global AIMP_Path:="C:\Program Files\AIMP3"

; Alt + A ; добавляем только выделенные файлы и папки
!vk41::
AIMP_AddPlaylist(Explorer_Get("",true))
return

; Win + A ; добавляем все файлы и папки на рабочем столе или в текущей папке проводника
#vk41::
AIMP_AddPlaylist(Explorer_Get())
return

AIMP_AddPlaylist(Items)
{
	Loop, Parse,Items,`n
	;if (SubStr(A_LoopField,-3,4)=".mp3") - только mp3 файлы без папок
	RunWait AIMP3.exe /INSERT %A_LoopField%,% AIMP_Path
}

Explorer_GetWindow(hwnd="") 
{ 
   ; thanks to jethrow for some pointers here 
    WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A") 
    WinGetClass class, ahk_id %hwnd% 
    
   if (process!="explorer.exe") 
      return 
   if (class ~= "(Cabinet|Explore)WClass") 
   { 
      for window in ComObjCreate("Shell.Application").Windows 
         if (window.hwnd==hwnd) 
            return window 
   } 
   else if (class ~= "Progman|WorkerW") 
      return "desktop" ; desktop found 
} 

Explorer_Get(hwnd="",selection=false) 
{ 
   if !(window := Explorer_GetWindow(hwnd)) 
      return ErrorLevel := "ERROR" 
   if (window="desktop") 
   { 
      ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman 
      if !hwWindow ; #D mode 
         ControlGet, hwWindow, HWND,, SysListView321, A 
      ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow% 
      base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop 
      Loop, Parse, files, `n, `r 
      { 
         path := base "\" A_LoopField 
         IfExist %path% ; ignore special icons like Computer (at least for now) 
            ret .= path "`n" 
      } 
   } 
   else 
   { 
      if selection 
         collection := window.document.SelectedItems 
      else 
         collection := window.document.Folder.Items 
      for item in collection 
         ret .= item.path "`n" 
   } 
   return Trim(ret,"`n") 
}

/*
Explorer_GetAll(hwnd="") 
{ 
   return Explorer_Get(hwnd) 
} 
Explorer_GetSelected(hwnd="") 
{ 
   return Explorer_Get(hwnd,true) 
} 
Explorer_GetPath(hwnd="") 
{ 
   if !(window := Explorer_GetWindow(hwnd)) 
      return ErrorLevel := "ERROR" 
   if (window="desktop") 
      return A_Desktop 
   path := window.LocationURL 
   path := RegExReplace(path, "ftp://.*@","ftp://") 
   StringReplace, path, path, file:/// 
   StringReplace, path, path, /, \, All 
    
   ; thanks to polyethene 
   Loop 
      If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex) 
         StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All 
      Else Break 
   return path 
}

/DEBUG - переводит программу в отладочный режим, при этом функционал, связанный с интеграцией плеера в систему, отключается. 
[С этим ключом вы можете запустить несколько копий программы] 
[Входные параметры не используется]


/ADD_PLAY - Добавить объекты в плейлист и начать его воспроизведение. 
[Под объектом понимается - плейлист, папка или файл] 
[Входные параметры - пути к объектам]


/BOOKMARK - Добавить файлы и/или папки в закладки. 
[Входные параметры - пути к файлам и/или папкам]


/DIR - Добавить папку(и) в плейлист. 
[Начнется ли проигрывание добавленных файлов, зависит от выставленных настроек плеера] 
[Входные параметры - пути к папкам]


/FILE - Добавить файл(ы) в плейлист. 
[Начнется ли проигрывание добавленных файлов, зависит от выставленных настроек плеера] 
[Входные параметры - пути к файлам]


/INSERT - Добавить объекты в плейлист. 
[Начнется ли проигрывание добавленных файлов, зависит от выставленных настроек плеера] 
[Под объектом понимается - плейлист, папка или файл] 
[Входные параметры - пути к объектам]


/RESTORE - Восстановить плеер на передний план 
[Входные параметры не используется]


/SKIN - Установка обложек в AIMP. После установки будет открыто окно настроек на странице выбора обложки. 
[Входные параметры - пути к обложкам]


/PLS - Открывает плейлисты в новых вкладках. 
[Начнется ли проигрывание плейлиста, зависит от выставленных настроек плеера] 
[Входные параметры - пути к плейлистам]


/CDA - Создает новый плейлист со списком файлов с указанного носителя с последующим его воспроизведением. 
[Входной параметр - [!] единственный - буква диска]


/PLAY - Начать воспроизведение 
[Входные параметры не используется]


/PAUSE - Приостановить воспроизведение 
[Входные параметры не используется]


/STOP - Остановить воспроизведение 
[Входные параметры не используется]


/NEXT - Следующий файл 
[Входные параметры не используется]


/PREV - Предыдущий файл 
[Входные параметры не используется]


/MUTE - Выключить / Включить звук 
[Входные параметры не используется]


/VOLUP - Прибавить громкость 
[Величина изменений громкости задается в настройках - Настройки \ Управление] 
[Входные параметры не используется]


/VOLDWN - Убавить громкость 
[Величина изменений громкости задается в настройках - Настройки \ Управление] 
[Входные параметры не используется]
*/

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

How the Shell Invokes Verbs
There are three ways that the Shell can invoke a verb.

Through COM and IDropTarget, by using a DropTarget key. This is the preferred method for Microsoft Windows XP and later systems.
As a command line call, as specified in a command key.
Through Dynamic Data Exchange (DDE), by using a ddeexec key.
Invoking a verb can launch the application specified by the verb's command subkey using CreateProcess. However, command-line verbs are limited by the maximum command-line length, so they are not useful for invoking verbs on multiple items. Command-line verbs are also restricted to working with items that can be represented as a string, such as a file system path.

Наилучшим способом добавления файлов наверное было бы использование IDropTarget interface, но моих знаний для этого не достаточно, надеюсь на помощь других участников форума в этом вопросе ? Кроме перечисленных способов была опробована отправка сообщеня WM_DROPFILES и Drop files simulation, пока безуспешно.

16

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:
Xwansu пишет:

Malcev, твой скрипт работает просто Шикарно. Many thanks!

На самом деле это не так, при выборе нескольких папок и файлов приложение AIMP3.exe будет запущено несколько раз, командой Run не предусмотрено ожидание завершения первой запущенной копии, что приводит к зависанию плеера (проверял на старенькой версии AIMP v2.60).Я это немного исправил посредством команды RunWait.

Я сейчас тоже проверил в версии AIMP3, выделил сразу 7 папок (с подпапками) - это 935 Мб и добавил в плейлист. Не заметил  никаких притормаживаний и зависаний. Процесс добавления никак не сказался на треке, который играл в данный момент.  В диспетчере задач тоже все спокойно: процесс AIMP3.exe ведет себя как обычно, потребление памяти не меняется.
PS: правда железо у меня не самое слабое.

17

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech, спасибо за твой вариант. Пока существенных отличий в работе 2х скриптов не заметил.

18 (изменено: Grey, 2012-02-17 09:06:01)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

SetBatchLInes, -1
CoordMode, Mouse

;SearchStr:="&Play in Winamp"
SearchStr:="AIMP3", SearchStr2:="Add to playlist"

F11:: ; http://www.autohotkey.com/forum/post-186048.html#186048
   IfWinNotExist, ahk_class #32768
      Send, {AppsKey}
   WinWait, ahk_class #32768,, 0.25
   If ErrorLevel
      Return
   MouseGetPos, xPos, yPos
   SendMessage, 0x1E1
   GetMenu(GetMenu(ErrorLevel, SearchStr), SearchStr2)
   MouseMove, xPos, yPos
   IfWinExist, ahk_class #32768
      WinClose, ahk_class #32768
   Return

GetMenu(hMenu, sStr)
{
   Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
   {
      If (DllCall("GetMenuState", "UInt", hMenu
                                , "UInt", A_Index-1
                                , "UInt", 0x400) & 0x860)
          Continue
      VarSetCapacity(sString, DllCall("GetMenuString", "UInt", hMenu
                                                     , "UInt", A_Index-1
                                                     , "UInt", 0
                                                     , "Int", 0
                                                     , "UInt", 0x400)*2)
      DllCall("GetMenuString", "UInt", hMenu
                             , "UInt", A_Index-1
                             , "Str", sString
                             , "Int", VarSetCapacity(sString)+1
                             , "UInt", 0x400)
      If % sString==sStr
      {
         SelectMenu(hMenu, A_Index-1)
         Return, DllCall("GetSubMenu", "UInt", hMenu, "Int", A_Index-1)
      }
   }
}

SelectMenu(hMenu, Index)
{
   VarSetCapacity(RECT, 16)
   DllCall("GetMenuItemRect", "UInt", 0
                            , "UInt", hMenu
                            , "UInt", Index
                            , "UInt", &RECT)
   xPos:=NumGet(RECT, 0)+(NumGet(RECT, 8)-NumGet(RECT, 0))//2
   yPos:=NumGet(RECT, 4)+(NumGet(RECT, 12)-NumGet(RECT, 4))//2
   MouseClick,, xPos, yPos,, 0
}

19

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey, не заработал: AIMP3, AHK_L. Только всплывает на доли секунды контекстное меню
В Winamp'е не пробывал. Если можно, в двух словах, как работает код и его преимущества перед вариантами выше.

20 (изменено: creature.ws, 2012-02-17 01:13:21)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

OFF: Пробывать, Пробовать.

21

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

creature.ws пишет:

OFF: Пробывать, Пробовать.

OFF: Теперь точно запомню, уже не в первый раз проскакивает. Попробую избегать это слово )

22

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

Grey, не заработал: AIMP3, AHK_L. Только всплывает на доли секунды контекстное меню

Xwansu, замени

SearchStr2:="Add to playlist"

на

SearchStr2:="Добавить в плейлист"

, у меня работает

Grey, спасибо, хороший пример вызова пунктов меню,
был ещё пример на оф. форуме вызова самого меню в произвольном месте экрана
Invoking directly ContextMenu of Files and Folders

Ещё один плохой способ добавления треков в плейлист AIMP-а, но который может быть применим для имитации перетаскивания файлов или других объектов из окна срипта:

DetectHiddenWindows On
CoordMode Mouse, Screen
CoordMode ToolTip, Screen

#vk41:: ; Win + A
ControlGet, hctrl, Hwnd,,TAIMPPlaylistView1, ahk_class TAIMP3MainWindow
if !DllCall("IsWindowVisible","uint",hctrl)
Return
WinGetPos wx,wy,ww,wh, ahk_id %hctrl%
if ww {
   MouseGetPos x,y
   ClipSaved := ClipboardAll
   Send ^{vk43} ; Ctrl + C
   WinActivate ahk_id %hctrl%
   wx+=ww/2, wy+=wh/2
   MouseMove wx,wy
   ToolTip Click Drag And Drop,wx-40,wy-10
   KeyWait LButton, D
   If DllCall("ole32\OleGetClipboard", "UintP", pdata)=0 
   {
      DllCall("shell32\SHDoDragDrop", "Uint", 0, "Uint", pdata, "Uint", 0, "Uint", 1|4, "UintP", nEffect)
      DllCall("ole32\OleSetClipboard","Uint",0)
      ToolTip
   }
   Clipboard := ClipSaved
   ClipSaved := 
   MouseMove x,y
}
Return

/*
Drop files simulation
http://www.autohotkey.com/forum/topic44936.html
*/

23

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:
Xwansu пишет:

Grey, не заработал: AIMP3, AHK_L. Только всплывает на доли секунды контекстное меню

Xwansu, замени

SearchStr2:="Add to playlist"

на

SearchStr2:="Добавить в плейлист"

, у меня работает

Проблема похоже не в этом.

24

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

Grey ...Если можно, в двух словах, как работает код...

Вам уже ответили:

kirtech пишет:

...пример вызова пунктов меню...

, далее:

Xwansu пишет:

...его преимущества перед вариантами выше.

преимущество в универсальности (!), скорости, отсутствует взаимодействие с буфером обмена.

kirtech пишет:

...был ещё пример на оф. форуме вызова самого меню в произвольном месте экрана

Сойдёт и нажатие на Appskey.

Xwansu пишет:

Проблема похоже не в этом.

Установили интерпретатор х64?, на нём работать не будет. Как вариант, можно скомпилировать (...\Ahk2Exe.exe (Unicode 32-bit)) этот скрипт в исполнительный файл, или скачать и поставить х86 версию.

Посмотреть точное написание пунктов меню, можно этим скриптом:

SetBatchLInes, -1

Ctrl & RButton:: ; http://www.autohotkey.com/forum/post-137692.html#137692
   IfWinNotExist, ahk_class #32768
   {
      Send, {AppsKey}
      WinWait, ahk_class #32768,, 0.25
         If ErrorLevel
            Return
   }
   SendMessage, 0x1E1
   MsgBox, 262144, Menuitem names, % GetMenu(ErrorLevel)
   Return

GetMenu(hMenu)
{
   Loop, % DllCall("GetMenuItemCount", "UInt", hMenu)
   {
      nPos:=DllCall("GetMenuItemID", "UInt", hMenu
                                   , "Int", A_Index-1)
      VarSetCapacity(sString, DllCall("GetMenuString", "UInt", hMenu
                                                     , "UInt", A_Index-1
                                                     , "UInt", 0
                                                     , "Int", 0
                                                     , "UInt", 0x400)*2)
      DllCall("GetMenuString", "UInt", hMenu
                             , "UInt", A_Index-1
                             , "Str", sString
                             , "Int", VarSetCapacity(sString)+1
                             , "UInt", 0x400)
      If !sString
         sString:="---------------------------------------"
      sContents.=A_Index-1 " : "(nPos=-1?"submenu":nPos) "`t`t"sString "`n"
      If (nPos=-1) And (hSubMenu:=DllCall("GetSubMenu", "UInt", hMenu
                                                      , "Int", A_Index-1))
         sContents.=GetMenu(hSubMenu)
   }
   Return, sContents
}

25

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey пишет:

интерпретатор х64?

Да, это он.
А никак не убрать всплывающее меню?
Вот похожая тема: "It'll invoke the context menu of a file-system/virtual file or folder, without opening the explorer window." - Sean http://www.autohotkey.com/forum/topic22120.html

26

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

А никак не убрать всплывающее меню?

Нет.

Xwansu пишет:

Вот похожая тема:...

Похожая чем?, тем, что там перетирают за контекстное меню? Чем просто эмуляция нажатия на Appskey не нравится?
Собственно тот код, Вы его запускали?

27

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey пишет:
Xwansu пишет:

А никак не убрать всплывающее меню?

Нет.

Понятно.

Grey пишет:
Xwansu пишет:

Вот похожая тема:...

Похожая чем?, тем, что там перетирают за контекстное меню? Чем просто эмуляция нажатия на Appskey не нравится?

Я против эмуляции нажатия на Appskey ничего не имею
Просто там на третьей странице идет обсуждение вызова пунктов меню без всплывающего окна (типа операция проходит в фоновом режиме).
http://www.autohotkey.com/forum/topic22120-30.html

Eucaly61 пишет:

below is the demo code to get and invoke ContextMenu (ShellEx) items without bring up popup menu

28

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey пишет:

...тот код, Вы его запускали?

А равно как и этот с третьей страницы?

29

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey пишет:
Grey пишет:

...тот код, Вы его запускали?

А равно как и этот с третьей страницы?

Первый да, второй - нет.

---------------------------
ShellContextMenu.ahk
---------------------------
Error at line 61.

#Include file "CoHelper.ahk" cannot be opened.

The program will exit.
---------------------------
ОК   
---------------------------

30 (изменено: creature.ws, 2012-02-19 00:27:47)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Дык по ссылочке, выше кода, имеется ссылка на архив с этим самым CoHelper.ahk, явное указание необходимости его скачать, распаковать и положить в папку со скриптом тоже имеется.

#Include CoHelper.ahk

31 (изменено: Malcev, 2012-02-19 00:32:50)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Только линк там пустой
http://www.autohotkey.com/forum/topic16631.html
http://www.autohotkey.com/forum/viewtopic.php?t=22923

32

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Ну вот и исчерпан вопрос

33

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

creature.ws пишет:

Дык по ссылочке, выше кода, имеется ссылка на архив с этим самым CoHelper.ahk, явное указание необходимости его скачать, распаковать и положить в папку со скриптом тоже имеется.

#Include CoHelper.ahk

Я знаю (прочитал всю ветку)

Sean пишет:

Gauss wrote:

The link for CoHelper.ahk is dead

Not just dead, it was deleted from the storage since some users had constantly annoyed by still posting questions on this library which became obsolete almost two years ago. And, this script is no longer maintained.

34

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Значит намеренно утаивали информацию нет, маловероятно, что «тот» скрипт кто-то возьмётся адаптировать под AHK-L.

35

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

creature.ws пишет:

Значит намеренно утаивали информацию нет, маловероятно, что «тот» скрипт кто-то возьмётся адаптировать под AHK-L.

Плюс, неизвестно, работает ли, всё-таки, «тот» скрипт или нет...(возможен перебор с запятыми)

36

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

cohelper.ahk
http://de.autohotkey.com/forum/topic7108.html

37

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Чтобы запустить тот скрипт с первой страницы, надо скачать библиотеку обозначенную как COM.zip, и поместить её в папку Lib созданную в корневой папке программы. Это ещё не всё, далее в самом том (ShellContextMenu.ahk) скрипте, нужно добавить префиксы к вызываемым функциям (на пример: к CoInitialize() добавить COM_, чтобы получилось COM_CoInitialize()), строку вида: #Include CoHelper.ahk - следует удалить. Скрипт с третьей страницы работает и с COM, и с COM_L библиотекой.

В итоге, что получается, даже если всё же выше обозначенные (тот и этот) скрипты запускаются:
первый скрипт выводит контекстное меню с указанием пути до папки скрипта
второй выводит ГЪЮИ с информацией о GUID и т.п., далее дела у него не идут

А теперь стоит подумать, для чего эта возня, если всё можно решить эмуляцией нажатия одной кнопки, которая в коде прописана одной строкой?

38

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Grey, спасибо за развернутый ответ.
Я так понимаю, даже если бы эта штука работала, то пострадала бы еще скорость результирующего скрипта.
Поэтому, те, кому режет глаза всплывающее меню - могут использовать скрипт от Malcev. Остальные - юзать более универсальный (!) скрипт от Grey.

39

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

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

40 (изменено: kirtech, 2012-02-26 19:56:51)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Совместил и переработал срипты:
1.ShellContextMenu.ahk by Sean
2.Get and invoke ContextMenu (ShellEx) items without bring up popup menu by Eucaly61
3.Выполнить пункт меню файла в папке, используя COM спасибо teadrinker
, англ.InvokeVerb()

Добавление выделенных папок и файлов в AIMP3 работает. Возможно вызывать и другие пункты контекстного меню проводника применительно к выделенным папкам и файлам, но без недостатков не обошлось. С каждым вызовом меню происходит небольшая утечка памяти и объектов Gdi, от меня не зависящая, с которой было принято решение бороться с помощью перезагрузки скрипта, знаете другое решение - поделитесь.

Скрипт для получения (путём копирование в буфер обмена) списка доступных пунктов меню и визуализации самого меню. Вызываются команды вручную посредством клика, скрипт определяет ID команды и вызывает её. Последовательность пунктов меню и следовательно ID команд меняется, из-за чего автоматизация иногда бывает затруднена. Если вы видете что при вызове необходимого вам пункта меню для разных файлов и папок на разных дисках ID остаётся преждним, обычно это стандартные пункты "Свойства","Удалить","Создать ярлык"... , то можете использовать его во втором скрипте заменив функцию GetContexMenuCmdID("текст пункта меню|подменю") на полученный ID

/*
get and invoke ContextMenu (ShellEx) items without bring up popup menu
http://www.autohotkey.com/forum/post-271279.html#271279
IShellFolder::GetUIObjectOf
http://winapi.freetechsecrets.com/win32/WIN32IShellFolderGetUIObjectOf_Now_Su.htm
IContextMenu::QueryContextMenu
http://winapi.freetechsecrets.com/win32/WIN32IContextMenu.htm
Shell Interfaces
http://msdn.microsoft.com/en-us/library/windows/desktop/bb774328(v=vs.85).aspx
http://source.winehq.org/source/include/shobjidl.idl#L252
http://www.koders.com/noncode/fid66A0E1FAB1C94FB665CFA5236DA4CDAEA22742CE.aspx#L1051
http://www.netez.com/2xExplorer/shellFAQ/shmain.html
*/

DetectHiddenWindows, On 
Process, Exist 
WinGet, hAHK,ID,ahk_pid %ErrorLevel%

Reload_After:=20 ; боремся с утечкой ресурсов путём перезагрузки скрипта после определённого кол-ва вызовов меню
                 ; если знаете, предложите другой способ ?

global hMenu,mStr,pcm,ici,riid_IShellFolder,riid_IContextMenu,mText
riid_IShellFolder:=GUID(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}")
riid_IContextMenu:=GUID(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}")

global pHandleMenuMsg,pcm2,pcm3,uIdSubclass:=1
pHandleMenuMsg:=RegisterCallback("HandleMenuMsg","Fast",6)

NumPut(VarSetCapacity(ici,16+5*A_PtrSize,0),ici)
NumPut(0x4000,ici,4) ; CMIC_MASK_UNICODE = 0x4000
NumPut(hAHK,ici,8)

^F11::
WinGet, ID,, A
WinGetClass, Class, A
if !(Class~="(Cabinet|Explore)WClass")
Return

oShell:=ComObjCreate("Shell.Application")
Loop % oShell.Windows.Count {
oIE:=oShell.Windows.Item(A_Index-1)
Sleep 10
} Until oIE.HWND=ID
 
oFolderItems:=oIE.Document.SelectedItems
pc:=oFolderItems.Count
if !pc {
MsgBox, Ничего не выделено!
oShell:=oIE:=oFolderItems:=""
Return
}

pl:=[]
VarSetCapacity(apidl,pc*A_PtrSize,0)
pc:=0 ; pointers count
hMenu:=DllCall("CreatePopupMenu")
for Item in oFolderItems {
DllCall("shell32\SHParseDisplayName","str",Item.Path,"ptr",0,"ptr*",_pidl,"uint",0,"uint*",0)
DllCall("shell32\SHBindToParent","ptr",_pidl,"ptr",riid_IShellFolder,"ptr*",pIShellFolder,"ptr*",pidl)
pl.Insert(_pidl)
NumPut(pidl,apidl,pc*A_PtrSize)
++pc
if (pc<>oFolderItems.Count) ; Release ?
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
}
; IShellFolder::GetUIObjectOf
if DllCall(VTable(pIShellFolder,10),"ptr",pIShellFolder,"ptr",0,"uint",pc,"ptr",&apidl,"ptr",riid_IContextMenu,"ptr",0,"ptr*",pcm)
return
; IUnknown::QueryInterface
DllCall(VTable(pcm,0),"ptr",pcm,"ptr",GUID(IID_IContextMenu3,"{BCFCE0A0-EC17-11D0-8D10-00A0C90F2719}"),"ptr*",pcm3)
DllCall(VTable(pcm,0),"ptr",pcm,"ptr",GUID(IID_IContextMenu2,"{000214F4-0000-0000-C000-000000000046}"),"ptr*",pcm2)
if pcm {
; IContextMenu::QueryContextMenu         ##### Утечка памяти и объектов Gdi !? #####
DllCall(VTable(pcm,3),"ptr",pcm,"ptr",hMenu,"uint",0,"uint",3,"uint",0x7FFF,"uint",0)
GetContexMenuCmdID("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") ; текст пункта меню длиной этой строки будет помещён в буфер обмена
subclassed:=DllCall("SetWindowSubclass","ptr",hAHK,"ptr",pHandleMenuMsg,"ptr",uIdSubclass,"ptr",0)
DllCall("GetCursorPos","int64P",pt)                      ; TPM_RETURNCMD   =   0x100
TrayTip,,% "ID команды`nменю " miID:=DllCall("TrackPopupMenu","ptr",hMenu,"ptr",0x100,"int",pt<<32>>32,"int",pt>>32,"int",0,"ptr",hAHK,"ptr",0) 
NumPut(miID-3,ici,8+A_PtrSize)
; IContextMenu::InvokeCommand
DllCall(VTable(pcm,4),"ptr",pcm,"ptr",&ici)
}
; Release
DllCall(VTable(pcm,2),"ptr",pcm3)
DllCall(VTable(pcm,2),"ptr",pcm2)
DllCall(VTable(pcm,2),"ptr",pcm)
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
Loop % pl.MaxIndex()
DllCall("ole32\CoTaskMemFree","ptr",pl[A_Index])
if DllCall("RemoveWindowSubclass","ptr",hAHK,"ptr",pHandleMenuMsg,"ptr",uIdSubclass)
subclassed:=0
DllCall("DestroyMenu","ptr",hMenu)
oShell:=oIE:=oFolderItems:=""
Clipboard:=mText ; Поместим в буфер обмена текст пунктов меню у которых он получен
--Reload_After
if !Reload_After
Reload
Return

Esc::
if subclassed
DllCall("RemoveWindowSubclass","uint",hAHK,"uint",pHandleMenuMsg,"uint",uIdSubclass)
ExitApp

GetContexMenuCmdID(CmdName)
{
 Loop, Parse, CmdName, | 
 {
  nmatch:=A_Index
  miText:=A_LoopField
  nSize:=StrLen(miText)+2 ; "&" + 00
  VarSetCapacity(mStr,nSize*2,0)
  if (A_Index=1)
  _hMenu:=hMenu
  else _hMenu:=DllCall("GetSubMenu","ptr",_hMenu,"int",miN)
  Loop, % DllCall("GetMenuItemCount","ptr",_hMenu)
  { 
    miN:=A_Index-1, miID:=DllCall("GetMenuItemID","ptr",_hMenu,"int",miN)
    DllCall("GetMenuStringW","ptr",_hMenu,"int",miN,"wstr",mStr,"int",nSize,"uint",0x400)
    StringReplace, _mStr,mStr,&,,All
	mText.=mStr "`n"
    if (miText=_mStr) {
    ++match
    Break
    }
  }
 }
 if (match=nmatch)
 return miID
}

VTable(ptr, n) {
  return NumGet(NumGet(ptr+0),n*A_PtrSize)
}

GUID(ByRef GUID, sGUID) ; Converts a string to a binary GUID and returns its address.
{
  VarSetCapacity(GUID,16,0)
  return DllCall("ole32\CLSIDFromString","wstr",sGUID,"ptr",&GUID) >= 0 ? &GUID : ""
}

HandleMenuMsg(hWnd,Msg,wParam,lParam,IdSubclass,dwRefData)
{ 
  Critical
  if (IdSubclass=1) {
   If pcm3 { 
   If !DllCall(VTable(pcm3,7),"ptr", pcm3,"uint",Msg,"uint",wParam, "ptr",lParam,"uintP",lResult)
   Return lResult
   } 
   Else If pcm2 {
   If !DllCall(VTable(pcm3,6),"ptr",pcm2,"uint",Msg,"uint",wParam,"ptr",lParam) 
   Return 0 
   } 
 }
  Return DllCall("DefSubclassProc","uint",hWnd,"uint",Msg,"uint",wParam,"ptr",lParam)
}

/*
529 WM_ENTERMENULOOP
32  WM_SETCURSOR
278 WM_INITMENU 
279 WM_INITMENUPOPUP
44  WM_MEASUREITEM
43  WM_DRAWITEM 
289 WM_ENTERIDLE
287 WM_MENUSELECT
533 WM_CAPTURECHANGED 
293
530 WM_EXITMENULOOP
*/

Рабочий скрипт, добвляет файлы и папки в AIMP3 посредством выделения в проводнике и нажатия Ctrl + F11

/*
get and invoke ContextMenu (ShellEx) items without bring up popup menu
http://www.autohotkey.com/forum/post-271279.html#271279
IShellFolder::GetUIObjectOf
http://winapi.freetechsecrets.com/win32/WIN32IShellFolderGetUIObjectOf_Now_Su.htm
IContextMenu::QueryContextMenu
http://winapi.freetechsecrets.com/win32/WIN32IContextMenu.htm
Shell Interfaces
http://msdn.microsoft.com/en-us/library/windows/desktop/bb774328(v=vs.85).aspx
http://source.winehq.org/source/include/shobjidl.idl#L252
http://www.koders.com/noncode/fid66A0E1FAB1C94FB665CFA5236DA4CDAEA22742CE.aspx#L1051
http://www.netez.com/2xExplorer/shellFAQ/shmain.html
*/

DetectHiddenWindows, On 
Process, Exist 
WinGet, hAHK,ID,ahk_pid %ErrorLevel%

Reload_After:=20 ; боремся с утечкой ресурсов путём перезагрузки скрипта после определённого кол-ва вызовов меню
                 ; если знаете, предложите другой способ ?

global hMenu,mStr,pcm,ici,riid_IShellFolder,riid_IContextMenu
riid_IShellFolder:=GUID(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}")
riid_IContextMenu:=GUID(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}")

oShell:=ComObjCreate("Shell.Application")
NumPut(VarSetCapacity(ici,16+5*A_PtrSize,0),ici)
NumPut(0x4000,ici,4) ; CMIC_MASK_UNICODE = 0x4000
NumPut(hAHK,ici,8)

^F11::
WinGet, ID,, A
WinGetClass, Class, A
if !(Class~="(Cabinet|Explore)WClass")
Return

Loop % oShell.Windows.Count {
oIE:=oShell.Windows.Item(A_Index-1)
Sleep 10
} Until oIE.HWND=ID
 
oFolderItems:=oIE.Document.SelectedItems
pc:=oFolderItems.Count
if !pc {
MsgBox, Ничего не выделено!
oShell:=oIE:=oFolderItems:=""
Return
}

pl:=[]
VarSetCapacity(apidl,pc*A_PtrSize,0)
pc:=0 ; pointers count
hMenu:=DllCall("CreatePopupMenu")
for Item in oFolderItems {
DllCall("shell32\SHParseDisplayName","str",Item.Path,"ptr",0,"ptr*",_pidl,"uint",0,"uint*",0)
DllCall("shell32\SHBindToParent","ptr",_pidl,"ptr",riid_IShellFolder,"ptr*",pIShellFolder,"ptr*",pidl)
pl.Insert(_pidl)
NumPut(pidl,apidl,pc*A_PtrSize)
++pc
if (pc<>oFolderItems.Count) ; Release ?
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
}
; IShellFolder::GetUIObjectOf
if DllCall(VTable(pIShellFolder, 10),"ptr",pIShellFolder,"ptr",0,"uint",pc,"ptr",&apidl,"ptr",riid_IContextMenu,"ptr",0,"ptr*",pcm)
return
if pcm {
; IContextMenu::QueryContextMenu         ##### Утечка памяти и объектов Gdi !? #####
DllCall(VTable(pcm,3),"ptr",pcm,"ptr",hMenu,"uint",0,"uint",3,"uint",0x7FFF,"uint",0)
; DllCall("GetCursorPos","int64P",pt)                       ; TPM_RETURNCMD   =   0x100
; TrayTip,,% "ID команды`nменю " miID:=DllCall("TrackPopupMenu","ptr",hMenu,"ptr",0x100,"int",pt<<32>>32,"int",pt>>32,"int",0,"ptr",hAHK,"ptr",0) 
if miID:=GetContexMenuCmdID("AIMP3|Добавить в плейлист") { ; парсим текст меню и подменю для получения ID команды, ID имеет свойство меняться
  NumPut(miID-3,ici,8+A_PtrSize)
; ContextMenu::InvokeCommand
  DllCall(VTable(pcm,4),"ptr",pcm,"ptr",&ici)
 }
}
; Release
DllCall(VTable(pcm,2),"ptr",pcm)
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
Loop % pl.MaxIndex()
DllCall("ole32\CoTaskMemFree","ptr",pl[A_Index])
DllCall("DestroyMenu","ptr",hMenu)
oIE:=oFolderItems:=""
--Reload_After
if !Reload_After
Reload
Return

Esc::ExitApp

GetContexMenuCmdID(CmdName)
{
 Loop, Parse, CmdName, | 
 {
  nmatch:=A_Index
  miText:=A_LoopField
  nSize:=StrLen(miText)+2 ; "&" + 00
  VarSetCapacity(mStr,nSize*2,0)
  if (A_Index=1)
  _hMenu:=hMenu
  else _hMenu:=DllCall("GetSubMenu","ptr",_hMenu,"int",miN)
  Loop, % DllCall("GetMenuItemCount","ptr",_hMenu)
  { 
    miN:=A_Index-1, miID:=DllCall("GetMenuItemID","ptr",_hMenu,"int",miN)
    DllCall("GetMenuStringW","ptr",_hMenu,"int",miN,"wstr",mStr,"int",nSize,"uint",0x400)
    StringReplace, _mStr,mStr,&,,All
	;Clipboard.=mStr "`n"
    if (miText=_mStr) {
    ++match
    Break
    }
  }
 }
 if (match=nmatch)
 return miID
}

VTable(ptr, n) {
  return NumGet(NumGet(ptr+0),n*A_PtrSize)
}

GUID(ByRef GUID, sGUID) ; Converts a string to a binary GUID and returns its address.
{
  VarSetCapacity(GUID,16,0)
  return DllCall("ole32\CLSIDFromString","wstr",sGUID,"ptr",&GUID) >= 0 ? &GUID : ""
}

Оба срипта могут использоваться если закрыть глаза на утечку ресурсов
Скрипт был опробован на двух компьютерах под Windows XP SP3, AutoHotkey_L x86 Unicode,  но возможно будет работать и на x64

Если кому необходимо, скрипт возможно приспособить и для AHK Basic
CoHelper.ahk

/*
CoHelper.ahk
*/

VTable(ppv, idx)
{
   Return DecodeInteger(DecodeInteger(ppv) + idx * 4)
}

DecodeInteger(ptr)
{
   Return *ptr | *++ptr << 8 | *++ptr << 16 | *++ptr << 24
}

EncodeInteger(ref, val)
{
   DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}

Ansi2Unicode(ByRef sString, ByRef wString, nLen = 0)
{
   If !nLen
      nLen := DllCall("MultiByteToWideChar"
      , "Uint", 0
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", 0
      , "int",  0)

   VarSetCapacity(wString, nLen * 2)

   DllCall("MultiByteToWideChar"
      , "Uint", 0
      , "Uint", 0
      , "Uint", &sString
      , "int",  -1
      , "Uint", &wString
      , "int",  nLen)
}

Unicode2Ansi(ByRef wString, ByRef sString, nLen = 0)
{
   pString := wString + 0 > 65535 ? wString : &wString

   If !nLen
      nLen := DllCall("WideCharToMultiByte"
      , "Uint", 0
      , "Uint", 0
      , "Uint", pString
      , "int",  -1
      , "Uint", 0
      , "int",  0
      , "Uint", 0
      , "Uint", 0)

   VarSetCapacity(sString, nLen)

   DllCall("WideCharToMultiByte"
      , "Uint", 0
      , "Uint", 0
      , "Uint", pString
      , "int",  -1
      , "str",  sString
      , "int",  nLen
      , "Uint", 0
      , "Uint", 0)
}

CLSID4ProgID(Byref CLSID, sProgID)
{
   VarSetCapacity(CLSID, 16)
   Ansi2Unicode(sProgID, wProgID)
   DllCall("ole32\CLSIDFromProgID", "str", wProgID, "str", CLSID)
}

GUID4String(Byref CLSID, sString)
{
   VarSetCapacity(CLSID, 16, 0)
   Ansi2Unicode(sString, wString, 39)
   DllCall("ole32\CLSIDFromString", "str", wString, "str", CLSID)
}

String4GUID(Byref CLSID)
{
   VarSetCapacity(wString, 39 * 2)
   DllCall("ole32\StringFromGUID2", "str", CLSID, "str", wString, "int", 39)
   Unicode2Ansi(wString, sString, 39)
   Return sString
}

CreateObject(ByRef CLSID, ByRef IID, CLSCTX = 5)
{
   If ( StrLen(CLSID) = 38 )
   GUID4String(CLSID, CLSID)
   If ( StrLen(  IID) = 38 )
   GUID4String(  IID,   IID)
   DllCall("ole32\CoCreateInstance", "str", CLSID, "Uint", 0, "Uint", CLSCTX, "str", IID, "UintP", ppv)
   Return ppv
}

GetObject(Namespace)
{
   Ansi2Unicode(Namespace, wNamespace)
   GUID4String(IID_IDispatch, "{00020400-0000-0000-C000-000000000046}")
   DllCall("ole32\CoGetObject", "str", wNamespace, "Uint", 0, "str", IID_IDispatch, "UintP", pdisp)
   Return pdisp
}

GetActiveObject(ProgID)
{
   CLSID4ProgID(CLSID, ProgID)
   DllCall("oleaut32\GetActiveObject", "str", CLSID, "Uint", 0, "UintP", punk)
   Return punk
}

SysAllocString(sString)
{
   Ansi2Unicode(sString, wString)
   Return DllCall("oleaut32\SysAllocString", "str", wString)
}

SysFreeString(pString)
{
   Return DllCall("oleaut32\SysFreeString", "Uint", pString)
}

OleInitialize()
{
   DllCall("ole32\OleInitialize", "Uint", 0)
}

OleUninitialize()
{
   DllCall("ole32\OleUninitialize")
}

CoInitialize()
{
   DllCall("ole32\CoInitialize", "Uint", 0)
}

CoUninitialize()
{
   DllCall("ole32\CoUninitialize")
}

QueryInterface(ppv, ByRef IID)
{
   If ( StrLen(IID) = 38 )
   GUID4String(IID,   IID)
   DllCall(DecodeInteger(DecodeInteger(ppv)), "Uint", ppv, "str", IID, "UintP", ppv)
   Return ppv
}

AddRef(ppv)
{
   Return DllCall(DecodeInteger(DecodeInteger(ppv) + 4), "Uint", ppv)
}

Release(ppv)
{
   Return DllCall(DecodeInteger(DecodeInteger(ppv) + 8), "Uint", ppv)
}

QueryService(ppv, ByRef SID, ByRef IID)
{
   If ( StrLen(SID) = 38 )
   GUID4String(SID,   SID)
   If ( StrLen(IID) = 38 )
   GUID4String(IID,   IID)
   GUID4String(IID_IServiceProvider, "{6D5140C1-7436-11CE-8034-00AA006009FA}")
   DllCall(DecodeInteger(DecodeInteger(ppv)), "Uint", ppv, "str", IID_IServiceProvider, "UintP", psp)
   DllCall(DecodeInteger(DecodeInteger(psp) + 12), "Uint", psp, "str", SID, "str", IID, "UintP", ppv)
   DllCall(DecodeInteger(DecodeInteger(psp) +  8), "Uint", psp)
   Return ppv
}

41 (изменено: Xwansu, 2012-02-26 00:28:57)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:

Скрипт был опробован на двух компьютерах под Windows XP SP3, AutoHotkey_L x86 Unicode,  но возможно будет работать и на x64

Не работает на win7 x64, AutoHotkey_L  Unicode.

При использовании скрипта (by Malcev) некоторые файлы добавляются некорректно.
Code: 2 (00000002)
Message: Can't open the file
Думаю, проблема связана с тегами...

42 (изменено: kirtech, 2012-02-26 19:58:52)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

Не работает на win7 x64, AutoHotkey_L  Unicode.

Это моя ошибка, я не учёл что указатели в структуре ici займут 8 байт каждый ,  в сриптах выше уже поправил. Установил Windows 7 x64 в VirtualBox нашел и исправил ошибки, проверил - работает.

Насчёт утечек объектов Gdi утилита GdiUsage,показала что это изображения добавляемые в меню сторонними приложениями(AkelPad например) и они не удаляются после его разрушения. Я пытался их получить для дальнейшего удаления с помощью следующего кода, но безрезультатно.


GetContexMenuBitmaps()
{
	VarSetCapacity(MENUITEMINFO,44,0)
	NumPut(0x10,MENUITEMINFO,4) ; MIIM_TYPE = 0x10
	NumPut(4,MENUITEMINFO,8)  ; MFT_BITMAP = 0x4
	Loop % DllCall("GetMenuItemCount","ptr",hMenu) {
    miN:=A_Index-1
	;miID:=DllCall("GetMenuItemID","ptr",hMenu,"int",miN)
    msgbox % DllCall("GetMenuItemInfoW","ptr",hMenu,"uint",miN,"int",1,"ptr",&MENUITEMINFO)
	if hbmp:=NumGet(MENUITEMINFO,36) ; NumGet(MENUITEMINFO,24)
	bitmaps.=hbmp "`n"
	;hSubMenu:=NumGet(MENUITEMINFO,20)
	}
    msgbox % bitmaps
}

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

43

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:
Xwansu пишет:

Не работает на win7 x64, AutoHotkey_L  Unicode.

Замените строки:

NumPut(VarSetCapacity(ici,36,0),ici)
на 
NumPut(VarSetCapacity(ici,16+5*A_PtrSize,0),ici)
...
NumPut(miID-3,ici,12)
на
NumPut(miID-3,ici,8+A_PtrSize)

Заменил две этих строки, сохранил в формате Unicode. При запуске ничего не происходит, ошибок нет.

44

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu пишет:

Заменил две этих строки, сохранил в формате Unicode. При запуске ничего не происходит, ошибок нет.

Выполните следующий скрипт с одним выделенным файлом или папкой  и пришлите отчет который будет скопирован в буфер обмена (пример смотрите ниже), а там будет видно.

DetectHiddenWindows, On 
Process, Exist 
WinGet, hAHK,ID,ahk_pid %ErrorLevel%
global hMenu,mStr,pcm,ici,riid_IShellFolder,riid_IContextMenu,mText
riid_IShellFolder:=GUID(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}")
riid_IContextMenu:=GUID(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}")
NumPut(VarSetCapacity(ici,16+5*A_PtrSize,0),ici), NumPut(0x4000,ici,4), NumPut(hAHK,ici,8)

^F11::
WinGet, ID,, A
WinGetClass, Class, A
if !(Class~="(Cabinet|Explore)WClass")
Return
err .="1." ID "|"
oShell:=ComObjCreate("Shell.Application")
Loop % oShell.Windows.Count {
oIE:=oShell.Windows.Item(A_Index-1)
Sleep 10
} Until oIE.HWND=ID
oFolderItems:=oIE.Document.SelectedItems
pc:=oFolderItems.Count
if !pc {
MsgBox, Ничего не выделено!
oShell:=oIE:=oFolderItems:=""
Return
}
err .="2." pc "|"
pl:=[]
VarSetCapacity(apidl,pc*A_PtrSize,0) ,pc:=0, hMenu:=DllCall("CreatePopupMenu")
for Item in oFolderItems {
err .="3." DllCall("shell32\SHParseDisplayName","str",Item.Path,"ptr",0,"ptr*",_pidl,"uint",0,"uint*",0) "|"
err .="4." DllCall("shell32\SHBindToParent","ptr",_pidl,"ptr",riid_IShellFolder,"ptr*",pIShellFolder,"ptr*",pidl) "|"
pl.Insert(_pidl)
NumPut(pidl,apidl,pc*A_PtrSize)
++pc
if (pc<>oFolderItems.Count)
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
}
err .="5." DllCall(VTable(pIShellFolder, 10),"ptr",pIShellFolder,"ptr",0,"uint",pc,"ptr",&apidl,"ptr",riid_IContextMenu,"ptr",0,"ptr*",pcm) "|"
if pcm {
err .="6." DllCall(VTable(pcm,3),"ptr",pcm,"ptr",hMenu,"uint",0,"uint",3,"uint",0x7FFF,"uint",0) "|" 
if miID:=GetContexMenuCmdID("AIMP3|Добавить в плейлист")
  err .="7." miID "|"
  NumPut(miID-3,ici,8+A_PtrSize)
  err .="8." DllCall(VTable(pcm,4),"ptr",pcm,"ptr",&ici) "|"
}
DllCall(VTable(pcm,2),"ptr",pcm)
DllCall(VTable(pIShellFolder,2),"ptr",pIShellFolder)
Loop % pl.MaxIndex()
DllCall("ole32\CoTaskMemFree","ptr",pl[A_Index])
DllCall("DestroyMenu","ptr",hMenu)
oIE:=oFolderItems:=""
Clipboard:=err "`n`n" mText
err:=""
Return

Esc::ExitApp

GetContexMenuCmdID(CmdName)
{
 Loop, Parse, CmdName, | 
 {
  nmatch:=A_Index
  miText:=A_LoopField
  nSize:=StrLen(miText)+2 ; "&" + 00
  VarSetCapacity(mStr,nSize*2,0)
  if (A_Index=1)
  _hMenu:=hMenu
  else _hMenu:=DllCall("GetSubMenu","ptr",_hMenu,"int",miN)
  Loop, % DllCall("GetMenuItemCount","ptr",_hMenu)
  { 
    miN:=A_Index-1, miID:=DllCall("GetMenuItemID","ptr",_hMenu,"int",miN)
    DllCall("GetMenuStringW","ptr",_hMenu,"int",miN,"wstr",mStr,"int",nSize,"uint",0x400)
    StringReplace, _mStr,mStr,&,,All
	mText .=mStr "`n"
    if (miText=_mStr) {
    ++match
    Break
    }
  }
 }
 if (match=nmatch)
 return miID
}

VTable(ptr, n) {
  return NumGet(NumGet(ptr+0),n*A_PtrSize)
}

GUID(ByRef GUID, sGUID) ; Converts a string to a binary GUID and returns its address.
{
  VarSetCapacity(GUID,16,0)
  return DllCall("ole32\CLSIDFromString","wstr",sGUID,"ptr",&GUID) >= 0 ? &GUID : ""
}

Цифры после "3.","4.","5.","8." должны быть нулями, остальные просто должны быть.

1.0x101fa|2.1|3.0|4.0|5.0|6.170|7.159|8.0|

&Откры
&App M
&Прово
&Searc
[--- &
&Просм
&Найти
Добави
Воспро
Добави
&Добав
&Воспр

AIMP3
Воспроизвести
Добавить в плейлист

45

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Ответил по e-mail

46 (изменено: kirtech, 2012-02-26 23:05:55)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Xwansu, клавиши Ctrl + F11 нажимаете находясь в окне проводника? Судя по этим строчкам

if !(Class~="(Cabinet|Explore)WClass") ; ~= -> Сокращение команды RegExMatch [AHK_L 31+] !!!
013: Return (3.32)

скрипт не находит класса окна. Если вы действительно жали клавиши находясь в проводнике и при этом выделив папку или файл, то запустите утилиту ..\AutoHotkey\AutoHotkeyAU3_Spy.exe и навёв курсор мыши на окно проводника должны увидеть следующее:
http://i29.fastpic.ru/big/2012/0226/9a/33cf80dbdd8a8c72c3cf00086ef3a79a.png

47

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:

Xwansu, клавиши Ctrl + F11 нажимаете находясь в окне проводника?

Да.

kirtech пишет:

скрипт не находит класса окна. Если вы действительно жали клавиши находясь в проводнике и при этом выделив папку или файл, то запустите утилиту ..\AutoHotkey\AutoHotkeyAU3_Spy.exe и навёв курсор мыши на окно проводника должны увидеть следующее

Подтверждаю, все так и есть.

48

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

Замените:

WinGet, ID,, A
WinGetClass, Class, A
if !(Class~="(Cabinet|Explore)WClass")
Return
на 
ID:=WinActive("A")
WinGetClass, Class, ahk_id %ID%
if !(Class="CabinetWClass")
Return

что-то изменилось?

49

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech пишет:

Замените:

WinGet, ID,, A
WinGetClass, Class, A
if !(Class~="(Cabinet|Explore)WClass")
Return
на 
ID:=WinActive("A")
WinGetClass, Class, ahk_id %ID%
if !(Class="CabinetWClass")
Return

что-то изменилось?

Теперь все супер!
(но необходимо учитывать выбранный язык программы)
kirtech, спасибо - буду пока юзать Ваш вариант!

50 (изменено: Xwansu, 2012-03-03 06:51:12)

Re: AHK: хоткей на добавление выделенного файла в плейлист AIMP3/Winamp

kirtech, в чем м.б. проблема: AHK висит в трее и переодически вылетает ~ через каждые 10 мин. Раньше такого не было
update: вылетало, сейчас в норме