Autorun

Обсуждение только плагинов и утилит для Total Commander.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

A55555 писал(а):Можно ли добавить к этому поиску такую фишку, чтоб "http://" торрента-файла по которому ты только что искал файлы сразу попадала в буфер обмена?
Многое будет зависить от того, есть ли такая ссылка в файле, но попробовать можно. Модуль с изменениями:

[cut="Torrent.aucfg"]

Код: Выделить всё

Pragma IncludeOnce

# 70500-70599

RegisterCommand 70500 "TorrentFindData" 0
RegisterCommand 70501 "TorrentFindData" 1
RegisterCommand 70502 "GoToPathFromTextFile"
RegisterCommand 70503 "ToggleEverything"
RegisterCommand 70504 "FindTorrentParts"
RegisterCommand 70505 "TorrentSize"
RegisterCommand 70506 "TorrentFindOptions"
RegisterCommand 70507 "TorrentDebugInfo"

RegisterCommand 70508 "TorrentBugTest"

SetHotkeyAction /K:A /H:0 /DM /S TorrentDebugInfo
SetHotkeyAction /K:A /K:W /H:0 /DM /S TorrentFindOptions
SetHotkeyAction /K:A /K:W /H:T /DM /S TorrentFixedInfo

Global gEvPath = COMMANDER_PATH & "\Everything.exe", gEvAuto = 0, gEvDelay = 100

Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0, gTorrentUrl, gTorrentLog
Global gTorrentSize = 0, gTorrentCount = 0, gDriveInclude = "e:\;f:\;g:\;h:\;i:\;j:"

Global h_WinFindTorr = 0, g_WinThread = 0
Global g_WinFindTorr = 0, g_FindTorrTask = 0
Global o_WinFindTorr = Callback("WinFindTorrProc", "hwnd;uint;wparam;lparam")

Func WinFindTorrProc(hWnd, uMsg, wParam, lParam)
    Static WM_CLOSE = 0x0010
    If uMsg = WM_CLOSE Then
       If DllCall("DestroyWindow", "handle", hWnd) Then
          h_WinFindTorr = 0        
          g_FindTorrTask = 0
       EndIf   
       Return 0
    EndIf
    Return DllCall("CallWindowProcW", "ptr", g_WinFindTorr, _
                                      "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func WinFindTorrentData(bWhile = 1)
    Local hIco    
    h_WinFindTorr = DllCall("CreateWindowExW", _
                            "dword", 0, _
                            "wstr", "msctls_progress32", _
                            "wstr", "", _
                            "dword", 0x00C80000, _
                            "int", 200, "int", 100, "int", Scale(400), "int", Scale(50), _
                            "handle", AUTORUN_TCHANDLE, _
                            "handle", 0, "handle", 0, "ptr", 0, "handle")
    If h_WinFindTorr = 0 Then Return 0
    
    WinAlign(h_WinFindTorr, 0, DllCall("GetDesktopWindow"))
    WinSetPos("", -Scale(50), "", "", 1, h_WinFindTorr)
    WinSetState(5, h_WinFindTorr)
    
    g_WinFindTorr = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                            "hwnd", h_WinFindTorr, _
                            "int", -4, _
                            "long_ptr", o_WinFindTorr.Ptr, "ptr")
                            
    Static PBS_MARQUEE     =  0x08, _
           PBM_SETMARQUEE  =  1034, _
           WM_GETICON      =  0x7f, _
           WM_SETICON      =  0x80
           
    hIco = SendMessage(AUTORUN_TCHANDLE, WM_GETICON, 2, 0)                     
    SendMessage(h_WinFindTorr, WM_SETICON, 0, hIco)
    
    WinSetStyle(PBS_MARQUEE, 2, h_WinFindTorr)    
    SendMessage(h_WinFindTorr, PBM_SETMARQUEE, 1, 0)
    
    WinSetText("Searching...", h_WinFindTorr)
    
    g_FindTorrTask = 1
    If bWhile Then
       While g_FindTorrTask
           Sleep(50)
       Wend
       h_WinFindTorr = 0
    EndIf   
EndFunc

Func TorrentFindData(lParam, nMode)
    If IsPressed(0x10) And Not nMode Then
       SetTorrentDrives()
       Return
    EndIf
    Local bEverything = nMode
    If h_WinFindTorr Then
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       g_FindTorrTask = 0  
       Return
    Endif
    Static buf = Buffer(256)
    buf.Zero()
    Local nSymb = DllCall("GetLogicalDriveStringsW", "dword", buf.size, "ptr", buf.ptr)    
    If Not nSymb Then
       MsgBox("Не удалось получить список логических дисков" & auCRLF "SYSERROR: " & SYSERROR, "Autorun")
       Return
    EndIf
    Static aDrive = List(), aFound = List()
    Local i = 0, sz, sDrives
    aDrive.Count = 0
    While 1
       sDrive = buf.GetStr(i)
       sz = StrLen(sDrive)
       If sz = 0 Then break
       aDrive.add(sDrive)
       i = i + sz*2 + 2
    Wend
    sDrives = aDrive.text
    #MsgBox(sDrives)    
    Local obj = Plugin("TCTorrent")
    If ERROR <> 0 Then
       ShowHint("TCTorrent.wdx plugin error " & ERROR)
       Return
    Endif
    Local lRet = false 
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       lRet = true
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Каталог " & sFile)
       lRet = true
    ElseIf FileGetSize(sFile) > 1024*1024*5 Then
       ShowHint("Размер файла больше 5 Мб " & sFile)
       lRet = true
    Else
       obj.FileName = sFile
       Local name =  obj.GetValue(0)
       Local size = obj.GetValue(2,0)	# size -> bytes       
       Local files = obj.GetValue(1)
       If files < 1 Then
          ShowHint("Файл не является торрент-файлом " & sFile)
          lRet = true        
       EndIf
    Endif
    Free(obj)
    If lRet Then Return
    IniRead gDriveInclude %COMMANDER_INI% "Autorun" "TorrentDrives" %"gDriveInclude"
    Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
    If gCapsReverse Then bCaps = Not bCaps
    If Not bCaps Then
       MsgBox("Поиск данных торрента:" & auCRLF & auCRLF & _
              "Имя: "    & name & auCRLF & _
              "Размер: " & size & auCRLF & _
              "Файлов: " & files & auCRLF & auCRLF & _ 
              "Диски поиска: " & gDriveInclude & auCRLF & auCRLF & _       
              "Продолжить?", "Autorun", 3+32+0)
       If EXTENDED <> 6 Then Return
    Endif
    If bEverything Then 
       If gEvAuto And Not ProcessExist("Everything.exe") Then 
          ShellExec(gEvPath, "-startup")
          Sleep(gEvDelay)
       EndIf   
    EndIf      
    aFound.Count = 0    
    gTorrentSize = size
    h_WinFindTorr = 0
    gTorrentCount = 0
    RunThread "WinFindTorrentData"
    While g_FindTorrTask = 0
        Sleep(50)
    Wend
    TorrentGetFixed(0, 0, sFile)
    Local found
    If bEverything Then      
       found = FileFindEv("size:" & gTorrentSize, "", "sort:3")
       Local nError = ERROR
       If nError = 1 Then MsgBox("Не найдено окно Everything.")
       If nError = 2 Then MsgBox("Ошибка выполнения запроса к IPC Everything.")  
       If nError > 0 Then 
          g_FindTorrTask = 0
          Return
        EndIf  
    Else   
       For i = 0 to aDrive.Count -1
           If StrPos(gDriveInclude, aDrive[i]) Then
            If files > 1 Then
               found &= FileFind(aDrive[i], "*.*", 1, 2, "PathList", "Func:FindTorrentDir") & auCRLF
            Else
               found &= FileFind(aDrive[i], "*.*", 1, 1, "PathList", "Func:FindTorrentFile") & auCRLF
            EndIf   
           Endif   
       Next
    EndIf   
    found = StrTrim(found)
    aFound.Text = found
    If bEverything Then gTorrentCount = aFound.Count
    If bEverything And gEvAuto Then ShellExec(gEvPath, "-exit")     
    If g_FindTorrTask = 0 Then
       If gTorrentCount = 0 Then
          MsgBox("Поиск отменен" & auCRLF & auCRLF & _
                 "Найдено: " & gTorrentCount & auCRLF & auCRLF & found, "Autorun", 48)
       
       Else
          MsgBox("Поиск отменен" & auCRLF & auCRLF & _
                 "Найдено: " & gTorrentCount & auCRLF & auCRLF & found & auCRLF & auCRLF & _       
                 "Сохранить в текстовый файл?", "Autorun", 3+48+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(aFound[0])
          If EXTENDED = 6 Then SaveDataPathToText(sFile, found)
       EndIf
    Else 
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       If DllCall("DestroyWindow", "handle", h_WinFindTorr) Then h_WinFindTorr = 0
       If gTorrentCount = 0 Then
          Local mode = files > 1 ? 0 : 1
          Local sMode = (mode = 0 ? "«Имя и размер»" : "«Только имя»")
          MsgBox("Найдено: " & gTorrentCount & auCRLF & auCRLF & _
                 "Файлов в торренте: " & files & " " & auCRLF & auCRLF & _         
                 "Продолжить в режиме " & sMode & "?", "Autorun", 3+64+0)
             If EXTENDED = 6 Then Return FindTorrentParts(mode)               
       Else
          bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
          If gCapsReverse Then bCaps = Not bCaps
          If bCaps Then      
             SetHintParam("ShowHint", "Font", 15, "Arial")
             SetHintParam("ShowHint", "BackColor", 0xFF0000)
             SetHintParam("ShowHint", "Text", 0xFFFFFF)     
             ShowHint("Автопереход к найденному", 0, 0, 1000, 1)
             WinAlign(LAST_HINT_WINDOW)
             Sleep(100)         
             SetHintParam("ShowHint", "Reload")             
             GoToPathFromMsg(aFound[0])
             Return
          EndIf
          MsgBox("Найдено: " & gTorrentCount & auCRLF & auCRLF & found & auCRLF & auCRLF & _       
                 "Сохранить в текстовый файл?", "Autorun", 3+64+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(aFound[0])
          If EXTENDED = 6 Then SaveDataPathToText(sFile, found)
       EndIf
    EndIf
EndFunc

Func SaveDataPathToText(Filename, DataPath)
     Local file = FileChangeExt(Filename, "txt"), bGoto = false
     If FileExist(file) Then
        MsgBox("Файл существует" & auCRLF & auCRLF & _
                file & auCRLF & auCRLF & "Перезаписать?", "Autorun", 3+32+0)
        If EXTENDED <> 6 Then Return
     EndIf
     FileWrite(file, DataPath)
     #MsgBox("Файл сохранен " & auCRLF & auCRLF & file, "Autorun", 64)
     SetHintParam("ShowHint", "Font", 15, "Arial")
     SetHintParam("ShowHint", "BackColor", 0xFF0000)
     SetHintParam("ShowHint", "Text", 0xFFFFFF)     
     ShowHint("Файл сохранен", 0, 0, 1000, 1)
     WinAlign(LAST_HINT_WINDOW)
     Sleep(100)         
     SetHintParam("ShowHint", "Reload")
     If bGoto Then
        If RequestInfo(1000) = 1 Then
           CommandExec /CD %'file'
        Else
           CommandExec /CD '' %'file'
        Endif
     Endif   
EndFunc

Func GoToPathFromTextFile()
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       Return
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Файл является каталогом " & sFile)
       Return
    ElseIf FileGetExt(sFile) <> "TXT" Then
       ShowHint("Расширение файла не .txt " & sFile)
       Return
    ElseIf FileGetSize(sFile) > 1024*2 Then
       ShowHint("Размер файла больше 2 Кб " & sFile)
       Return       
    EndIf
    Local txt = FileRead(sFile)
    Local target = StrPart(txt, auCRLF, 1)
    If target <> "" Then
       GoToPathFromMsg(target)
    Else   
       ShowHint("Пустой путь" & target)  
    EndIf    
EndFunc

Func GoToPathFromMsg(Target)
    If FileExist(Target) Then
       If RequestInfo(1000) = 2 Then
          CommandExec /CD %'Target'
       Else
          CommandExec /CD '' %'Target'
       Endif
       SendCommand(4006)
       If StrPos(FileGetAttr(Target), "D") Then SendCommand(2002)
       Local ForceRedraw = 0
       If ForceRedraw Then
          WinRedraw(1)
          SendCommand(540)     # cm_RereadSource
       EndIf
    Else
       ShowHint("Путь не существует " & Target)
    EndIf    
EndFunc

Func FindTorrentFile(file)
    Static T1 = GetUptime()
    If Not g_FindTorrTask Then Return 0
    If Round(GetUptime() - T1, 0) > 200 Then 
       WinSetText(" [" & gTorrentCount & "] " & file.FullPath, h_WinFindTorr)
       T1 = GetUptime()
       Sleep(5)
    EndIf         
    If file.size = gTorrentSize Then 
       gTorrentCount += 1
       Return 1
    EndIf
    Return 2
EndFunc

Func FindTorrentDir(file)
    Static T2 = GetUptime()
    If Not g_FindTorrTask Then Return 0
    If Round(GetUptime() - T2, 0) > 200 Then 
       WinSetText(" [" & gTorrentCount & "] " & file.FullPath, h_WinFindTorr)
       T2 = GetUptime()
       Sleep(5)
    EndIf   
    Local sz = FileFind(file.FullPath, "*.*", 1, 0, "TotalSize")  
    If sz = gTorrentSize Then 
       gTorrentCount += 1
       Return 1
    EndIf    
    Return 2
EndFunc

Global gVbsInputBox

Func SetTorrentDrives()
    Local out, drives, vbs
    
    IniRead drives %COMMANDER_INI% "Autorun" "TorrentDrives" %"gDriveInclude"    
    vbs = '/c ECHO Wscript.Echo Inputbox("Search on these disks:","Autorun","' & drives & '")>%TEMP%\~auto_0001.vbs'
    
    ProcessExecGetOutput out %COMSPEC% %vbs%
    
    gVbsInputBox = 1
    RunThread("WinVbsInputBoxActivate")
    ProcessExecGetOutput /OEM out "cscript.exe" "/nologo ~auto_0001.vbs" %TEMP%
    gVbsInputBox = 0
    
    out = StrTrim(out)
    If out = "" Then Return
    
    IniWrite %COMMANDER_INI% "Autorun" "TorrentDrives" %out%
    Sleep(50)
    MsgBox("Ключ сохранен.", "Autorun", 64)           
EndFunc

Func WinVbsInputBoxActivate()
    Local hVbs
    While gVbsInputBox
        hVbs = WinFind(0, "#32770", "Autorun")
        If hVbs > 0 Then
           WinSetState(23, hVbs)
           Break
        EndIf
        Sleep(50)
    Wend
EndFunc

Func TorrentSize(lParam)
    Local T1 = GetUptime()
    Local obj = Plugin("TCTorrent")
    If ERROR <> 0 Then
       ShowHint("TCTorrent.wdx plugin error " & ERROR)
       Return
    Endif
    Local size = 0, files = 0
    Local aSel = List()
          aSel.Text = GetSelectedItems(3, 0)       
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    Local lRet = false
    If aSel.Count = 0 Then
       If Not FileExist(sFile) Then 
          ShowHint("Файл не существует " & sFile)
          lRet = true
       ElseIf StrPos(FileGetAttr(sFile), "D") Then
          ShowHint("Каталог " & sFile)
          lRet = true       
       Else
          obj.FileName = sFile
          files = obj.GetValue(1)
          size = obj.GetValue(2,0)	# size -> bytes
          Free(obj)
       Endif
    EndIf
    If lRet Then
       Free(obj, aSel)
       Return
    EndIf
    If aSel.Count > 10 Then
       ShowHint("Выделено: " & aSel.Count & auCRLF & "Подсчёт времени...")
    EndIf    
    Local j, k = 0, dirs = 0, torrs = 0
    If aSel.Count > 0 Then
       For j = 0 To aSel.Count - 1
          sFile = sPath & aSel[j]
          If FileExist(sFile) Then 
             k += 1
             If Not StrPos(FileGetAttr(sFile), "D") Then
               obj.FileName = sFile
               s = obj.GetValue(2,0)
               If s > 0 Then 
                  size += s
                  files += obj.GetValue(1)
                  torrs += 1 
               Endif  
             Else   
               dirs += 1
             Endif   
          EndIf
       Next
       sName = "S/A: " & aSel.Count & "/" & k	# Selected / Available
    Else
       SetHintParam("ShowHint", "Font", 10, "")
       ShowHint("" & sName & auCRLF & _
                "Размер: " & SizeFormat(size, 1, 'G', 2, 1) & auCRLF & _
                "Файлов: " & files)
       Sleep(100)
       SetHintParam("ShowHint", "Reload")
       Free(aSel)
       Return
    EndIf
    Local tl = Round(GetUptime() - T1, 0) / 1000
    SetHintParam("ShowHint", "Font", 10, "")
    ShowHint((k = aSel.Count ? "" : "Файл " & sName & auCRLF) & _
             "Элементов: " & aSel.Count & auCRLF & _
             "Обработано: " & torrs & auCRLF & _
             "Каталогов: " & dirs & auCRLF & _              
             "Размер: " & SizeFormat(size, 0, 'M', 2) & auCRLF & _
             "Размер: " & SizeFormat(size, 0, 'G', 2) & auCRLF & _
             "Размер: " & SizeFormat(size, 0, 'T', 4) & auCRLF & _
             "Файлов: " & files & auCRLF & _                       
             "Powered by TCTorrent.wdx" & auCRLF & _
             "Время операции: " &  StrFormat("%.3f", tl) & " sec")
    Sleep(100)
    SetHintParam("ShowHint", "Reload")          
    Free(obj, aSel)
EndFunc

Func ToggleEverything()    
    If Not ProcessExist("Everything.exe") Then
       CommandExec em_everything
    Else
       CommandExec em_everything_exit
    Endif    
EndFunc 

Func TerminateEverything()
    CommandExec em_everything_exit
EndFunc

Func TorrentBugTest(lParam)
    RunThread("TorrentThreadTest")
EndFunc

Func TorrentThreadTest()
    Local out, tor, vbs
    tor = "d:\Temp\Jinn'sLiveUSB 11.2.2.torrent"
    vbs = '/c ECHO Wscript.Echo Inputbox("Torrent file for testing:","Autorun","' & tor & '")>%TEMP%\~auto_0002.vbs'    
    ProcessExecGetOutput out %COMSPEC% %vbs%
    
    gVbsInputBox = 1
    RunThread("WinVbsInputBoxActivate")
    ProcessExecGetOutput /OEM out "cscript.exe" "/nologo ~auto_0002.vbs" %TEMP%
    gVbsInputBox = 0
    
    out = StrTrim(out)
    If out = "" Then Return
    If Not FileExist(out) Then 
       MsgBox("File doesn't exist " & out)
       Return
    EndIf
    
    Local hIco = 0   
    Local hWnd = DllCall("CreateWindowExW", _
                         "dword", 0, _
                         "wstr", "msctls_progress32", _
                         "wstr", "", _
                         "dword", 0x00C80000, _
                         "int", 200, "int", 100, "int", Scale(400), "int", Scale(50), _
                         "handle", AUTORUN_TCHANDLE, _
                         "handle", 0, "handle", 0, "ptr", 0, "handle")
    If hWnd = 0 Then Return 0
    
    WinAlign(hWnd, 0, DllCall("GetDesktopWindow"))
    WinSetPos("", -Scale(50), "", "", 1, hWnd)
    WinSetState(5, hWnd)
                                
    Static PBS_MARQUEE     =  0x08, _
           PBM_SETMARQUEE  =  1034, _
           WM_GETICON      =  0x7f, _
           WM_SETICON      =  0x80
           
    hIco = SendMessage(AUTORUN_TCHANDLE, WM_GETICON, 2, 0)                     
    SendMessage(hWnd, WM_SETICON, 0, hIco)
    
    WinSetStyle(PBS_MARQUEE, 2, hWnd)    
    SendMessage(hWnd, PBM_SETMARQUEE, 1, 0)
    For i = 1 To 500
        TorrentInfo(hWnd, i, out)
        If WinGetState(1, hWnd) = 0 Then
           MsgBox("Тестирование прервано", "Autorun", 48)
           Return
        EndIf
    Next    
    MsgBox("Тестирование успешно завершено", "Autorun", 64)
    DllCall("DestroyWindow", "handle", hWnd)
EndFunc

# original function by Loopback
Func TorrentInfo(hWnd, nPass, sFile)
    Static aFixed = List('Name', 'TotalSize', 'FileCount', 'BlockSize', 'BlockCount', _
                         'Created', 'Creator', 'Hash', 'Comment', 'Encoding', _
                         'Multifile', 'PrivateTorrent', 'Publisher', 'PublisherURL')
    Static aMulti = List('Tracker', 'Webseed', 'Error', 'CustomField')

    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName

    Local hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
    If hDll = 0 Then Return MsgBox("Can't load " & sLibPath)

    Local hHandle = DllCall(sLibName & "\TorrentOpen", "wstr", sFile, "handle")
    If hHandle = 0 Then
        DllCall("FreeLibrary", "handle", hDll)
        Return MsgBox("Can't open " & sFile)
    EndIf

    Local nCount, sRes

    For i = 0 to aFixed.Count - 1
        sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", aFixed[i], "int", 0, "wstr")
        OutputDebugString(aFixed[i] & ": " & sRes)
        WinSetText(nPass & ": " & sRes, hWnd)
    Next

    OutputDebugString(auCRLF & 'Files:')
    nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", "File", "uint")
    For j = 0 To nCount - 1
        sRes = StrFormat("[%12s] %s", _
                 DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileSize", "int", j, "wstr"), _
                 DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "File", "int", j, "wstr"))
        OutputDebugString(sRes)
        WinSetText(nPass & ": " & sRes, hWnd)
    Next

    For i = 0 to aMulti.Count - 1
        OutputDebugString(auCRLF & aMulti[i] & 's:')
        nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", aMulti[i], "uint")
        For j = 0 To nCount - 1
            sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", aMulti[i], "int", j, "wstr")
            OutputDebugString(sRes)
            WinSetText(nPass & ": " & sRes, hWnd)
        Next
    Next

    DllCall(sLibName & "\TorrentClose", "handle", hHandle)
    DllCall("FreeLibrary", "handle", hDll)
EndFunc 

#Func FindTorrentParts(lParam)
#    RunThread "ThreadTorrentParts" lParam
#EndFunc

Func FindTorrentParts(lParam)
    # модификаторы вызова
    Local b_CTRL = IsPressed (0x11), b_Shift = IsPressed (0x10)
    If lParam = 1 Then b_CTRL = true
    If lParam = 2 Then b_Shift = true    
    
    # повторный вызов при запущенной задаче
    If h_WinFindTorr Then
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       g_FindTorrTask = 0  
       Return
    Endif
    
    If gEvAuto And Not ProcessExist("Everything.exe") Then 
       ShellExec(gEvPath, "-startup")
       Sleep(gEvDelay)       
    Endif
    
    # имя файла под курсором
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    
    # файл не существует или является каталогом
    If Not FileExist(sFile) Then 
       ShowHint("File doesn't exist " & sFile)
       Return
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Not a torrent file " & sFile)
       Return
    ElseIf FileGetSize(sFile) > 1024*1024*5 Then
       ShowHint("File size > 5 Mb " & sFile)
       Return
    EndIf    
    
    # путь к библиотеке плагина
    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName

    # не удалось загрузить библиотеку
    Local hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
    If hDll = 0 Then 
       ShowHint("TCTorrent.wlx can't load library " & sLibPath)
       Return
    EndIf    

    # библиотеке не удалось открыть файл
    Local hHandle = DllCall(sLibName & "\TorrentOpen", "wstr", sFile, "handle")
    If hHandle = 0 Then
        ShowHint("TCTorrent.wlx can't open file " & sFile)    
        DllCall("FreeLibrary", "handle", hDll)
        Return
    EndIf
    
    # файл не является торрент-файлом
    Local nFiles
    nFiles = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileCount", "int", 0, "wstr")
    If nFiles < 1 Then
       ShowHint("Corrupt torrent file " & sFile)
       DllCall(sLibName & "\TorrentClose", "handle", hHandle)       
       DllCall("FreeLibrary", "handle", hDll)       
       Return             
    EndIf  
    
    # окно прогресса операции
    h_WinFindTorr = 0
    If g_WinThread Then 
       RunThread "WinFindTorrentData"
       While g_FindTorrTask = 0
           Sleep(50)
       Wend
    Else
        WinFindTorrentData(0)
    EndIf
    
    TorrentGetFixed(sLibName, hHandle, sFile)
    
    # локальные переменные
    Local T1 = GetUptime(), T2 = T1, T3, bSpeed = 0, nRes = 0
    Local bName = Not b_Shift, bSize = Not b_CTRL, sSize, sMode, sMem, sDbg
    Local j, nCount, sRes, nError, sList, sDirs, aQuery = List(), aCount = List()
    
    Static aMode = List("«Имя и размер»", "«Только имя»", "«Только размер»")
    If bName And bSize Then
       nMode = 0
    ElseIf bName Then
       nMode = 1    
    Else
       nMode = 2
    EndIf
    sMode = aMode[nMode]
    
    # количество файлов в торренте
    nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", "File", "uint")

    # перечисление файлов в торренте
    For j = 0 To nCount - 1
        
        If gTorrentDbg Then gDbgStep = "Step 1. TorrentGet j=" & j & auCRLF
        
        # имя файла
        sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "File", "int", j, "wstr")
        
        # размер файла
        If bSize Then
           sSize = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileSize", "int", j, "wstr")
        EndIf
        
        sDbg = Round((j+1)/nCount*100,0) & '% - '
        If gTorrentDbg Then
           nRes += StrLen(sRes) + 8
           sMem = StrLen(sList) + StrLen(sDirs) + nRes
           sDbg &= SizeFormat(sMem*2, 1, 'G', 2) &  ' - '        
        EndIf

        If gTorrentDbg Then gDbgStep &= "Step 2. WinSetText " & sRes & auCRLF
        
        # меньше сообщений окну прогресса
        If bSpeed Then
           T3 = GetUptime()
           If Round(T3 - T2, 0) > 250 Then 
              WinSetText(sDbg & sRes, h_WinFindTorr)
              T2 = T3
           EndIf
        Else
           WinSetText(sDbg & sRes, h_WinFindTorr)
        EndIf

        If gTorrentDbg Then gDbgStep &= "Step 3. FileFindEv " & sRes & auCRLF
        
        # запрос к Everything
        If bName And bSize Then
           aQuery.Text = FileFindEv('*"' & sRes & '" size:' & sSize, "", "")
        ElseIf bName Then
           aQuery.Text = FileFindEv('*"' & sRes & '"', "", "")        
        Else
           aQuery.Text = FileFindEv('size:' & sSize, "", "")
        EndIf
                
        # ошибка запроса
        nError = ERROR
        If nError > 0 Then Break

        If gTorrentDbg Then gDbgStep &= "Step 4. aCount.Add" & auCRLF
        
        # обработка запроса
        aCount.Add("[" & aQuery.Count & "] " & sRes)        
        If aQuery.Count > 0 Then 
           If gTorrentDbg Then gDbgStep &= "Step 5. sList" & auCRLF
           sList &= aQuery.Text & auCRLF
           If gTorrentDbg Then gDbgStep &= "Step 6. sDirs" & auCRLF
           If nFiles > 1 Then 
              If gTorrentDbg Then gDbgStep &= "Step 7. StrReplace" & auCRLF
              sDirs &= StrReplace(aQuery.Text, sRes, "") & auCRLF
           Else
              sDirs &= aQuery.Text & auCRLF
           EndIf
        Else
           If gTorrentDbg Then 
              gDbgStep &= "Step 5. Skip" & auCRLF
              gDbgStep &= "Step 6. Skip" & auCRLF
              gDbgStep &= "Step 7. Skip" & auCRLF              
           EndIf             
        EndIf  

        If gTorrentDbg Then gDbgStep &= "Step 8. Next"
        #Sleep(3000)
        
        # опрерация прервана закрытием окна прогресса
        If g_FindTorrTask = 0 Then Break
    Next
    
    If gTorrentDbg Then gDbgStep &= "Step 9. Out"
       
    If nError = 1 Then MsgBox("Everything window not found.")
    If nError = 2 Then MsgBox("IPC Everything query execution error.")  
    If nError > 0 Then 
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)       
       Free(aCount, aQuery)
       DllCall(sLibName & "\TorrentClose", "handle", hHandle)
       DllCall("FreeLibrary", "handle", hDll)           
       Return
    EndIf

    Local c = 0, m = Map(), top5 = List(), sTop5, bDirs = StrLen(StrTrim(sDirs))
    
    # суммирование путей при непустом результате
    If g_FindTorrTask And bDirs Then 
       aQuery.Text = sDirs
       For value In aQuery
           c = 1
           If m.Has(value) Then c += m.Get(value)
           m.Set(value, c)
       Next
    EndIf
    
    # сортировка путей по убыванию
    If g_FindTorrTask And bDirs Then
       top5.SortMethod = 1 
       For key, value In m          
           top5.Add("[" & value & "]" & Chr(160) & key)
       Next
       top5.Sort(1)
       
       # выбор верхних пяти путей
       For j = 0 To top5.Count - 1
          sTop5 &= top5[j] & auCRLF
          If j >= 4 Then Break
       Next   
    EndIf
    
    c = top5.Count
    Local top1, files = aCount.Text
    If c > 0 Then top1 = StrTrim(StrPart(top5[0], Chr(160), 2))

    # освобождение объектов и библиотеки    
    Free(aCount, aQuery, top5, m)    
    DllCall(sLibName & "\TorrentClose", "handle", hHandle)
    DllCall("FreeLibrary", "handle", hDll)
    
    # время операции    
    T2 = Round(GetUptime() - T1, 0) / 1000
    T3 = "Время поиска: " &  StrFormat("%.3f", T2) & " sec"
    
    If gEvAuto Then ShellExec(gEvPath, "-exit")    
    
    If g_FindTorrTask = 0 Then
       MsgBox("Поиск отменен", "Autorun", 48)
    Else        
       # закрытие окна прогресса
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       If DllCall("DestroyWindow", "handle", h_WinFindTorr) Then h_WinFindTorr = 0
       
       # ничего не найдено
       If c = 0 Then
          If nMode < 2 Then
             MsgBox("Найдено: " & c & auCRLF & auCRLF & _
                    "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                    "Режим: " & sMode & auCRLF & auCRLF & _                
                    "Продолжить в режиме " & aMode[nMode+1] & "?", "Autorun", 3+64+0)
             If EXTENDED = 6 Then Return FindTorrentParts(nMode+1)                
          Else
             MsgBox("Найдено: " & c & auCRLF & auCRLF & _
                    "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                    "Режим: " & sMode, "Autorun", 64)
          EndIf           
       Else          
          # проверка CapsLock
          Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
          If gCapsReverse Then bCaps = Not bCaps
          If bCaps Then
             ShowRedHint("Автопереход к найденному")
             GoToPathFromMsg(top1)
             Return
          EndIf          
          MsgBox("Найдено: " & c & auCRLF & auCRLF & sTop5 & auCRLF & _
                 "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                 "Режим: " & sMode & auCRLF & auCRLF & _                
                 "Сохранить в текстовый файл?", "Autorun", 3+64+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(top1)
          If EXTENDED = 6 Then
             Local txt
             txt &= top1 & auCRLF & auCRLF
             txt &= "-----------------" & auCRLF             
             txt &= "Top 5 locations:" & auCRLF 
             txt &= "-----------------" & auCRLF             
             txt &= sTop5 & auCRLF
             txt &= "-----------------" & auCRLF             
             txt &= "Torrent files:" & auCRLF     
             txt &= "-----------------" & auCRLF             
             txt &= files & auCRLF & auCRLF
             txt &= "-----------------" & auCRLF                          
             txt &= "Full list:" & auCRLF
             txt &= "-----------------" & auCRLF                
             txt &= sList             
             SaveDataPathToText(sFile, txt)
          EndIf   
       EndIf
    EndIf
EndFunc

Func TorrentFindOptions()
     gTorrentDbg = Not gTorrentDbg
     ShowRedHint("Торрент Debug " & (gTorrentDbg ? "включен" : "выключен"))
EndFunc

Func TorrentDebugInfo()
    If Not gTorrentDbg Then gDbgStep = "Торрент Debug выключен"
    If gDbgStep = "" Then gDbgStep = "Empty"
    SetHintParam("ShowHint", "Font", 13, "Arial")
    SetHintParam("ShowHint", "BackColor", 0x000000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(gDbgStep)
    WinAlign(LAST_HINT_WINDOW)    
    ClipPut(gDbgStep)  
    SetHintParam("ShowHint", "Reload") 
EndFunc

Func TorrentGetFixed(TorrLib, TorrHandle, TorrFile)
    Local sRes, sComm, i = 0, bLib = false, hDll
    
    Static aFixed = List('Name', 'TotalSize', 'FileCount', 'BlockSize', 'BlockCount', _
                         'Created', 'Creator', 'Hash', 'Comment', 'Encoding', _
                         'Multifile', 'PrivateTorrent', 'Publisher', 'PublisherURL')
                         
    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName
                         
    If TorrLib = 0 Then 
       TorrLib = sLibName 
       hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
       If hDll = 0 Then 
          gTorrentLog = "Can't load " & sLibPath
          Return 
       EndIf
       TorrHandle = DllCall(sLibName & "\TorrentOpen", "wstr", TorrFile, "handle")
       If TorrHandle = 0 Then
           DllCall("FreeLibrary", "handle", hDll)
           gTorrentLog = "Can't open " & TorrFile
           Return
       EndIf
       bLib = true
    EndIf   
                             
    gTorrentUrl = DllCall(TorrLib & "\TorrentGet", _
                   "handle", TorrHandle, "wstr", "PublisherURL", "int", 0, "wstr")
    gTorrentLog = "File: "   & TorrFile & auCRLF
    
    For i = 0 to aFixed.Count - 1
        sRes = DllCall(TorrLib & "\TorrentGet", _
               "handle", TorrHandle, "wstr", aFixed[i], "int", 0, "wstr")
        If i = 8 Then sComm = sRes
        gTorrentLog &= aFixed[i] & ": " & sRes & auCRLF
    Next
    
    gTorrentLog = StrTrim(gTorrentLog)
    If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = sComm
    If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = "[No valid URL] " & FileGetName(TorrFile)
    
    If bLib Then
       DllCall(sLibName & "\TorrentClose", "handle", TorrHandle)
       DllCall("FreeLibrary", "handle", hDll)
    EndIf   
EndFunc

Func TorrentFixedInfo()
    If gTorrentLog = "" Then gTorrentLog = "No torrent information"
    SetHintParam("ShowHint", "Font", 13, "Arial")
    SetHintParam("ShowHint", "BackColor", 0x000000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(gTorrentLog)
    WinAlign(LAST_HINT_WINDOW)
    ClipPut(gTorrentUrl)  
    SetHintParam("ShowHint", "Reload") 
EndFunc
[/cut]
Сейчас если ссылки нет в поле "PublisherURL", она ищется в поле "Comment". Если и в поле "Comment" ничего нет, то в буфер копируется текст "[No valid URL]" с именем файла. Информация в буфер попадает только после нажатия Alt+Win+T. Эта комбинация показывает подсказку о последнем запущенном torrent файле и копирует ссылку в буфер. Посмотрите, как вам такой вариант.

Loopback
Мысль посетила. Раз уж объект List корректно загружает файл в любой кодировке, то может ему и поле добавить "CodePage", где будут сведения о такой кодировке?
A55555
Сообщения: 72
Зарегистрирован: Вс фев 06, 2011 10:50

Сообщение A55555 »

Orion9 писал(а): Многое будет зависить от того, есть ли такая ссылка в файле, но попробовать можно. Модуль с изменениями:
[cut="Torrent.aucfg"]

Код: Выделить всё

Pragma IncludeOnce

# 70500-70599

RegisterCommand 70500 "TorrentFindData" 0
RegisterCommand 70501 "TorrentFindData" 1
RegisterCommand 70502 "GoToPathFromTextFile"
RegisterCommand 70503 "ToggleEverything"
RegisterCommand 70504 "FindTorrentParts"
RegisterCommand 70505 "TorrentSize"
RegisterCommand 70506 "TorrentFindOptions"
RegisterCommand 70507 "TorrentDebugInfo"

RegisterCommand 70508 "TorrentBugTest"

SetHotkeyAction /K:A /H:0 /DM /S TorrentDebugInfo
SetHotkeyAction /K:A /K:W /H:0 /DM /S TorrentFindOptions
SetHotkeyAction /K:A /K:W /H:T /DM /S TorrentFixedInfo

Global gEvPath = COMMANDER_PATH & "\Everything.exe", gEvAuto = 0, gEvDelay = 100

Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0, gTorrentUrl, gTorrentLog
Global gTorrentSize = 0, gTorrentCount = 0, gDriveInclude = "e:\;f:\;g:\;h:\;i:\;j:"

Global h_WinFindTorr = 0, g_WinThread = 0
Global g_WinFindTorr = 0, g_FindTorrTask = 0
Global o_WinFindTorr = Callback("WinFindTorrProc", "hwnd;uint;wparam;lparam")

Func WinFindTorrProc(hWnd, uMsg, wParam, lParam)
    Static WM_CLOSE = 0x0010
    If uMsg = WM_CLOSE Then
       If DllCall("DestroyWindow", "handle", hWnd) Then
          h_WinFindTorr = 0        
          g_FindTorrTask = 0
       EndIf   
       Return 0
    EndIf
    Return DllCall("CallWindowProcW", "ptr", g_WinFindTorr, _
                                      "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func WinFindTorrentData(bWhile = 1)
    Local hIco    
    h_WinFindTorr = DllCall("CreateWindowExW", _
                            "dword", 0, _
                            "wstr", "msctls_progress32", _
                            "wstr", "", _
                            "dword", 0x00C80000, _
                            "int", 200, "int", 100, "int", Scale(400), "int", Scale(50), _
                            "handle", AUTORUN_TCHANDLE, _
                            "handle", 0, "handle", 0, "ptr", 0, "handle")
    If h_WinFindTorr = 0 Then Return 0
    
    WinAlign(h_WinFindTorr, 0, DllCall("GetDesktopWindow"))
    WinSetPos("", -Scale(50), "", "", 1, h_WinFindTorr)
    WinSetState(5, h_WinFindTorr)
    
    g_WinFindTorr = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                            "hwnd", h_WinFindTorr, _
                            "int", -4, _
                            "long_ptr", o_WinFindTorr.Ptr, "ptr")
                            
    Static PBS_MARQUEE     =  0x08, _
           PBM_SETMARQUEE  =  1034, _
           WM_GETICON      =  0x7f, _
           WM_SETICON      =  0x80
           
    hIco = SendMessage(AUTORUN_TCHANDLE, WM_GETICON, 2, 0)                     
    SendMessage(h_WinFindTorr, WM_SETICON, 0, hIco)
    
    WinSetStyle(PBS_MARQUEE, 2, h_WinFindTorr)    
    SendMessage(h_WinFindTorr, PBM_SETMARQUEE, 1, 0)
    
    WinSetText("Searching...", h_WinFindTorr)
    
    g_FindTorrTask = 1
    If bWhile Then
       While g_FindTorrTask
           Sleep(50)
       Wend
       h_WinFindTorr = 0
    EndIf   
EndFunc

Func TorrentFindData(lParam, nMode)
    If IsPressed(0x10) And Not nMode Then
       SetTorrentDrives()
       Return
    EndIf
    Local bEverything = nMode
    If h_WinFindTorr Then
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       g_FindTorrTask = 0  
       Return
    Endif
    Static buf = Buffer(256)
    buf.Zero()
    Local nSymb = DllCall("GetLogicalDriveStringsW", "dword", buf.size, "ptr", buf.ptr)    
    If Not nSymb Then
       MsgBox("Не удалось получить список логических дисков" & auCRLF "SYSERROR: " & SYSERROR, "Autorun")
       Return
    EndIf
    Static aDrive = List(), aFound = List()
    Local i = 0, sz, sDrives
    aDrive.Count = 0
    While 1
       sDrive = buf.GetStr(i)
       sz = StrLen(sDrive)
       If sz = 0 Then break
       aDrive.add(sDrive)
       i = i + sz*2 + 2
    Wend
    sDrives = aDrive.text
    #MsgBox(sDrives)    
    Local obj = Plugin("TCTorrent")
    If ERROR <> 0 Then
       ShowHint("TCTorrent.wdx plugin error " & ERROR)
       Return
    Endif
    Local lRet = false 
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       lRet = true
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Каталог " & sFile)
       lRet = true
    ElseIf FileGetSize(sFile) > 1024*1024*5 Then
       ShowHint("Размер файла больше 5 Мб " & sFile)
       lRet = true
    Else
       obj.FileName = sFile
       Local name =  obj.GetValue(0)
       Local size = obj.GetValue(2,0)	# size -> bytes       
       Local files = obj.GetValue(1)
       If files < 1 Then
          ShowHint("Файл не является торрент-файлом " & sFile)
          lRet = true        
       EndIf
    Endif
    Free(obj)
    If lRet Then Return
    IniRead gDriveInclude %COMMANDER_INI% "Autorun" "TorrentDrives" %"gDriveInclude"
    Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
    If gCapsReverse Then bCaps = Not bCaps
    If Not bCaps Then
       MsgBox("Поиск данных торрента:" & auCRLF & auCRLF & _
              "Имя: "    & name & auCRLF & _
              "Размер: " & size & auCRLF & _
              "Файлов: " & files & auCRLF & auCRLF & _ 
              "Диски поиска: " & gDriveInclude & auCRLF & auCRLF & _       
              "Продолжить?", "Autorun", 3+32+0)
       If EXTENDED <> 6 Then Return
    Endif
    If bEverything Then 
       If gEvAuto And Not ProcessExist("Everything.exe") Then 
          ShellExec(gEvPath, "-startup")
          Sleep(gEvDelay)
       EndIf   
    EndIf      
    aFound.Count = 0    
    gTorrentSize = size
    h_WinFindTorr = 0
    gTorrentCount = 0
    RunThread "WinFindTorrentData"
    While g_FindTorrTask = 0
        Sleep(50)
    Wend
    TorrentGetFixed(0, 0, sFile)
    Local found
    If bEverything Then      
       found = FileFindEv("size:" & gTorrentSize, "", "sort:3")
       Local nError = ERROR
       If nError = 1 Then MsgBox("Не найдено окно Everything.")
       If nError = 2 Then MsgBox("Ошибка выполнения запроса к IPC Everything.")  
       If nError > 0 Then 
          g_FindTorrTask = 0
          Return
        EndIf  
    Else   
       For i = 0 to aDrive.Count -1
           If StrPos(gDriveInclude, aDrive[i]) Then
            If files > 1 Then
               found &= FileFind(aDrive[i], "*.*", 1, 2, "PathList", "Func:FindTorrentDir") & auCRLF
            Else
               found &= FileFind(aDrive[i], "*.*", 1, 1, "PathList", "Func:FindTorrentFile") & auCRLF
            EndIf   
           Endif   
       Next
    EndIf   
    found = StrTrim(found)
    aFound.Text = found
    If bEverything Then gTorrentCount = aFound.Count
    If bEverything And gEvAuto Then ShellExec(gEvPath, "-exit")     
    If g_FindTorrTask = 0 Then
       If gTorrentCount = 0 Then
          MsgBox("Поиск отменен" & auCRLF & auCRLF & _
                 "Найдено: " & gTorrentCount & auCRLF & auCRLF & found, "Autorun", 48)
       
       Else
          MsgBox("Поиск отменен" & auCRLF & auCRLF & _
                 "Найдено: " & gTorrentCount & auCRLF & auCRLF & found & auCRLF & auCRLF & _       
                 "Сохранить в текстовый файл?", "Autorun", 3+48+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(aFound[0])
          If EXTENDED = 6 Then SaveDataPathToText(sFile, found)
       EndIf
    Else 
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       If DllCall("DestroyWindow", "handle", h_WinFindTorr) Then h_WinFindTorr = 0
       If gTorrentCount = 0 Then
          Local mode = files > 1 ? 0 : 1
          Local sMode = (mode = 0 ? "«Имя и размер»" : "«Только имя»")
          MsgBox("Найдено: " & gTorrentCount & auCRLF & auCRLF & _
                 "Файлов в торренте: " & files & " " & auCRLF & auCRLF & _         
                 "Продолжить в режиме " & sMode & "?", "Autorun", 3+64+0)
             If EXTENDED = 6 Then Return FindTorrentParts(mode)               
       Else
          bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
          If gCapsReverse Then bCaps = Not bCaps
          If bCaps Then      
             SetHintParam("ShowHint", "Font", 15, "Arial")
             SetHintParam("ShowHint", "BackColor", 0xFF0000)
             SetHintParam("ShowHint", "Text", 0xFFFFFF)     
             ShowHint("Автопереход к найденному", 0, 0, 1000, 1)
             WinAlign(LAST_HINT_WINDOW)
             Sleep(100)         
             SetHintParam("ShowHint", "Reload")             
             GoToPathFromMsg(aFound[0])
             Return
          EndIf
          MsgBox("Найдено: " & gTorrentCount & auCRLF & auCRLF & found & auCRLF & auCRLF & _       
                 "Сохранить в текстовый файл?", "Autorun", 3+64+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(aFound[0])
          If EXTENDED = 6 Then SaveDataPathToText(sFile, found)
       EndIf
    EndIf
EndFunc

Func SaveDataPathToText(Filename, DataPath)
     Local file = FileChangeExt(Filename, "txt"), bGoto = false
     If FileExist(file) Then
        MsgBox("Файл существует" & auCRLF & auCRLF & _
                file & auCRLF & auCRLF & "Перезаписать?", "Autorun", 3+32+0)
        If EXTENDED <> 6 Then Return
     EndIf
     FileWrite(file, DataPath)
     #MsgBox("Файл сохранен " & auCRLF & auCRLF & file, "Autorun", 64)
     SetHintParam("ShowHint", "Font", 15, "Arial")
     SetHintParam("ShowHint", "BackColor", 0xFF0000)
     SetHintParam("ShowHint", "Text", 0xFFFFFF)     
     ShowHint("Файл сохранен", 0, 0, 1000, 1)
     WinAlign(LAST_HINT_WINDOW)
     Sleep(100)         
     SetHintParam("ShowHint", "Reload")
     If bGoto Then
        If RequestInfo(1000) = 1 Then
           CommandExec /CD %'file'
        Else
           CommandExec /CD '' %'file'
        Endif
     Endif   
EndFunc

Func GoToPathFromTextFile()
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       Return
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Файл является каталогом " & sFile)
       Return
    ElseIf FileGetExt(sFile) <> "TXT" Then
       ShowHint("Расширение файла не .txt " & sFile)
       Return
    ElseIf FileGetSize(sFile) > 1024*2 Then
       ShowHint("Размер файла больше 2 Кб " & sFile)
       Return       
    EndIf
    Local txt = FileRead(sFile)
    Local target = StrPart(txt, auCRLF, 1)
    If target <> "" Then
       GoToPathFromMsg(target)
    Else   
       ShowHint("Пустой путь" & target)  
    EndIf    
EndFunc

Func GoToPathFromMsg(Target)
    If FileExist(Target) Then
       If RequestInfo(1000) = 2 Then
          CommandExec /CD %'Target'
       Else
          CommandExec /CD '' %'Target'
       Endif
       SendCommand(4006)
       If StrPos(FileGetAttr(Target), "D") Then SendCommand(2002)
       Local ForceRedraw = 0
       If ForceRedraw Then
          WinRedraw(1)
          SendCommand(540)     # cm_RereadSource
       EndIf
    Else
       ShowHint("Путь не существует " & Target)
    EndIf    
EndFunc

Func FindTorrentFile(file)
    Static T1 = GetUptime()
    If Not g_FindTorrTask Then Return 0
    If Round(GetUptime() - T1, 0) > 200 Then 
       WinSetText(" [" & gTorrentCount & "] " & file.FullPath, h_WinFindTorr)
       T1 = GetUptime()
       Sleep(5)
    EndIf         
    If file.size = gTorrentSize Then 
       gTorrentCount += 1
       Return 1
    EndIf
    Return 2
EndFunc

Func FindTorrentDir(file)
    Static T2 = GetUptime()
    If Not g_FindTorrTask Then Return 0
    If Round(GetUptime() - T2, 0) > 200 Then 
       WinSetText(" [" & gTorrentCount & "] " & file.FullPath, h_WinFindTorr)
       T2 = GetUptime()
       Sleep(5)
    EndIf   
    Local sz = FileFind(file.FullPath, "*.*", 1, 0, "TotalSize")  
    If sz = gTorrentSize Then 
       gTorrentCount += 1
       Return 1
    EndIf    
    Return 2
EndFunc

Global gVbsInputBox

Func SetTorrentDrives()
    Local out, drives, vbs
    
    IniRead drives %COMMANDER_INI% "Autorun" "TorrentDrives" %"gDriveInclude"    
    vbs = '/c ECHO Wscript.Echo Inputbox("Search on these disks:","Autorun","' & drives & '")>%TEMP%\~auto_0001.vbs'
    
    ProcessExecGetOutput out %COMSPEC% %vbs%
    
    gVbsInputBox = 1
    RunThread("WinVbsInputBoxActivate")
    ProcessExecGetOutput /OEM out "cscript.exe" "/nologo ~auto_0001.vbs" %TEMP%
    gVbsInputBox = 0
    
    out = StrTrim(out)
    If out = "" Then Return
    
    IniWrite %COMMANDER_INI% "Autorun" "TorrentDrives" %out%
    Sleep(50)
    MsgBox("Ключ сохранен.", "Autorun", 64)           
EndFunc

Func WinVbsInputBoxActivate()
    Local hVbs
    While gVbsInputBox
        hVbs = WinFind(0, "#32770", "Autorun")
        If hVbs > 0 Then
           WinSetState(23, hVbs)
           Break
        EndIf
        Sleep(50)
    Wend
EndFunc

Func TorrentSize(lParam)
    Local T1 = GetUptime()
    Local obj = Plugin("TCTorrent")
    If ERROR <> 0 Then
       ShowHint("TCTorrent.wdx plugin error " & ERROR)
       Return
    Endif
    Local size = 0, files = 0
    Local aSel = List()
          aSel.Text = GetSelectedItems(3, 0)       
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    Local lRet = false
    If aSel.Count = 0 Then
       If Not FileExist(sFile) Then 
          ShowHint("Файл не существует " & sFile)
          lRet = true
       ElseIf StrPos(FileGetAttr(sFile), "D") Then
          ShowHint("Каталог " & sFile)
          lRet = true       
       Else
          obj.FileName = sFile
          files = obj.GetValue(1)
          size = obj.GetValue(2,0)	# size -> bytes
          Free(obj)
       Endif
    EndIf
    If lRet Then
       Free(obj, aSel)
       Return
    EndIf
    If aSel.Count > 10 Then
       ShowHint("Выделено: " & aSel.Count & auCRLF & "Подсчёт времени...")
    EndIf    
    Local j, k = 0, dirs = 0, torrs = 0
    If aSel.Count > 0 Then
       For j = 0 To aSel.Count - 1
          sFile = sPath & aSel[j]
          If FileExist(sFile) Then 
             k += 1
             If Not StrPos(FileGetAttr(sFile), "D") Then
               obj.FileName = sFile
               s = obj.GetValue(2,0)
               If s > 0 Then 
                  size += s
                  files += obj.GetValue(1)
                  torrs += 1 
               Endif  
             Else   
               dirs += 1
             Endif   
          EndIf
       Next
       sName = "S/A: " & aSel.Count & "/" & k	# Selected / Available
    Else
       SetHintParam("ShowHint", "Font", 10, "")
       ShowHint("" & sName & auCRLF & _
                "Размер: " & SizeFormat(size, 1, 'G', 2, 1) & auCRLF & _
                "Файлов: " & files)
       Sleep(100)
       SetHintParam("ShowHint", "Reload")
       Free(aSel)
       Return
    EndIf
    Local tl = Round(GetUptime() - T1, 0) / 1000
    SetHintParam("ShowHint", "Font", 10, "")
    ShowHint((k = aSel.Count ? "" : "Файл " & sName & auCRLF) & _
             "Элементов: " & aSel.Count & auCRLF & _
             "Обработано: " & torrs & auCRLF & _
             "Каталогов: " & dirs & auCRLF & _              
             "Размер: " & SizeFormat(size, 0, 'M', 2) & auCRLF & _
             "Размер: " & SizeFormat(size, 0, 'G', 2) & auCRLF & _
             "Размер: " & SizeFormat(size, 0, 'T', 4) & auCRLF & _
             "Файлов: " & files & auCRLF & _                       
             "Powered by TCTorrent.wdx" & auCRLF & _
             "Время операции: " &  StrFormat("%.3f", tl) & " sec")
    Sleep(100)
    SetHintParam("ShowHint", "Reload")          
    Free(obj, aSel)
EndFunc

Func ToggleEverything()    
    If Not ProcessExist("Everything.exe") Then
       CommandExec em_everything
    Else
       CommandExec em_everything_exit
    Endif    
EndFunc 

Func TerminateEverything()
    CommandExec em_everything_exit
EndFunc

Func TorrentBugTest(lParam)
    RunThread("TorrentThreadTest")
EndFunc

Func TorrentThreadTest()
    Local out, tor, vbs
    tor = "d:\Temp\Jinn'sLiveUSB 11.2.2.torrent"
    vbs = '/c ECHO Wscript.Echo Inputbox("Torrent file for testing:","Autorun","' & tor & '")>%TEMP%\~auto_0002.vbs'    
    ProcessExecGetOutput out %COMSPEC% %vbs%
    
    gVbsInputBox = 1
    RunThread("WinVbsInputBoxActivate")
    ProcessExecGetOutput /OEM out "cscript.exe" "/nologo ~auto_0002.vbs" %TEMP%
    gVbsInputBox = 0
    
    out = StrTrim(out)
    If out = "" Then Return
    If Not FileExist(out) Then 
       MsgBox("File doesn't exist " & out)
       Return
    EndIf
    
    Local hIco = 0   
    Local hWnd = DllCall("CreateWindowExW", _
                         "dword", 0, _
                         "wstr", "msctls_progress32", _
                         "wstr", "", _
                         "dword", 0x00C80000, _
                         "int", 200, "int", 100, "int", Scale(400), "int", Scale(50), _
                         "handle", AUTORUN_TCHANDLE, _
                         "handle", 0, "handle", 0, "ptr", 0, "handle")
    If hWnd = 0 Then Return 0
    
    WinAlign(hWnd, 0, DllCall("GetDesktopWindow"))
    WinSetPos("", -Scale(50), "", "", 1, hWnd)
    WinSetState(5, hWnd)
                                
    Static PBS_MARQUEE     =  0x08, _
           PBM_SETMARQUEE  =  1034, _
           WM_GETICON      =  0x7f, _
           WM_SETICON      =  0x80
           
    hIco = SendMessage(AUTORUN_TCHANDLE, WM_GETICON, 2, 0)                     
    SendMessage(hWnd, WM_SETICON, 0, hIco)
    
    WinSetStyle(PBS_MARQUEE, 2, hWnd)    
    SendMessage(hWnd, PBM_SETMARQUEE, 1, 0)
    For i = 1 To 500
        TorrentInfo(hWnd, i, out)
        If WinGetState(1, hWnd) = 0 Then
           MsgBox("Тестирование прервано", "Autorun", 48)
           Return
        EndIf
    Next    
    MsgBox("Тестирование успешно завершено", "Autorun", 64)
    DllCall("DestroyWindow", "handle", hWnd)
EndFunc

# original function by Loopback
Func TorrentInfo(hWnd, nPass, sFile)
    Static aFixed = List('Name', 'TotalSize', 'FileCount', 'BlockSize', 'BlockCount', _
                         'Created', 'Creator', 'Hash', 'Comment', 'Encoding', _
                         'Multifile', 'PrivateTorrent', 'Publisher', 'PublisherURL')
    Static aMulti = List('Tracker', 'Webseed', 'Error', 'CustomField')

    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName

    Local hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
    If hDll = 0 Then Return MsgBox("Can't load " & sLibPath)

    Local hHandle = DllCall(sLibName & "\TorrentOpen", "wstr", sFile, "handle")
    If hHandle = 0 Then
        DllCall("FreeLibrary", "handle", hDll)
        Return MsgBox("Can't open " & sFile)
    EndIf

    Local nCount, sRes

    For i = 0 to aFixed.Count - 1
        sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", aFixed[i], "int", 0, "wstr")
        OutputDebugString(aFixed[i] & ": " & sRes)
        WinSetText(nPass & ": " & sRes, hWnd)
    Next

    OutputDebugString(auCRLF & 'Files:')
    nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", "File", "uint")
    For j = 0 To nCount - 1
        sRes = StrFormat("[%12s] %s", _
                 DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileSize", "int", j, "wstr"), _
                 DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "File", "int", j, "wstr"))
        OutputDebugString(sRes)
        WinSetText(nPass & ": " & sRes, hWnd)
    Next

    For i = 0 to aMulti.Count - 1
        OutputDebugString(auCRLF & aMulti[i] & 's:')
        nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", aMulti[i], "uint")
        For j = 0 To nCount - 1
            sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", aMulti[i], "int", j, "wstr")
            OutputDebugString(sRes)
            WinSetText(nPass & ": " & sRes, hWnd)
        Next
    Next

    DllCall(sLibName & "\TorrentClose", "handle", hHandle)
    DllCall("FreeLibrary", "handle", hDll)
EndFunc 

#Func FindTorrentParts(lParam)
#    RunThread "ThreadTorrentParts" lParam
#EndFunc

Func FindTorrentParts(lParam)
    # модификаторы вызова
    Local b_CTRL = IsPressed (0x11), b_Shift = IsPressed (0x10)
    If lParam = 1 Then b_CTRL = true
    If lParam = 2 Then b_Shift = true    
    
    # повторный вызов при запущенной задаче
    If h_WinFindTorr Then
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       g_FindTorrTask = 0  
       Return
    Endif
    
    If gEvAuto And Not ProcessExist("Everything.exe") Then 
       ShellExec(gEvPath, "-startup")
       Sleep(gEvDelay)       
    Endif
    
    # имя файла под курсором
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    
    # файл не существует или является каталогом
    If Not FileExist(sFile) Then 
       ShowHint("File doesn't exist " & sFile)
       Return
    ElseIf StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Not a torrent file " & sFile)
       Return
    ElseIf FileGetSize(sFile) > 1024*1024*5 Then
       ShowHint("File size > 5 Mb " & sFile)
       Return
    EndIf    
    
    # путь к библиотеке плагина
    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName

    # не удалось загрузить библиотеку
    Local hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
    If hDll = 0 Then 
       ShowHint("TCTorrent.wlx can't load library " & sLibPath)
       Return
    EndIf    

    # библиотеке не удалось открыть файл
    Local hHandle = DllCall(sLibName & "\TorrentOpen", "wstr", sFile, "handle")
    If hHandle = 0 Then
        ShowHint("TCTorrent.wlx can't open file " & sFile)    
        DllCall("FreeLibrary", "handle", hDll)
        Return
    EndIf
    
    # файл не является торрент-файлом
    Local nFiles
    nFiles = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileCount", "int", 0, "wstr")
    If nFiles < 1 Then
       ShowHint("Corrupt torrent file " & sFile)
       DllCall(sLibName & "\TorrentClose", "handle", hHandle)       
       DllCall("FreeLibrary", "handle", hDll)       
       Return             
    EndIf  
    
    # окно прогресса операции
    h_WinFindTorr = 0
    If g_WinThread Then 
       RunThread "WinFindTorrentData"
       While g_FindTorrTask = 0
           Sleep(50)
       Wend
    Else
        WinFindTorrentData(0)
    EndIf
    
    TorrentGetFixed(sLibName, hHandle, sFile)
    
    # локальные переменные
    Local T1 = GetUptime(), T2 = T1, T3, bSpeed = 0, nRes = 0
    Local bName = Not b_Shift, bSize = Not b_CTRL, sSize, sMode, sMem, sDbg
    Local j, nCount, sRes, nError, sList, sDirs, aQuery = List(), aCount = List()
    
    Static aMode = List("«Имя и размер»", "«Только имя»", "«Только размер»")
    If bName And bSize Then
       nMode = 0
    ElseIf bName Then
       nMode = 1    
    Else
       nMode = 2
    EndIf
    sMode = aMode[nMode]
    
    # количество файлов в торренте
    nCount = DllCall(sLibName & "\TorrentCountGet", "handle", hHandle, "wstr", "File", "uint")

    # перечисление файлов в торренте
    For j = 0 To nCount - 1
        
        If gTorrentDbg Then gDbgStep = "Step 1. TorrentGet j=" & j & auCRLF
        
        # имя файла
        sRes = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "File", "int", j, "wstr")
        
        # размер файла
        If bSize Then
           sSize = DllCall(sLibName & "\TorrentGet", "handle", hHandle, "wstr", "FileSize", "int", j, "wstr")
        EndIf
        
        sDbg = Round((j+1)/nCount*100,0) & '% - '
        If gTorrentDbg Then
           nRes += StrLen(sRes) + 8
           sMem = StrLen(sList) + StrLen(sDirs) + nRes
           sDbg &= SizeFormat(sMem*2, 1, 'G', 2) &  ' - '        
        EndIf

        If gTorrentDbg Then gDbgStep &= "Step 2. WinSetText " & sRes & auCRLF
        
        # меньше сообщений окну прогресса
        If bSpeed Then
           T3 = GetUptime()
           If Round(T3 - T2, 0) > 250 Then 
              WinSetText(sDbg & sRes, h_WinFindTorr)
              T2 = T3
           EndIf
        Else
           WinSetText(sDbg & sRes, h_WinFindTorr)
        EndIf

        If gTorrentDbg Then gDbgStep &= "Step 3. FileFindEv " & sRes & auCRLF
        
        # запрос к Everything
        If bName And bSize Then
           aQuery.Text = FileFindEv('*"' & sRes & '" size:' & sSize, "", "")
        ElseIf bName Then
           aQuery.Text = FileFindEv('*"' & sRes & '"', "", "")        
        Else
           aQuery.Text = FileFindEv('size:' & sSize, "", "")
        EndIf
                
        # ошибка запроса
        nError = ERROR
        If nError > 0 Then Break

        If gTorrentDbg Then gDbgStep &= "Step 4. aCount.Add" & auCRLF
        
        # обработка запроса
        aCount.Add("[" & aQuery.Count & "] " & sRes)        
        If aQuery.Count > 0 Then 
           If gTorrentDbg Then gDbgStep &= "Step 5. sList" & auCRLF
           sList &= aQuery.Text & auCRLF
           If gTorrentDbg Then gDbgStep &= "Step 6. sDirs" & auCRLF
           If nFiles > 1 Then 
              If gTorrentDbg Then gDbgStep &= "Step 7. StrReplace" & auCRLF
              sDirs &= StrReplace(aQuery.Text, sRes, "") & auCRLF
           Else
              sDirs &= aQuery.Text & auCRLF
           EndIf
        Else
           If gTorrentDbg Then 
              gDbgStep &= "Step 5. Skip" & auCRLF
              gDbgStep &= "Step 6. Skip" & auCRLF
              gDbgStep &= "Step 7. Skip" & auCRLF              
           EndIf             
        EndIf  

        If gTorrentDbg Then gDbgStep &= "Step 8. Next"
        #Sleep(3000)
        
        # опрерация прервана закрытием окна прогресса
        If g_FindTorrTask = 0 Then Break
    Next
    
    If gTorrentDbg Then gDbgStep &= "Step 9. Out"
       
    If nError = 1 Then MsgBox("Everything window not found.")
    If nError = 2 Then MsgBox("IPC Everything query execution error.")  
    If nError > 0 Then 
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)       
       Free(aCount, aQuery)
       DllCall(sLibName & "\TorrentClose", "handle", hHandle)
       DllCall("FreeLibrary", "handle", hDll)           
       Return
    EndIf

    Local c = 0, m = Map(), top5 = List(), sTop5, bDirs = StrLen(StrTrim(sDirs))
    
    # суммирование путей при непустом результате
    If g_FindTorrTask And bDirs Then 
       aQuery.Text = sDirs
       For value In aQuery
           c = 1
           If m.Has(value) Then c += m.Get(value)
           m.Set(value, c)
       Next
    EndIf
    
    # сортировка путей по убыванию
    If g_FindTorrTask And bDirs Then
       top5.SortMethod = 1 
       For key, value In m          
           top5.Add("[" & value & "]" & Chr(160) & key)
       Next
       top5.Sort(1)
       
       # выбор верхних пяти путей
       For j = 0 To top5.Count - 1
          sTop5 &= top5[j] & auCRLF
          If j >= 4 Then Break
       Next   
    EndIf
    
    c = top5.Count
    Local top1, files = aCount.Text
    If c > 0 Then top1 = StrTrim(StrPart(top5[0], Chr(160), 2))

    # освобождение объектов и библиотеки    
    Free(aCount, aQuery, top5, m)    
    DllCall(sLibName & "\TorrentClose", "handle", hHandle)
    DllCall("FreeLibrary", "handle", hDll)
    
    # время операции    
    T2 = Round(GetUptime() - T1, 0) / 1000
    T3 = "Время поиска: " &  StrFormat("%.3f", T2) & " sec"
    
    If gEvAuto Then ShellExec(gEvPath, "-exit")    
    
    If g_FindTorrTask = 0 Then
       MsgBox("Поиск отменен", "Autorun", 48)
    Else        
       # закрытие окна прогресса
       g_FindTorrTask = 0
       SendMessage(h_WinFindTorr, 0x0010, 0, 0)
       If DllCall("DestroyWindow", "handle", h_WinFindTorr) Then h_WinFindTorr = 0
       
       # ничего не найдено
       If c = 0 Then
          If nMode < 2 Then
             MsgBox("Найдено: " & c & auCRLF & auCRLF & _
                    "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                    "Режим: " & sMode & auCRLF & auCRLF & _                
                    "Продолжить в режиме " & aMode[nMode+1] & "?", "Autorun", 3+64+0)
             If EXTENDED = 6 Then Return FindTorrentParts(nMode+1)                
          Else
             MsgBox("Найдено: " & c & auCRLF & auCRLF & _
                    "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                    "Режим: " & sMode, "Autorun", 64)
          EndIf           
       Else          
          # проверка CapsLock
          Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
          If gCapsReverse Then bCaps = Not bCaps
          If bCaps Then
             ShowRedHint("Автопереход к найденному")
             GoToPathFromMsg(top1)
             Return
          EndIf          
          MsgBox("Найдено: " & c & auCRLF & auCRLF & sTop5 & auCRLF & _
                 "Торрент: " & nCount & " файлов" & auCRLF & T3 & auCRLF & _
                 "Режим: " & sMode & auCRLF & auCRLF & _                
                 "Сохранить в текстовый файл?", "Autorun", 3+64+0)
          If EXTENDED = 2 Then Return
          If EXTENDED = 7 Then GoToPathFromMsg(top1)
          If EXTENDED = 6 Then
             Local txt
             txt &= top1 & auCRLF & auCRLF
             txt &= "-----------------" & auCRLF             
             txt &= "Top 5 locations:" & auCRLF 
             txt &= "-----------------" & auCRLF             
             txt &= sTop5 & auCRLF
             txt &= "-----------------" & auCRLF             
             txt &= "Torrent files:" & auCRLF     
             txt &= "-----------------" & auCRLF             
             txt &= files & auCRLF & auCRLF
             txt &= "-----------------" & auCRLF                          
             txt &= "Full list:" & auCRLF
             txt &= "-----------------" & auCRLF                
             txt &= sList             
             SaveDataPathToText(sFile, txt)
          EndIf   
       EndIf
    EndIf
EndFunc

Func TorrentFindOptions()
     gTorrentDbg = Not gTorrentDbg
     ShowRedHint("Торрент Debug " & (gTorrentDbg ? "включен" : "выключен"))
EndFunc

Func TorrentDebugInfo()
    If Not gTorrentDbg Then gDbgStep = "Торрент Debug выключен"
    If gDbgStep = "" Then gDbgStep = "Empty"
    SetHintParam("ShowHint", "Font", 13, "Arial")
    SetHintParam("ShowHint", "BackColor", 0x000000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(gDbgStep)
    WinAlign(LAST_HINT_WINDOW)    
    ClipPut(gDbgStep)  
    SetHintParam("ShowHint", "Reload") 
EndFunc

Func TorrentGetFixed(TorrLib, TorrHandle, TorrFile)
    Local sRes, sComm, i = 0, bLib = false, hDll
    
    Static aFixed = List('Name', 'TotalSize', 'FileCount', 'BlockSize', 'BlockCount', _
                         'Created', 'Creator', 'Hash', 'Comment', 'Encoding', _
                         'Multifile', 'PrivateTorrent', 'Publisher', 'PublisherURL')
                         
    Static sLibName = "TCTorrent.wlx" & (auX64 ? "64" : "")
    Static sLibPath = COMMANDER_PATH & "\Plugins\wlx\TCTorrent" & sLibName
                         
    If TorrLib = 0 Then 
       TorrLib = sLibName 
       hDll = DllCall("LoadLibrary", "wstr", sLibPath, "handle")
       If hDll = 0 Then 
          gTorrentLog = "Can't load " & sLibPath
          Return 
       EndIf
       TorrHandle = DllCall(sLibName & "\TorrentOpen", "wstr", TorrFile, "handle")
       If TorrHandle = 0 Then
           DllCall("FreeLibrary", "handle", hDll)
           gTorrentLog = "Can't open " & TorrFile
           Return
       EndIf
       bLib = true
    EndIf   
                             
    gTorrentUrl = DllCall(TorrLib & "\TorrentGet", _
                   "handle", TorrHandle, "wstr", "PublisherURL", "int", 0, "wstr")
    gTorrentLog = "File: "   & TorrFile & auCRLF
    
    For i = 0 to aFixed.Count - 1
        sRes = DllCall(TorrLib & "\TorrentGet", _
               "handle", TorrHandle, "wstr", aFixed[i], "int", 0, "wstr")
        If i = 8 Then sComm = sRes
        gTorrentLog &= aFixed[i] & ": " & sRes & auCRLF
    Next
    
    gTorrentLog = StrTrim(gTorrentLog)
    If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = sComm
    If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = "[No valid URL] " & FileGetName(TorrFile)
    
    If bLib Then
       DllCall(sLibName & "\TorrentClose", "handle", TorrHandle)
       DllCall("FreeLibrary", "handle", hDll)
    EndIf   
EndFunc

Func TorrentFixedInfo()
    If gTorrentLog = "" Then gTorrentLog = "No torrent information"
    SetHintParam("ShowHint", "Font", 13, "Arial")
    SetHintParam("ShowHint", "BackColor", 0x000000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(gTorrentLog)
    WinAlign(LAST_HINT_WINDOW)
    ClipPut(gTorrentUrl)  
    SetHintParam("ShowHint", "Reload") 
EndFunc
[/cut]
Сейчас если ссылки нет в поле "PublisherURL", она ищется в поле "Comment". Если и в поле "Comment" ничего нет, то в буфер копируется текст "[No valid URL]" с именем файла. Информация в буфер попадает только после нажатия Alt+Win+T. Эта комбинация показывает подсказку о последнем запущенном torrent файле и копирует ссылку в буфер. Посмотрите, как вам такой вариант.
Спасибо. Работает. Буду стабильность тестировать.
В поле "PublisherURL" в моих торрент-файлах или ничего нет или ссылка на страницу профиля релизера.
Сссылки на страницу раздачи у меня все в "Comment".
Работает, но получается копирует то что нужно только в случае, если "PublisherURL" пусто (а это редкость). Начинать, как мне кажется, нужно с поля "Comment", а потом уже "PublisherURL".

Если есть возможность сделать, именно для себя костыль, копирование в буфер по умолчанию (без нажатия горячих клавишь), подскажете пожалуйста.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):А почему потоки, запускаемые из кнопок и горячих клавиш, не отображаются в GetState?
Я же писал совсем недавно - из плагинов нет статистики. А если бы и была, в подавляющем большинстве случаев код горячих клавиш отрабатывает так быстро, что нет смысла добавлять и сразу же удалять информацию в менеджере потоков.
Orion9 писал(а):Ведь эти функции тоже в отдельных потоках запускаются, верно?
Если из кнопок, зарегистрированных с RegisterCommand - то нет, они выполняются в том же потоке. В CSMA/SHA по умолчанию (без ключа /S) - в отдельном, так исторически сложилось.

По остальному прокомментировать нечего, пока не доберусь до тестирования.
Orion9 писал(а):Раз уж объект List корректно загружает файл в любой кодировке, то может ему и поле добавить "CodePage", где будут сведения о такой кодировке?
В принципе сейчас список нейтрален в смысле кодировки, хотелось бы его таким и оставить. И одной кодировкой тут не обойдёшься, придется хранить и информацию о BOM. Учитывая, что кодировка применима только к файловым функциям, не хотелось бы загромождать объект лишними свойствами. В общем тут надо думать.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

A55555
Я понял. Весь файл нет смысла скидывать, поменяйте просто заголовок и несколько строк в функции.

Было:

Код: Выделить всё

Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0, gTorrentUrl, gTorrentLog
Global gTorrentSize = 0, gTorrentCount = 0, gDriveInclude = "e:\;f:\;g:\;h:\;i:\;j:"
Стало:

Код: Выделить всё

Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0
Global gTorrentLog, gTorrentUrl, gTorrentUrlClip = 1
Global gTorrentSize = 0, gTorrentCount = 0, gDriveInclude = "e:\;f:\;g:\;h:\;i:\;j:"
Было:

Код: Выделить всё

gTorrentLog = StrTrim(gTorrentLog)
If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = sComm
If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = "[No valid URL] " & FileGetName(TorrFile) 
Стало:

Код: Выделить всё

gTorrentLog = StrTrim(gTorrentLog)
If StrPos(sComm, "http") Then 
   gTorrentUrl = sComm
Else
   If Not StrPos(gTorrentUrl, "http") Then gTorrentUrl = "[No valid URL] " & FileGetName(TorrFile)    
EndIf
If gTorrentUrlClip Then ClipPut(gTorrentUrl)
Loopback
Да, я забыл, что у Autorun есть проблемы с субплагинами и статистикой, но вопрос стоит по-прежнему остро: какой смысл в GetState("threads"), который ничего не показывает? К примеру, я запускаю несколько потоков через кнопки, а вижу только "Main". И зря вы так про менеджер. Задача менеджера как раз в том, чтобы показывать все потоки, даже те, которые запускаются на доли секунды.
Loopback писал(а):В общем тут надо думать.
Надо, наверное. Иначе путаница получается. Или придётся самостоятельно следить за маркером. Пока добавил условие:

Код: Выделить всё

Local bom = FileRead(gHBarFile, 2, "RAW")
If ERROR = 1 Then
   gHBarLoadError = 1
   gHBarCP = "Unknown"       
   Return
EndIf   
If bom = "FFFE" Then 
   gHBarCP = "UTF-16"
Else
   gHBarCP = "ANSI"
EndIf
Вроде работает. Но я смотрю у Гислера юникодная панель даже без маркера открывается, видимо он реализовал какой-то простенький алгоритм для этого типа проверки на нулевой байт или что-то в этом роде. Посмотрю, в общем, как лучше сделать. Одно радует: ни в UTF-8, ни в UTF-16 BE тотал панели не открывает, именно поэтому стоит проверка только на FFFE.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

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

Пока еще добавил проверку через маркер панели в UTF-16:

Код: Выделить всё

Local utf = "5B0042007500740074006F006E006200610072005D000D000A00"
Но это мелочи. Более крупные изменения затронули оконную процедуру. В прошлом виде она имела серьезные недостатки, например не кликались с первого раза кнопки с модификатором Ctrl. Пришлось отказаться от получения координат через MouseGetPos т.к. она нарушала работу DragDetect. А также пришлось добавить дополнительный вызов оригинальной гислеровской процедуры для правильной эмуляции нажатия:

Код: Выделить всё

DllCall("CallWindowProcW", _
   "ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam) 
DllCall("CallWindowProcW", _
   "ptr", gHBarWndProc, "hwnd", hWnd, "uint", WM_LBUTTONUP, "wparam", wParam, "lparam", lParam)
Return 0
Ну, добавил еще один путь для поиска временно-загруженной панели через GetCurrentPath(). Была идея указания пути через буфер или через поиск истории в ini, но пока мне это не нужно. У меня все панели храняться в \Bars и другого не предвидется. В общем, это последняя и довольно стабильная (проверял на разных панелях, кодировках и путях) версия модуля. Но если будете пользоваться (кому это фича интересна), обязательно делайте резервные копии. За порчу ваших панелей я не отвечаю )

[cut]

Код: Выделить всё

Pragma IncludeOnce

# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"

# правый клик с удержанием Ctrl
ControlSetMouseAction /R /K:C 28 "HBarShowMenu"

Global gDragIndex, gDropIndex
Global gHBarButtons = 0, gHBarDivs = 0

Global gHBarName, gHBarFile, gHBarTxt, gHBarCP = "ANSI", gHBarWincmd = 0
Global gHBarHint = 0, gHBarVerb, gHBarCancel, gHBarCancelLoad, gHBarLoadError = 0
Global gHBarList = List(), gHBarMap = List(), gHBarUndo, gHBarUndoTs, gHBarUndoLoad

Global gHBarWndProc, hBarWnd = 0
Global gHBarWP = Callback("HBarWndProc", "hwnd;uint;wparam;lparam")

Func HBarWndProc(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           hTotal = DllCall("GetModuleHandleW", "Ptr", 0, "handle"), _
           MK_SHIFT        = 0x0004, _      
           MK_CONTROL      = 0x0008, _
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202
    Static drag_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32646), _
           stop_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32648), _
           drag_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 22), _
           stop_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 21)
    Static SM_CXDRAG = 68, SM_CYDRAG = 69, _
           dragX = GetSystemMetrics(SM_CXDRAG), dragY = GetSystemMetrics(SM_CYDRAG), _
           startX, startY
    Local x, y, pos
    If gHBarLoadError Then 
       Return DllCall("CallWindowProcW", _
              "ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
    EndIf          
    Switch uMsg
       Case WM_LBUTTONDOWN 
          If IsDrag = 0 And BitAND(wParam, MK_CONTROL) Then
             #MouseGetPos("x","y")
             Static buf = Buffer(8)	# POINT
             buf.Zero()
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             startX = x
             startY = y
             buf.SetNum(0, "int", x, "int", y)
             DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
             pos = buf.GetNum(0, "int64")             
             #x = buf.GetNum(0)
             #y = buf.GetNum(4)
             #If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
             If DllCall("DragDetect", "hwnd", hWnd, "int64", pos) Then             
                IsDrag = 1
                WinSetStyle(0x80000, 3, hWnd)
                DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
                gDragIndex = HBarGetIdx()
             Else
                IsDrag = 0
                DllCall("CallWindowProcW", _
                   "ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam) 
                DllCall("CallWindowProcW", _
                   "ptr", gHBarWndProc, "hwnd", hWnd, "uint", WM_LBUTTONUP, "wparam", wParam, "lparam", lParam)
                Return 0
             EndIf
          EndIf    
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             DllCall("ReleaseCapture")
             IsDrag = 0
             If WinFromPoint() = hWnd Then
                gDropIndex = HBarGetIdx()
                If gDragIndex <> gDropIndex Then
                   If gHBarHint Then ShowDragHint("Index " & gDragIndex & " To Index: " & gDropIndex)
                   HBarDragnDrop(gDragIndex, gDropIndex)
                EndIf
             EndIf
             WinSetStyle(0x80000, 5, hWnd)
             Return 0
             #MouseGetPos("x","y")
             #lParam = MakeInt(y, x + 200, 2)
          EndIf
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             If WinFromPoint() = hWnd Then
                DllCall("SetCursor", "Ptr", drag_cursor)
             Else
                DllCall("SetCursor", "Ptr", stop_cursor)               
             EndIf
          EndIf   
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func HBarShowHint()
    If WinHasStyle(0x80000, 1, hBarWnd) Then Return
    # состояние Ctrl
    Local bMap = IsPressed(0x11)    
    # состояние CapsLock и Shift
    If Not bMap Then
       If BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1) = 0 Then
          If Not IsPressed(0x10) Then Return
       EndIf
    EndIf   
    # дескриптор горизонтальной панели 
    Local hWnd = RequestInfo(28)
    If hWnd = 0 Then 
       Return "Окно панели не найдено " & hWnd
    EndIf
    # глобальные переменные дескриптора и оконной процедуры
    If hBarWnd <> hWnd Then
       hBarWnd = hWnd
       gHBarWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                             "hwnd", hBarWnd, "int", -4, "long_ptr", gHBarWP.Ptr, "ptr")
    EndIf
    # поиск файла панели
    If gHBarName <> WinGetText(hBarWnd) Then
       gHBarUndo = false
       gHBarUndoLoad = ""
       gHBarCancel = false
       gHBarCancelLoad = ""       
       gHBarFile = HBarGetFile()
       If Not FileExist(gHBarFile) Then
          gHBarName = ""
          Return "Файл панели не найден " & gHBarFile
       EndIf   
       # загрузка панели
       HBarLoad()
       If gHBarLoadError Then Return HBarGetHint(bMap)
    EndIf
    # индекс кнопки под курсором
    gDragIndex = HBarGetIdx()
    If Not gDragIndex Then Return "Не удалось определить индекс кнопки"
    Return HBarGetHint(bMap)  
EndFunc

Func HBarGetFile()
    Local bar, txt
    # информация о файле панели в wincmd.ini
    IniRead bar %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"
    # раскрытие переменной окружения
    bar = Set(bar) 
    # в конфигурации указано только имя файла
    If FileGetDir(bar) = "" Then bar = COMMANDER_PATH & "\" & bar
    gHBarWincmd = bar
    # чтение текста окна панели
    txt = WinGetText(hBarWnd)
    gHBarName = txt
    # на панель загружен временный .bar файл
    If Not StrPos(bar, txt) Then       
       bar = COMMANDER_PATH & "\Bars\" & txt
    EndIf
    If Not FileExist(bar) Then
       bar = GetCurrentPath() & "\" & txt
    EndIf     
    # проверка существования файла панели
    If Not FileExist(bar) Then
       bar = COMMANDER_PATH & "\" & txt
    EndIf      
    Return bar
EndFunc

Func HBarLoad()
    gHBarLoadError = 0
    Local bar = FileRead(gHBarFile, 128, "RAW")
    Local bom = "FFFE"
    Local utf = "5B0042007500740074006F006E006200610072005D000D000A00"
    If ERROR = 1 Then
       gHBarLoadError = 1
       gHBarCP = "Unknown"       
       Return
    EndIf   
    If StrLeft(bar, 4) = "FFFE" Then 
       gHBarCP = "UTF-16 BOM"
    Else
       IF StrPos(bar, utf) Then
          gHBarCP = "UTF-16 без BOM"
       Else
          gHBarCP = "ANSI"
       EndIf
    EndIf
    # загрузка файла в массив
    gHBarList.Count = 0
    gHBarList.LoadFromFile(gHBarFile, gHBarCP)    
    # количество кнопок в файле
    Local nCount = 0
    IniRead nCount  %gHBarFile% "Buttonbar" "Buttoncount" 0
    # обнуление счетчиков
    gHBarDivs = 0
    gHBarButtons = 0
    # локальные переменные
    Local j, key, val, found, oButton = Map(), oCmd = Map()
    # поиск кнопок и команд
    For j = 0 To gHBarList.Count - 1        
        found = 0    
        If StrLeft(gHBarList[j], 6) = "button" Then  
           found = 1
        ElseIf StrLeft(gHBarList[j], 3) = "cmd" Then  
           found = 2
        EndIf
        If found > 0 Then
           key = StrLower(StrPart(gHBarList[j], "=", 1))
           val = StrLen(StrPart(gHBarList[j], "=", 2))
           If found = 1 Then
              oButton.Set(key, val)              
           Else
              oCmd.Set(key, val)          
           EndIf
        EndIf
    Next
    gHBarMap.Count = 0    
    # подсчет кнопок и разделителей
    For j = 1 To nCount     
        key = "button" & j
        val = oButton.Get(key, 0)         
        If val > 0 Then
           # количество кнопок                 
           gHBarButtons += 1
           gHBarMap.Add(1)
        Else
           # количество разделителей  
           gHBarDivs += 1   
           gHBarMap.Add(0)
        EndIf
    Next
    Free(oButton, oCmd)
    If gHBarButtons = 0 Then gHBarLoadError = 1
    # карта панели
    gHBarTxt = auCRLF & auCRLF & "Loaded" & ": " & gHBarFile & " > " & gHBarCP & " "
    If gHBarLoadError Then gHBarTxt &= " -- ERROR LOADING"
    gHBarTxt &= auCRLF
    For j = 0 To gHBarMap.Count - 1
        gHBarTxt &= gHBarMap[j] & "  "
        If j > 0 and Mod(j, 50) = 0 Then gHBarTxt &= auCRLF
    Next
    gHBarTxt &= auCRLF & "Wincmd.ini: " & gHBarWincmd
EndFunc

Func HBarGetIdx()
    # дескриптор монитора окна ТС
    Local hMon = DllCall("MonitorFromWindow", "hwnd", AUTORUN_TCHANDLE, "dword", 2)
    # буфер для структуры MONITORINFOEX
    Local buf = Buffer(104)
    buf.Zero()
    buf.SetNum(0, "dword", 104)
    DllCall("GetMonitorInfoW", "ptr", hMon, "ptr", buf.ptr)
    # имя монитора
    Local sMon = buf.GetStr(40)
    # информация о масштабировании экрана
    Local DC = DllCall("GetDC", "int", 0)
    Local nDPI = DllCall("GetDeviceCaps", "handle", DC, "int", 88) # LOGPIXELSX
    Local nScale = DllCall("MulDiv", "int", 100, "int", nDPI, "int", 96)
    DllCall("ReleaseDC", "int", 0, "handle", DC)     
    # локальные переменные
    Local x, y, w, h, mx, my, idx, row, rows, rowh, dpi, b, extra
    # координаты и размеры окна панели
    WinGetPos("x", "y", "w", "h", hBarWnd) 
    # координаты указателя мыши
    MouseGetPos("mx", "my")
    # чтение информации о высоте кнопок
    IniRead b %COMMANDER_INI% "Buttonbar" "Buttonheight"
    IniRead dpi %COMMANDER_INI% "Buttonbar" "DefaultDpi" %'nDPI'
    Local b_ini = b, b_calc
    # масштабирование экрана
    If dpi <> nDPI Then
       IniRead d %COMMANDER_INI% "Buttonbar" %'"Buttonheight" & nDPI' 0
       If d <> 0 Then 
          b = d
       Else   
          b = Round(b / (dpi / nDPI), 0)
          b_calc = "*"
       EndIf
    EndIf   
    # количество рядов кнопок на панели
    rows = Floor(h/b)
    If rows = 0 Then Return HBarShowHint("Error number of rows can't be zero")
    # количество дополнительных пикселей
    extra = Mod(h,b)
    # ширина разделителя    
    Local div = Floor(b/3)
    # высота одного ряда
    rowh = b + 3
    # номер ряда под указателем
    row = Ceil((my - y)/rowh)
    # абстрактные координаты по оси х
    Local tx = (mx - x + 1) + ((row - 1) * w), cx = 0
    # индекс кнопки в ряду    
    If gHBarDivs = 0 Then
       idx = (Floor((mx - x)/b) + 1) + (row-1)*(Floor(w/b))
    Else
       j = 1
       idx = 0       
       For i = 0 To gHBarMap.Count - 1
           cx += (gHBarMap[i] = 0 ? div : b)
           ex = j*w - cx
           If i + 1 <= gHBarMap.Count - 1 Then
              If ex < (gHBarMap[i+1] = 0 ? div : b) Then
                 cx += ex
                 j += 1
              EndIf
           Else
              cx += ex   
           EndIf   
           If cx >= tx Then
              idx = i + 1
              Break
           EndIf   
       Next        
    EndIf
    # дополнительная информация
    gHBarVerb = "mouse=" & mx & ", " & my & auCRLF & _
                "bar=" & x & ", " & y & ", " & w & ", " & h & auCRLF &  _
                "map=" & tx & ", " & cx & auCRLF & _
                "row=" & row & " of " & rows & auCRLF & _
                "height=" & rowh & " (" & extra & ")" & " b=" & b & b_calc & " (" & b_ini & ")" & auCRLF & _
                "buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _ 
                "width=" & b & ", " & div & auCRLF & _
                "mon=" & HMon & " dpi=" & nDPI & " scale=" & nScale & "%"     
    Return idx
EndFunc

Func HBarGetHint(bMap)
    # чтение информации о кнопке из .bar фйла
    Local sMenu, sButton, sCmd, sParam, sPath, sIcon
    IniRead sMenu   %gHBarFile% "Buttonbar" %'"menu"   & gDragIndex' ""
    IniRead sButton %gHBarFile% "Buttonbar" %'"button" & gDragIndex' ""
    IniRead sCmd    %gHBarFile% "Buttonbar" %'"cmd"    & gDragIndex' ""
    IniRead sParam  %gHBarFile% "Buttonbar" %'"param"  & gDragIndex' ""
    IniRead sPath   %gHBarFile% "Buttonbar" %'"path"   & gDragIndex' ""
    IniRead sIcon   %gHBarFile% "Buttonbar" %'"iconic" & gDragIndex' ""
    # удаление подсказки тотала
    Local hTip = WinFind(0, "TToolTip")
    If hTip > 0 Then DllCall("DestroyWindow", "handle", hTip)
    # возврат текста     
    Return gHBarVerb & auCRLF & _
           "" & auCRLF & _           
           "index=" & gDragIndex & " of " & gHBarButtons+gHBarDivs & auCRLF & _           
           "menu=" & sMenu & auCRLF & _
           "button=" & sButton & auCRLF & _
           "cmd=" & sCmd & auCRLF & _
           "param=" & sParam & auCRLF & _
           "path=" & sPath  & auCRLF & _
           "iconic=" & sIcon & (bMap ? gHBarTxt : "")
EndFunc

Func HBarDragnDrop(DragIdx, DropIdx)
    Static aItems = List("button","cmd","param","path","menu","iconic")
    Local T1, T2, bTL = 0
    If bTL Then T1 = GetUptime()    
    Local i, j, k, txt, key, new
    txt = gHBarList.Text
    gHBarUndoLoad = txt
    If Not gHBarCancel Then
       gHBarCancel = true
       gHBarCancelLoad = txt
    EndIf   
    # временная замена индекса
    For j = 0 To aItems.Count - 1
       key = aItems[j] & DragIdx & "="
       new = aItems[j] & 9999 & "="
       txt = StrReplace(txt, key, new)          
    Next
    If bTL Then   
       T2 = Round(GetUptime() - T1, 0) / 1000
       OutputDebugString("Время операции 1: " &  StrFormat("%.3f", T2) & " sec")
    EndIf   
    If DragIdx < DropIdx Then
       For i = DragIdx + 1 To DropIdx
            For k = 0 To aItems.Count - 1
               key = aItems[k] & i & "="
               new = aItems[k] & i - 1 & "="       
               txt = StrReplace(txt, key, new)
               If bTL Then OutputDebugString("DragIdx < " & key & " -> " & new)               
            Next
        Next
     Else
       For i = DragIdx - 1 TO DropIdx Step -1
            For k = 0 To aItems.Count - 1
               key = aItems[k] & i & "="
               new = aItems[k] & i + 1 & "="       
               txt = StrReplace(txt, key, new)
               If bTL Then OutputDebugString("DragIdx > " & key & " -> " & new)               
            Next
        Next
     EndIf
    If bTL Then   
       T2 = Round(GetUptime() - T1, 0) / 1000
       OutputDebugString("Время операции 2: " &  StrFormat("%.3f", T2) & " sec")
    EndIf 
    For j = 0 To aItems.Count - 1
       key = aItems[j] & 9999 & "="
       new = aItems[j] & DropIdx & "="
       txt = StrReplace(txt, key, new)          
    Next
    gHBarList.Text = txt
    gHBarList.SaveToFile(gHBarFile, gHBarCP)
    gHBarUndoTs = FileGetTime(gHBarFile)
    If gHBarUndoTs Then 
       gHBarUndo = true
    Else
       gHBarUndo = false    
       gHBarUndoLoad = ""   
    EndIf   
    HBarLoad()
    If bTL Then   
       T2 = Round(GetUptime() - T1, 0) / 1000
       OutputDebugString("Время операции 3: " &  StrFormat("%.3f", T2) & " sec")
    EndIf     
    SendCommand(2945)     # cm_ReloadBarIcons
EndFunc

Func ShowDragHint(DragHint)
    SetHintParam("ShowHint", "Font", 14, "Arial")
    SetHintParam("ShowHint", "BackColor", 0x000000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
    SetHintParam("ShowHint", "DarkText", 0xFFFFFF)    
    ShowHint(DragHint, "", "", 3000, 1)
    WinAlign(LAST_HINT_WINDOW)    
    Sleep(10)
    SetHintParam("ShowHint", "Reload")  
EndFunc

Func HBarShowMenu()
    Local hWnd = RequestInfo(28)
    If hWnd = 0 Then 
       ShowDragHint("Окно панели не найдено")
       Return
    EndIf
    If gHBarName <> WinGetText(hWnd) Then
       ShowDragHint("Нет сведений о файле панели")
       Return
    EndIf
    ShowPopupMenu /D /F /I:0 "HBarMenu"
EndFunc

Func HBarMenu()
    Local txt
    Local bak1 = FileChangeExt(gHBarFile, "bak1")
    Local bak2 = FileChangeExt(gHBarFile, "bak2")    
    txt &= 'MENUITEM "'  & gHBarName & '", em_aucmd /D' & auCRLF
    txt &= 'MENUITEM SEPARATOR' & auCRLF
    txt &= 'MENUITEM "Загружена как ANSI", em_aucmd  ' & (gHBarCP = "ANSI" ? "/C" : "") & ' -1' & auCRLF
    txt &= 'MENUITEM "Загружена как UTF-16", em_aucmd  ' & (StrPos(gHBarCP, "UTF-16") ? "/C" : "") & ' -1' & auCRLF
    txt &= 'MENUITEM SEPARATOR' & auCRLF
    txt &= 'MENUITEM "Отменить действие", em_aucmd ' & (gHBarUndo ?  "" : "/D") & ' -1 HBarUndo' & auCRLF
    txt &= 'MENUITEM "Вернуть первоначальную панель", em_aucmd ' & (gHBarCancel ?  "" : "/D") & ' -1 HBarCancel' & auCRLF
    txt &= 'MENUITEM SEPARATOR' & auCRLF
    txt &= 'MENUITEM "Резервная копия 1", em_aucmd ' & (FileExist(bak1) ? "" : "/D") & ' -1 HBarLoadBak 1' & auCRLF
    txt &= 'MENUITEM "Резервная копия 2", em_aucmd ' & (FileExist(bak2) ? "" : "/D") & ' -1 HBarLoadBak 2' & auCRLF    
    txt &= 'MENUITEM SEPARATOR' & auCRLF
    txt &= 'MENUITEM "Сделать резервную копию 1", em_aucmd -1 HBarSaveBak 1' & auCRLF
    txt &= 'MENUITEM "Сделать резервную копию 2", em_aucmd -1 HBarSaveBak 2' & auCRLF    
    Return txt
EndFunc

Func HBarSetCodePage(nCodePage)
    Local sCP = (nCodePage = 1 ? "ANSI" : "UTF-16")
    Local bLoadQ = gHBarCP <> sCP
    gHBarCP = sCP
    If bLoadQ Then
       MsgBox("Открыть панель в кодировке " & gHBarCP & "?", "Autorun", 3+64+0)
       If EXTENDED = 6 Then 
          HBarLoad()
          ShowDragHint("Панель открыта как " & gHBarCP)
          SendCommand(2945)  
       EndIf   
    EndIf
EndFunc

Func HBarSaveBak(nBak)
     Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
     If FileExist(bak) Then
        MsgBox("Файл существует" & auCRLF & auCRLF & _
                bak & auCRLF & auCRLF & "Перезаписать?", "Autorun", 3+32+0)
        If EXTENDED <> 6 Then Return
     EndIf
     FileCopy(gHBarFile, bak, 1)
     ShowDragHint("Файл сохранен " & bak)
EndFunc

Func HBarLoadBak(nBak)
     Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
     If Not FileExist(bak) Then
        MsgBox("Файл не существует " & bak, "Autorun")
        Return
     EndIf
     If Not FileExist(gHBarFile) Then
        MsgBox("Файл не существует " & gHBarFile, "Autorun")
        Return
     EndIf     
     MsgBox("Файл " & gHBarFile & " будет перезаписан файлом " & _
                bak & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
     If EXTENDED <> 6 Then Return
     FileCopy(bak, gHBarFile, 1)     
     HBarLoad()
     ShowDragHint("Файл загружен " & bak)
     SendCommand(2945)
EndFunc

Func HBarUndo()
    If Not gHBarUndo Then Return
    If FileGetTime(gHBarFile) <> gHBarUndoTs Then
       MsgBox("Файл " & gHBarFile & " изменился на диске" & auCRLF & auCRLF & _
              "Отмена действия невозможна", "Autorun", 64)
       Return       
    EndIf
    FileWrite(gHBarFile, gHBarUndoLoad, gHBarCP)    
    If ERROR = 1 Then
       MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
    Else
       gHBarUndo = false
       gHBarUndoLoad = ""
       HBarLoad()
       ShowDragHint("Действие отменено")
       SendCommand(2945)
    EndIf   
EndFunc

Func HBarCancel()
    If Not gHBarCancel Then Return
    If gHBarCancelLoad = "" Then Return MsgBox("Пустое значение CancelLoad")
    MsgBox("Файл будет перезаписан" & auCRLF & auCRLF & _
            gHBarFile & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
    If EXTENDED <> 6 Then Return
    FileWrite(gHBarFile, gHBarCancelLoad, gHBarCP)    
    If ERROR = 1 Then
       MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
    Else
       gHBarCancel = false
       gHBarCancelLoad = ""
       HBarLoad()
       ShowDragHint("Первоначальная панель загружена")
       SendCommand(2945)
    EndIf   
EndFunc
[/cut]
Критерий работоспособности функционала определить просто: если при наведении указателя мыши на последнюю кнопку панели с клавишей Ctrl информация в подсказке о ней отображается правильно, то значит и dragndrop на панели тоже будет работать правильно.
Mrak_Tlen
Сообщения: 30
Зарегистрирован: Вт окт 08, 2024 21:37

Сообщение Mrak_Tlen »

Добре
# На среднюю кнопку мыши - ком строка поле ввода вешаю меню TCDirMenu из TWinKey

Код: Выделить всё

ControlSetMouseAction /M 20 CommandExec em_CMD-20
где
[em_CMD-20]
cmd=cm_FocusCmdLine,em_tcdirmenu
[em_tcdirmenu]
cmd=%AHK1% %COMMANDER_PATH%\Plugins\wdx\TWinKey\tcdirmenu.ahk

Ахк это тупо нажатие Альт+1
tcdirmenu.ahk
Send, !1

Такое ощущение, что я нагромоздил лишнего )))

З.Ы. оказывается когда речь о поле ввода(№20 на скриншоте справки авторана), то отрабатывает оно не на панели ввода, а на маленькой стрелочке последних команд. Не сразу понял что не так и почему 1я строка моего сообщения не работает, а она то работает, но есть нюанс )))
A55555
Сообщения: 72
Зарегистрирован: Вс фев 06, 2011 10:50

Сообщение A55555 »

Orion9
спасибо большое. Работает.
Зависаний пока не было и ощущение, что 70504 быстрее стало работать.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Mrak_Tlen
Если у вас x64, то проблема может быть в плавающем Id контролов, которая иногда появляется в этой версии. Как-то затрагивали эту тему.

A55555
Рад, что все получилось как нужно.

Я тут обновил код подсказки, попробуйте, если интересно. Только старую функцию вам нужно будет удалить, чтобы не было проблем с дулирующими именами. Я еще буду пересматривать код, но общие черты не поменяются:

[cut]Изображение[/cut]

[cut="MediaInfo.aucfg"]

Код: Выделить всё

Pragma IncludeOnce

# 71000-71099

RegisterCommand 71000 "Duration"
RegisterCommand 71010 "MediaInfoTest"

Global gMediaInfoX32 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo_i386.dll"
Global gMediaInfoX64 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo.dll"

Global gDurationInfo = 0, gDurationBreak = false, gDurationBaloon = 1, gDurationTXT

Global gFilterAudio = ".aac .ac3 .aif .aiff .aifc .afc .ape .au .snd .cda .dsf .dts .dtswav .dtshd .dtsma .eac3 .flac .fla .m1a .m2a .mka .mpa .mp1 .mp2 .mp3 .mp4 .m4a .m4b .m4r .mod .mpc .mp+ .mpp .oga .ogx .ogg .ra .spx .opus .qoa .svx .8svx .tak .tta .wav .wave .w64 .bwf .rf64 .wma .wv"

Global gFilterVideo = ".avi .wmv .wmp .wm .asf .mpg .mpeg .mpe .m1v .m2v .mpv2 .mp2v .ts .tp .tpr .trp .vob .ifo .ogm .ogv .mp4 .m4v .m4p .m4b .3gp .3gpp .3g2 .3gp2 .mkv .rm .ram .rmvb .rpm .flv .swf .mov .qt .amr .nsv .dpg .m2ts .m2t .mts .dvr-ms .k3g .skm .evo .nsr .amv .divx .webm .wtv .f4v .mxf"

Global gBTipWndProc, gBTipWnd = Map(), gBTip = 0
Global gBText = Buffer(1024),  gBTool = Buffer(auX64 ? 56 : 40)
Global gBTipX, gBTipY
Global gBTipWP = Callback("BTipWndProc", "hwnd;uint;wparam;lparam")

Func Duration(lParam)
    If gDurationInfo > 0 Then
       gDurationBreak = true
       Sleep(250)
       Return
    EndIf
    If gDurationBaloon Then
       gBTip = CreateBaloonTip("MediaInfo", 1, 200)
       If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")       
    EndIf   
    RunThread DurationInfo
EndFunc

Func DurationInfo()
    Local T1 = GetUptime(), T2 = T1
    Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)    
    Local bCtrl = IsPressed(0x11), bShift = IsPressed(0x10), bAlt = IsPressed(0x12)
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
    Static sExt = gFilterAudio & " " & gFilterVideo
    If Not bAlt Then
       If hLib = 0 Then 
          ShowMediaHint("Error LoadLibrary " & sLib)
          Return 
       EndIf
       Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
       Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
       Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
       Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
       Local hMI = DllCall(pNew, "Ptr")
       If hMI = 0 Then 
          ShowMediaHint("MediaInfo.dll couldn't create new object")
          Return
       Endif
    Else     
       Local obj = Plugin("TCMediaInfo")
       If ERROR <> 0 Then
          ShowMediaHint("TCMediaInfo.wdx plugin error " & ERROR)
          Return
       Endif
    EndIf
    Local sDuration
    Local aSel = List()
          aSel.Text = GetSelectedItems(3, 0)       
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If aSel.Count = 0 Then
       If Not FileExist(sFile) Then 
          ShowMediaHint("Файл не существует " & sFile)
          Free(aSel)
          If bAlt Then Free(obj)
          Return
       Endif
    EndIf       
    If aSel.Count = 0 And Not StrPos(FileGetAttr(sFile), "D") Then
       Free(aSel)
       If bAlt Then
          obj.FileName = sFile     
          sDuration = obj.GetValue(0)	# duration
          Free(obj)
       Else
          If DllCall(pOpen, "Ptr", hMI, "Wstr", sFile, "Uint") <> 1 Then
             Return ShowMediaHint("MediaInfo.dll coudn't open file " &  sFile)                            
          EndIf
          sDuration = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                                    "Wstr", "Duration/String3", "Int", 1, "Int", 0, "Wstr")
       EndIf   
       Return ShowMediaHint("Файл: " & sName & auCRLF & "Длительность: " & sDuration, 1) 
    Endif
    gDurationInfo = 1    
    gDurationBreak = false
    ShowMediaHint("Загрузка", 1)    
    Local i, j, valid = 0
    Local dirs = 0, files = 0, errs = 0, item = 0, aFiles = List(), seconds = 0, b_Hint = 0
    Local depth = (bCtrl ? 1 : 0), ms = 0
    bExtLog = false
    # загрузка файлов в массив    
    If aSel.Count > 0 Then
       For j = 0 To aSel.Count - 1
          sFile = sPath & aSel[j]
          If FileExist(sFile) Then 
             valid += 1
             aFiles.Add(sFile)
             If StrPos(FileGetAttr(sFile), "D") Then 
                If ListMediaFiles(sFile, aFiles, depth) > 0 Then aFiles.Count = 0
             EndIf   
          EndIf   
       Next
       sName = aSel.Count & "/" & valid
    Else
       aFiles.Add(sFile)
       ListMediaFiles(sFile, aFiles, depth)
    EndIf
    Free(aSel)
    If aFiles.Count > 1 Then
       ShowMediaHint("Depth: " & depth & auCRLF & _
                     "CapsLock: " & (bCaps ? "Yes" : "No") & auCRLF & _
                     (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                     "Элементов: " & aFiles.Count & auCRLF & _                     
                     "Подсчёт времени...", 1)
    EndIf
    T2 = GetUptime()
    If bShift Then
       DurationLogString("Duration.Name:" & sName)    
       DurationLogString("Duration.Items:" & aFiles.Count)
    EndIf   
    For i = 0 To aFiles.Count - 1
        If bExtLog Then DurationLogString("Duration.File:" & aFiles[i])
        If StrPos(FileGetAttr(aFiles[i]), "D") Then
           dirs += 1
           If bExtLog Then DurationLogString("Duration.Directory:" & aFiles[i])
           Continue 
        EndIf
        item += 1
        If bAlt Then
           obj.FileName = aFiles[i]
           ms = obj.GetValue(0,3)	# duration -> milliseconds
        Else
           ext = FileGetExt(aFiles[i])
           If Not bCaps Then
              If Not StrPos(sExt, '.' & ext) Then 
                  If bShift Then DurationLogString("Duration.Filter:" & aFiles[i])
                 Continue
              EndIf
           EndIf
           If DllCall(pOpen, 'ptr', hMI, "wstr", aFiles[i], "uint") <> 1 Then
              errs += 1
              If bShift Then DurationLogString("Duration.Error:" & aFiles[i])
              Continue        
           EndIf
           ms = DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Duration", "int", 1, "int", 0, "wstr")
        EndIf
        If ms > 0 Then
           seconds += ms
           files += 1
        Else
           If bShift Then DurationLogString("Duration.Empty:" & aFiles[i])
        EndIf
        If gDurationBreak = true Or (IsPressed (0x11) And IsPressed (0x1B)) Then
           ShowMediaHint("Операция прервана", 1)
           Sleep(500)
           If gDurationBaloon Then
              Static buf = Buffer(160)
              buf.Zero()
              buf.SetStr("Прервано" & Chr(0))
              SendMessage(gBTip, 1057, 3, buf.ptr)              
           EndIf   
           Break
        EndIf
        If Round(GetUptime() - T2, 0) > 500 Then
           ShowMediaHint("Depth: " & depth & auCRLF & _
                    "CapsLock: " & (bCaps ? "Yes" : "No") & auCRLF & _
                    (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                    "Элементов: " & aFiles.Count & auCRLF & _                     
                    "Обработка: " & i & " из " & aFiles.Count, 1)                        
           T2 = GetUptime()
         EndIf
    Next    
    If bAlt Then Free(obj)
    If Not bAlt And hMI <> 0 Then DllCall(pDel, "Ptr", hMI)
    gDurationInfo = 0    
    gDurationBreak = false
    seconds = Floor(seconds / 1000)
    Local day = Floor(seconds / 86400)
    Local hour = Floor((seconds - (day * 86400)) / 3600)
    Local min = Floor(((seconds - (day * 86400)) - (hour * 3600)) / 60)
    Local sec = seconds - (day * 86400 + hour * 3600 + min * 60)
    Local total = StrFormat("%02d:%02d:%02d:%02d",day,hour,min,sec)
    Local tl = Round(GetUptime() - T1, 0) / 1000 
    Local txt = "Имя: " & sName & auCRLF & _
                "Каталогов: " & dirs & auCRLF & _    
                "Элементов: " & aFiles.Count & auCRLF & _
                "Обработано: " & files & " из " & item & auCRLF & _
                "Ошибки DLL: " & errs & auCRLF & _
                "Секунды: " & seconds & auCRLF & _
                "Минуты: " & Round(seconds / 60, 2) & auCRLF & _
                "Часы: " & Round(seconds / 3600, 2) & auCRLF & _
                "Сутки: " & Round(seconds / 86400, 2) & auCRLF & _             
                "Время: " & Chr(0x2211) & " "& total & auCRLF & _
                "Powered by " & (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                "Время операции: " &  StrFormat("%.3f", tl) & " sec"
    If bShift Then DurationLogString(auCRLF)
    Free(aFiles)
    ClipPut(txt)
    ShowMediaHint(txt, 1)
EndFunc

Func ListMediaFiles(sPath, ByRef aList, nDepth = 1)
    Local sFile, nAttr
    Local ffd = Buffer(604), bEsc = false
    Local hf = DllCall("FindFirstFileW", "wstr", sPath & "\*.*", "ptr", ffd.Ptr)
    If hf <> 0 then 
        While True 
            sFile = ffd.GetStr(44)         # cFileName
            nAttr = ffd.GetNum(0, "dword") # dwFileAttributes
            If BitAND(nAttr, 16) Then 
               If Not ((sFile = ".") Or (sFile = "..")) Then 
                  aList.Add(sPath & "\" & sFile)
                  If nDepth <> 1 Then
                     ListMediaFiles(sPath & "\" & sFile, aList, nDepth - 1)
                  EndIf   
               EndIf
            Else
               aList.Add(sPath & "\" & sFile)
            Endif     
            If DllCall("FindNextFileW", "handle", hf, "ptr", ffd.Ptr) = 0 Then Break
            If IsPressed (0x1B) Then
                bEsc = true
                Break
            EndIf    
        Wend
        DllCall("FindClose", "handle", hf)
    Endif 
    Free(ffd)
    Return bEsc
EndFunc

Func DurationLogString(LogString)
    gDurationTXT &= LogString & auCRLF
EndFunc

Func ShowMediaHint(MediaHint, Persist = false)
    # удаление подсказки тотала
    If gDurationBaloon And gBTip > 0 Then
       Local hTip = WinFind(0, "TToolTip")
       If hTip > 0 Then SendMessage(hTip, 0x0010, 0, 0)
       UpdateBaloonTip(gBTip, MediaHint)
       Return
    EndIf
    SetHintParam("ShowHint", "Font", 11, "Arial")
    #SetHintParam("ShowHint", "BackColor", 0x000000)
    #SetHintParam("ShowHint", "Text", 0xFFFFFF)
    SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
    SetHintParam("ShowHint", "DarkText", 0xFFFFFF)
    If Persist Then
       ShowHint(MediaHint)    
    Else    
       ShowHint(MediaHint, "", "", 3000, 1)
    EndIf   
    Sleep(10)
    SetHintParam("ShowHint", "Reload")  
EndFunc

Func MediaInfoTest(lParam)
    Local sFile = RequestCopyDataInfo("SP") & RequestCopyDataInfo("SN")
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       Return 
    Endif    
    If StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Каталог " & sFile)
       Return 
    Endif
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
    If hLib = 0 Then 
       ShowHint("Error LoadLibrary " & sLib)
       Return
    EndIf
    Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
    Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
    Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
    Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
    Static pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
    Static pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")    
    Local hMI = DllCall(pNew, "Ptr")
    If hMI = 0 Then 
       ShowHint("MediaInfo.dll couldn't create new object")
       Return 
    Endif
    If DllCall(pOpen, 'ptr', hMI, "wstr", sFile, "uint") <> 1 Then
       DllCall(pDel, "Ptr", hMI)        
       Return ShowHint("MediaInfo.dll couldn't open file " &  sFile)
    EndIf
    Local sMI
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Duration", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "VideoCount", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "AudioCount", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Recorded_Date", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover_Mime", "int", 1, "int", 0, "wstr") & auCRLF 
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Track/Position", "int", 1, "int", 0, "wstr")
    If IsPressed(0x11) Then
       DllCall(pOpt, 'ptr', hMI, "wstr", "Complete", "wstr", "0", "wstr")
       DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", "Inform", "Wstr")       
       sMI = DllCall(pInfo, 'ptr', hMI, "uint", 0, "wstr")       
    EndIf
    DllCall(pDel, "Ptr", hMI)
    If gDurationBaloon Then
       gBTip = CreateBaloonTip("MediaInfo", 1, 200)
       If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")
    EndIf
    If StrTrim(sMI) = "" Then sMI = "нет данных"
    ShowMediaHint(sMI)
EndFunc

Func CreateBaloonTip(TipTitle, TipIcon, TipWidth)
    Static TTM_TRACKACTIVATE   = 1041, _
           TTM_TRACKPOSITION   = 1042, _
           TTM_SETMAXTIPWIDTH  = 1048, _
           TTM_SETTITLE        = 1057, _
           TTM_ADDTOOL         = 1074
    Local hTip
    hTip = DllCall("CreateWindowExW", _
                 "dword", 8, _
                 "wstr", "tooltips_class32", _
                 "wstr", "", _
                 "dword", 0x00000c0, _
                 "int", 0, "int", 0, "int", 0, "int", 0, _
                 "handle", AUTORUN_TCHANDLE, _
                 "handle", 0, "handle", 0, "ptr", 0, "handle")
    If hTip = 0 Then Return 0
    MouseGetPos("gBTipX","gBTipY")
    #gBTipWnd.Set(hTip, MakeInt(gBTipX, gBTipY, 2))
    gBTipWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                           "hwnd", hTip, "int", -4, "long_ptr", gBTipWP.Ptr, "ptr")
    Local buf = Buffer(160)
    buf.Zero()
    buf.SetStr(TipTitle & Chr(0))
    SendMessage(hTip, TTM_SETTITLE, TipIcon, buf.ptr)
    gBText.Zero()
    gBText.SetStr("Инициализация" & Chr(0))    
    gBTool.Zero()                              # TTTOOLINFO
    If auX64 Then
       gBTool.SetNum(0, "uint", gBTool.size, _
                        "uint", 0x00a0, _
                        "hwnd", AUTORUN_TCHANDLE, _
                        "uint_ptr", 0)
       gBTool.SetNum(48, "ptr", gBText.ptr)    
    Else
       gBTool.SetNum(0, "uint", gBTool.size, _
                        "uint", 0x00a0, _
                        "hwnd", AUTORUN_TCHANDLE, _
                        "uint_ptr", 0, _
                        "long", 0, _
                        "long", 0, _
                        "long", 0, _
                        "long", 0, _
                        "ptr", 0, _
                        "ptr", gBText.ptr)
    EndIf
    SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, TipWidth)
    SendMessage(hTip, TTM_ADDTOOL, 0, gBTool.ptr)
    SendMessage(hTip, TTM_TRACKACTIVATE, 1, gBTool.ptr)    
    SendMessage(hTip, TTM_TRACKPOSITION, 0, MakeInt(gBTipX, gBTipY, 0))
    Free(buf)
    Return hTip 
EndFunc

Func UpdateBaloonTip(hTip, TipText)
    Static TTM_UPDATETIPTEXT = 1081
    gBText.Zero()
    gBText.SetStr(TipText & Chr(0)) 
    SendMessage(gBTip, TTM_UPDATETIPTEXT, 0, gBTool.ptr)
EndFunc

Func BTipWndProcTest(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202, _
           TTM_TRACKPOSITION = 1042
    Static tx, ty       
    Switch uMsg
       Case WM_LBUTTONDOWN 
          If IsDrag = 0 Then
             MouseGetPos("tx","ty")
             If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(ty, tx, 2)) Then                
                IsDrag = 1
                DllCall("SetCapture", "hwnd", hWnd, "hwnd")     
             EndIf
          EndIf         
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             WinGetPos("gBTipX", "gBTipY", "", "", hWnd)                                         
             IsDrag = 0
             DllCall("ReleaseCapture") 
          Else
             DllCall("DestroyWindow", "handle", hWnd)                      
          EndIf  
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             MouseGetPos("x","y")             
             SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))    
          EndIf       
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func BTipWndProc(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           WM_CREATE       = 0x0001, _
           WM_DESTROY      = 0x0002, _
           WM_SHOWWINDOW   = 0x0018, _     
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202, _
           WM_RBUTTONUP    = 0x0205, _           
           TTM_TRACKACTIVATE = 1041, _
           TTM_TRACKPOSITION = 1042
    Static SM_CXDRAG  = 68, _
           SM_CYDRAG  = 69, _
           DragWidth  = GetSystemMetrics(SM_CXDRAG), _
           DragHeight = GetSystemMetrics(SM_CYDRAG), _
           StartX     = 0, _
           StartY     = 0
    Local x, y
    Static tx, ty, buf = Buffer(8)
    Switch uMsg
       Case WM_SHOWWINDOW
          If wParam = 0 Then DllCall("DestroyWindow", "handle", hWnd)
       Case WM_DESTROY
          If gDurationInfo Then
             gDurationBreak = true
             MsgBox("Операция отменена")
             Return 0
          EndIf
       Case WM_LBUTTONDOWN
          If IsDrag = 0 Then
             buf.Zero()
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             StartX = x
             StartY = y
             buf.SetNum(0, "int", x, "int", y)
             DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
             tx = buf.GetNum(0)
             ty = buf.GetNum(4)
             IsDrag = 1
             DllCall("SetCapture", "hwnd", hWnd, "hwnd")
          EndIf          
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             WinGetPos("gBTipX", "gBTipY", "", "", hWnd)
             IsDrag = 0
             DllCall("ReleaseCapture")
          Else   
             DllCall("DestroyWindow", "handle", hWnd)             
          EndIf  
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             If Abs(x - startX) > DragWidth Or Abs(y - startY) > DragHeight Then
                buf.Zero()             
                buf.SetNum(0, "int", x, "int", y)
                DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
                x = buf.GetNum(0)
                y = buf.GetNum(4)                 
                SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))
             EndIf   
          EndIf
       Case WM_RBUTTONUP
            BTipShowMenu(hWnd)
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func BTipShowMenu(hWnd)
    ShowPopupMenu /D /F /I:0 "BTipCreateMenu"
EndFunc

Func BTipCreateMenu()
    Local txt
    txt &= 'MENUITEM "Лог операций", em_aucmd ' & (gDurationTXT <> "" ?  "" : "/D") & ' -1 DurationText' & auCRLF
    Return txt
EndFunc

Func DurationText()
    Local sLogFile = TEMP & "\duration.txt"
    FileWrite(sLogFile, gDurationTXT)
    ShellExec(sLogFile)
EndFunc
[/cut]
Двойной клик закрывает подсказку, правый клик показывает лог. Если gDurationBaloon = 0, то будет отображаться старая подсказка.
Mrak_Tlen
Сообщения: 30
Зарегистрирован: Вт окт 08, 2024 21:37

Сообщение Mrak_Tlen »

Если x64, то проблема может быть

Да, 64. Это не проблема, даже наверное хорошо, перевесил на правую кнопку мыши, что эргономичнее, просто пока отдуплил почему не работает... хорошо, что теперь понятно.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Mrak_Tlen
Я просто не успел вчера проверить. Подумал, что это связано с проблемой, с которой сам ранее столкунулся, когда делал вращение иконки a.k.a вентилятор Гислера
[cut]Изображение[/cut]
В ТС х64 вентилятор может плавать куда ему вздумается еще и черный квадрат за собой оставляет
[cut]Изображение[/cut]
Недавно уже писал, что в ТС х64 графический объект не всегда загружается, наверное чернота с этим связана. Но от идеи вращения пришлось отказаться не по этой причине. Оказалось, что эта иконка также зависает, как и другие более пригодные для этого элементы.

А по командной строке все нормально кликается (в конце на гифке видно), только целиться надо выше поля редактирования, что крайне не удобно. Для теста я использовал такой код:
[cut]

Код: Выделить всё

ControlSetMouseAction /R 20 CmdMenuTest

Func CmdMenuTest()
    ShowPopupMenu /D /F "CreateCmdMenu"
EndFunc

Func CreateCmdMenu()
    Local txt
    txt &= 'MENUITEM "Command 1", 100001' & auCRLF         
    txt &= 'MENUITEM "Command 2", 100002' & auCRLF         
    txt &= 'MENUITEM "Command 3", 100003' & auCRLF         
    txt &= 'MENUITEM SEPARATOR' & auCRLF
    txt &= 'MENUITEM "Settings...", 100004' & auCRLF         
    Return txt
EndFunc
[/cut]
Будем надеяться, в будущих версиях Loopback сделает собственную посылку клавиш и не придется вызывать сторонние скрипты для этого.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):Свойство делать необязательно, можно через макрос EXTENDED возвращать кодовую страницу, в которой загрузился файл в список.
Методы объектов не могут возвращать extended. Да и если бы могли, это число, а кроме кодировки надо еще возвращать признак BOM, это важно. Нет, ну понятно, что можно задействовать старший разряд, но неудобно, и напрямую параметром в метод записи не передать.

В принципе можно подумать о возвращаемом значении метода. Не очень красиво, но как вариант.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Loopback
Ну в общем-то это необязательно. Пользователю всё-равно придется следить за тем, в какой кодировке открывается файл, с которым он работает. А вот про потоки хотелось бы поподробнее. Например, для Autohotkey есть описание как все устроено. В английской справке, конечно, получше, чем в этой, но все же.

Касаемо Autorun, не совсем понятно, что именно происходит при запуске длительных операций из нескольких кнопок. Как осуществляется многозадачность? Тоталу отсылается номер зарегистрированной команды и адрес привязанной функции, а он уже сам дальше ее крутит? Крутит в своем отдельно созданном для этого потоке?
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Очередной видосик
[cut]Изображение[/cut]
Остальное чуть позже.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Практически полностью автономный модуль со всеми последними обновлениями:
[cut="MediaInfo.aucfg"]

Код: Выделить всё

Pragma IncludeOnce

# 71000-71099

RegisterCommand 71000 "Duration"
RegisterCommand 71010 "MediaInfoTest"

SetHotkeyAction /K:A /H:F12 SetHintFields
SetHotkeyAction /K:A /H:1 /DM /S ShowPipeEx 0 1
SetHotkeyAction /K:A /H:2 /DM /S ShowPipeEx 0 2
SetHotkeyAction /K:A /H:3 /DM /S ShowPipeEx 0 3
SetHotkeyAction /K:A /H:4 /DM /S ShowPipeEx 0 4
SetHotkeyAction /K:A /H:5 /DM /S ChangeLeftsideHint

Global gMediaInfoX32 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo_i386.dll"
Global gMediaInfoX64 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo.dll"
Global gMediaExifX32 = COMMANDER_PATH & "\Plugins\wlx\ExifToolView\exiftool.exe"

Global gDurationInfo = 0, gDurationBreak = false, gDurationBaloon = 1, gDurationTXT

Global gFilterAudio = ".aac .ac3 .aif .aiff .aifc .afc .ape .au .snd .cda .dsf .dts .dtswav .dtshd .dtsma .eac3 .flac .fla .m1a .m2a .mka .mpa .mp1 .mp2 .mp3 .mp4 .m4a .m4b .m4r .mod .mpc .mp+ .mpp .oga .ogx .ogg .ra .spx .opus .qoa .svx .8svx .tak .tta .wav .wave .w64 .bwf .rf64 .wma .wv"

Global gFilterVideo = ".avi .wmv .wmp .wm .asf .mpg .mpeg .mpe .m1v .m2v .mpv2 .mp2v .ts .tp .tpr .trp .vob .ifo .ogm .ogv .mp4 .m4v .m4p .m4b .3gp .3gpp .3g2 .3gp2 .mkv .rm .ram .rmvb .rpm .flv .swf .mov .qt .amr .nsv .dpg .m2ts .m2t .mts .dvr-ms .k3g .skm .evo .nsr .amv .divx .webm .wtv .f4v .mxf"

Global gBTipWndProc, gBTipWnd = Map(), gBTip = 0
Global gBText = Buffer(1024*4),  gBTool = Buffer(auX64 ? 56 : 40)
Global gBTipX, gBTipY
Global gBTipWP = Callback("BTipWndProc", "hwnd;uint;wparam;lparam")

Func Duration(lParam)
    If gDurationInfo > 0 Then
       gDurationBreak = true
       Sleep(250)
       Return
    EndIf
    If gDurationBaloon Then
       gBTip = CreateBaloonTip("MediaInfo", 1, 200)
       If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")       
    EndIf   
    RunThread DurationInfo
EndFunc

Func DurationInfo()
    Local T1 = GetUptime(), T2 = T1
    Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)    
    Local bCtrl = IsPressed(0x11), bShift = IsPressed(0x10), bAlt = IsPressed(0x12)
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
    Static sExt = gFilterAudio & " " & gFilterVideo
    If Not bAlt Then
       If hLib = 0 Then 
          ShowMediaHint("Error LoadLibrary " & sLib)
          Return 
       EndIf
       Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
       Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
       Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
       Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
       Local hMI = DllCall(pNew, "Ptr")
       If hMI = 0 Then 
          ShowMediaHint("MediaInfo.dll couldn't create new object")
          Return
       Endif
    Else     
       Local obj = Plugin("TCMediaInfo")
       If ERROR <> 0 Then
          ShowMediaHint("TCMediaInfo.wdx plugin error " & ERROR)
          Return
       Endif
    EndIf
    Local sDuration
    Local aSel = List()
          aSel.Text = GetSelectedItems(3, 0)       
    Local sPath = RequestCopyDataInfo("SP")    
    Local sName = RequestCopyDataInfo("SN")        
    Local sFile = sPath & sName
    If aSel.Count = 0 Then
       If Not FileExist(sFile) Then 
          ShowMediaHint("Файл не существует " & sFile)
          Free(aSel)
          If bAlt Then Free(obj)
          Return
       Endif
    EndIf       
    If aSel.Count = 0 And Not StrPos(FileGetAttr(sFile), "D") Then
       Free(aSel)
       If bAlt Then
          obj.FileName = sFile     
          sDuration = obj.GetValue(0)	# duration
          Free(obj)
       Else
          If DllCall(pOpen, "Ptr", hMI, "Wstr", sFile, "Uint") <> 1 Then
             Return ShowMediaHint("MediaInfo.dll coudn't open file " &  sFile)                            
          EndIf
          sDuration = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                                    "Wstr", "Duration/String3", "Int", 1, "Int", 0, "Wstr")
       EndIf   
       Return ShowMediaHint("Файл: " & sName & auCRLF & "Длительность: " & sDuration, 1) 
    Endif
    gDurationInfo = 1    
    gDurationBreak = false
    ShowMediaHint("Загрузка", 1)    
    Local i, j, valid = 0
    Local dirs = 0, files = 0, errs = 0, item = 0, aFiles = List(), seconds = 0, b_Hint = 0
    Local depth = (bCtrl ? 1 : 0), ms = 0, vc, ac
    bExtLog = false
    # загрузка файлов в массив    
    If aSel.Count > 0 Then
       For j = 0 To aSel.Count - 1
          sFile = sPath & aSel[j]
          If FileExist(sFile) Then 
             valid += 1
             aFiles.Add(sFile)
             If StrPos(FileGetAttr(sFile), "D") Then 
                If ListMediaFiles(sFile, aFiles, depth) > 0 Then aFiles.Count = 0
             EndIf   
          EndIf   
       Next
       sName = aSel.Count & "/" & valid
    Else
       aFiles.Add(sFile)
       ListMediaFiles(sFile, aFiles, depth)
    EndIf
    Free(aSel)
    If aFiles.Count > 1 Then
       ShowMediaHint("Depth: " & depth & auCRLF & _
                     "Filter: " & (Not bShift ? "Yes" : "No") & auCRLF & _
                     (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                     "Элементов: " & aFiles.Count & auCRLF & _
                     "Подсчёт времени...", 1)
    EndIf
    T2 = GetUptime()
    DurationLogString("Duration.Name:" & sName)    
    DurationLogString("Duration.Items:" & aFiles.Count)
    For i = 0 To aFiles.Count - 1
        If bExtLog Then DurationLogString("Duration.File:" & aFiles[i])
        If StrPos(FileGetAttr(aFiles[i]), "D") Then
           dirs += 1
           If bExtLog Then DurationLogString("Duration.Directory:" & aFiles[i])
           Continue 
        EndIf
        item += 1
        If bAlt Then
           obj.FileName = aFiles[i]
           ms = obj.GetValue(0,3)	# duration -> milliseconds
        Else
           ext = FileGetExt(aFiles[i])
           If Not bShift Then
              If Not StrPos(sExt, '.' & ext) Then 
                 DurationLogString("Duration.Filter:" & aFiles[i])
                 Continue
              EndIf
           EndIf
           If DllCall(pOpen, "Ptr", hMI, "Wstr", aFiles[i], "Uint") <> 1 Then
              errs += 1
              DurationLogString("Duration.Error:" & aFiles[i])
              Continue        
           EndIf
           vc = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                              "Wstr", "VideoCount", "Int", 1, "Int", 0, "Wstr")
           ac = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                              "Wstr", "AudioCount", "Int", 1, "Int", 0, "Wstr")
           If vc = "" And ac = "" Then
              DurationLogString("Duration.Warning:" & aFiles[i])
              Continue
           EndIf
           ms = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                              "Wstr", "Duration", "Int", 1, "Int", 0, "Wstr")
        EndIf
        If ms > 0 Then
           seconds += ms
           files += 1
        Else
           DurationLogString("Duration.Empty:" & aFiles[i])
        EndIf
        If gDurationBreak = true Or (IsPressed (0x11) And IsPressed (0x1B)) Then
           ShowMediaHint("Операция прервана", 1)
           Sleep(500)
           If gDurationBaloon Then
              Static buf = Buffer(160)
              buf.Zero()
              buf.SetStr("Прервано" & Chr(0))
              SendMessage(gBTip, 1057, 3, buf.ptr)              
           EndIf   
           Break
        EndIf
        If Round(GetUptime() - T2, 0) > 500 Then
           ShowMediaHint("Depth: " & depth & auCRLF & _
                         "Filter: " & (Not bShift ? "Yes" : "No") & auCRLF & _
                         (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                         "Элементов: " & aFiles.Count & auCRLF & _
                         "Обработка: " & i & " из " & aFiles.Count, 1)
           T2 = GetUptime()
         EndIf
    Next    
    If bAlt Then Free(obj)
    If Not bAlt And hMI <> 0 Then DllCall(pDel, "Ptr", hMI)
    gDurationInfo = 0    
    gDurationBreak = false
    seconds = Floor(seconds / 1000)
    Local day = Floor(seconds / 86400)
    Local hour = Floor((seconds - (day * 86400)) / 3600)
    Local min = Floor(((seconds - (day * 86400)) - (hour * 3600)) / 60)
    Local sec = seconds - (day * 86400 + hour * 3600 + min * 60)
    Local total = StrFormat("%02d:%02d:%02d:%02d",day,hour,min,sec)
    Local tl = Round(GetUptime() - T1, 0) / 1000 
    Local txt = "Имя: " & sName & auCRLF & _
                "Каталогов: " & dirs & auCRLF & _    
                "Элементов: " & aFiles.Count & auCRLF & _
                "Обработано: " & files & " из " & item & auCRLF & _
                "Ошибки DLL: " & errs & auCRLF & _
                "Секунды: " & seconds & auCRLF & _
                "Минуты: " & Round(seconds / 60, 2) & auCRLF & _
                "Часы: " & Round(seconds / 3600, 2) & auCRLF & _
                "Сутки: " & Round(seconds / 86400, 2) & auCRLF & _             
                "Время: " & Chr(0x2211) & " "& total & auCRLF & _
                "Powered by " & (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
                "Время операции: " &  StrFormat("%.3f", tl) & " sec"
    DurationLogString(txt & auCRLF & auCRLF)
    Free(aFiles)
    ClipPut(txt)
    ShowMediaHint(txt, 1)
EndFunc

Func ListMediaFiles(sPath, ByRef aList, nDepth = 1)
    Local sFile, nAttr
    Local ffd = Buffer(604), bEsc = false
    Local hf = DllCall("FindFirstFileW", "wstr", sPath & "\*.*", "ptr", ffd.Ptr)
    If hf <> 0 then 
        While True 
            sFile = ffd.GetStr(44)         # cFileName
            nAttr = ffd.GetNum(0, "dword") # dwFileAttributes
            If BitAND(nAttr, 16) Then 
               If Not ((sFile = ".") Or (sFile = "..")) Then 
                  aList.Add(sPath & "\" & sFile)
                  If nDepth <> 1 Then
                     ListMediaFiles(sPath & "\" & sFile, aList, nDepth - 1)
                  EndIf   
               EndIf
            Else
               aList.Add(sPath & "\" & sFile)
            Endif     
            If DllCall("FindNextFileW", "handle", hf, "ptr", ffd.Ptr) = 0 Then Break
            If IsPressed (0x1B) Then
                bEsc = true
                Break
            EndIf    
        Wend
        DllCall("FindClose", "handle", hf)
    Endif 
    Free(ffd)
    Return bEsc
EndFunc

Func DurationLogString(LogString)
    gDurationTXT &= LogString & auCRLF
EndFunc

Func ShowMediaHint(MediaHint, Persist = false)
    # удаление подсказки тотала
    If gDurationBaloon And gBTip > 0 Then
       Local hTip = WinFind(0, "TToolTip")
       If hTip > 0 Then SendMessage(hTip, 0x0010, 0, 0)
       UpdateBaloonTip(gBTip, MediaHint)
       Return
    EndIf
    SetHintParam("ShowHint", "Font", 11, "Arial")
    #SetHintParam("ShowHint", "BackColor", 0x000000)
    #SetHintParam("ShowHint", "Text", 0xFFFFFF)
    SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
    SetHintParam("ShowHint", "DarkText", 0xFFFFFF)
    If Persist Then
       ShowHint(MediaHint)    
    Else    
       ShowHint(MediaHint, "", "", 3000, 1)
    EndIf   
    Sleep(10)
    SetHintParam("ShowHint", "Reload")  
EndFunc

Func MediaInfoTest(lParam)
    Local sFile = RequestCopyDataInfo("SP") & RequestCopyDataInfo("SN")
    If Not FileExist(sFile) Then 
       ShowHint("Файл не существует " & sFile)
       Return 
    Endif    
    If StrPos(FileGetAttr(sFile), "D") Then
       ShowHint("Каталог " & sFile)
       Return 
    Endif
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
    If hLib = 0 Then 
       ShowHint("Error LoadLibrary " & sLib)
       Return
    EndIf
    Static sPath = FileGetDir(sLib)
    Static sLang ="file://" & sPath & "\ru.csv"
    Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
    Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
    Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
    Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
    Static pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
    Static pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")    
    Local hMI = DllCall(pNew, "Ptr")
    If hMI = 0 Then 
       ShowHint("MediaInfo.dll couldn't create new object")
       Return 
    Endif
    If DllCall(pOpen, 'ptr', hMI, "wstr", sFile, "uint") <> 1 Then
       DllCall(pDel, "Ptr", hMI)        
       Return ShowHint("MediaInfo.dll couldn't open file " &  sFile)
    EndIf
    Local sMI
    sMI &= "Duration: "
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Duration", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= "Video: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "VideoCount", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= "Audio: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "AudioCount", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= "Recorded: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Recorded_Date", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= "Cover: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover", "int", 1, "int", 0, "wstr") & auCRLF
    sMI &= "Cover Mime: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover_Mime", "int", 1, "int", 0, "wstr") & auCRLF 
    sMI &= "Track/Position: "    
    sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Track/Position", "int", 1, "int", 0, "wstr")
    If IsPressed(0x11) Then
       sMI = ""
       DllCall(pOpt, "Ptr", hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")
       DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", sLang, "Wstr")       
       DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", "Inform", "Wstr")       
       Local lst = List()
       lst.Text = DllCall(pInfo, "Ptr", hMI, "Uint", 0, "Wstr")
       For line in lst
          sMI &= FixSpaces(line) & auCRLF
       Next
       Free(lst)
    EndIf
    DllCall(pDel, "Ptr", hMI)
    If gDurationBaloon Then
       gBTip = CreateBaloonTip("MediaInfo", 1, 300)
       If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")
    EndIf
    If StrTrim(sMI) = "" Then sMI = "нет данных"
    ShowMediaHint(sMI)
EndFunc

Func CreateBaloonTip(TipTitle, TipIcon, TipWidth)
    Static TTM_TRACKACTIVATE   = 1041, _
           TTM_TRACKPOSITION   = 1042, _
           TTM_SETMAXTIPWIDTH  = 1048, _
           TTM_SETTITLE        = 1057, _
           TTM_ADDTOOL         = 1074
    Local hTip
    hTip = DllCall("CreateWindowExW", _
                 "dword", 8, _
                 "wstr", "tooltips_class32", _
                 "wstr", "", _
                 "dword", 0x00000c0, _
                 "int", 0, "int", 0, "int", 0, "int", 0, _
                 "handle", AUTORUN_TCHANDLE, _
                 "handle", 0, "handle", 0, "ptr", 0, "handle")
    If hTip = 0 Then Return 0
    MouseGetPos("gBTipX","gBTipY")
    #gBTipWnd.Set(hTip, MakeInt(gBTipX, gBTipY, 2))
    gBTipWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                           "hwnd", hTip, "int", -4, "long_ptr", gBTipWP.Ptr, "ptr")
    Local buf = Buffer(160)
    buf.Zero()
    buf.SetStr(TipTitle & Chr(0))
    SendMessage(hTip, TTM_SETTITLE, TipIcon, buf.ptr)
    gBText.Zero()
    gBText.SetStr("Инициализация" & Chr(0))    
    gBTool.Zero()                              # TTTOOLINFO
    If auX64 Then
       gBTool.SetNum(0, "uint", gBTool.size, _
                        "uint", 0x00a0, _
                        "hwnd", AUTORUN_TCHANDLE, _
                        "uint_ptr", 0)
       gBTool.SetNum(48, "ptr", gBText.ptr)    
    Else
       gBTool.SetNum(0, "uint", gBTool.size, _
                        "uint", 0x00a0, _
                        "hwnd", AUTORUN_TCHANDLE, _
                        "uint_ptr", 0, _
                        "long", 0, _
                        "long", 0, _
                        "long", 0, _
                        "long", 0, _
                        "ptr", 0, _
                        "ptr", gBText.ptr)
    EndIf
    SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, TipWidth)
    SendMessage(hTip, TTM_ADDTOOL, 0, gBTool.ptr)
    SendMessage(hTip, TTM_TRACKACTIVATE, 1, gBTool.ptr)
    SendMessage(hTip, TTM_TRACKPOSITION, 0, MakeInt(gBTipX, gBTipY, 0))
    Free(buf)
    Return hTip 
EndFunc

Func UpdateBaloonTip(hTip, TipText)
    Static TTM_UPDATETIPTEXT = 1081
    gBText.Zero()
    gBText.SetStr(TipText & Chr(0)) 
    SendMessage(gBTip, TTM_UPDATETIPTEXT, 0, gBTool.ptr)
EndFunc

Func BTipWndProcTest(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202, _
           TTM_TRACKPOSITION = 1042
    Static tx, ty       
    Switch uMsg
       Case WM_LBUTTONDOWN 
          If IsDrag = 0 Then
             MouseGetPos("tx","ty")
             If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(ty, tx, 2)) Then                
                IsDrag = 1
                DllCall("SetCapture", "hwnd", hWnd, "hwnd")     
             EndIf
          EndIf         
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             WinGetPos("gBTipX", "gBTipY", "", "", hWnd)                                         
             IsDrag = 0
             DllCall("ReleaseCapture") 
          Else
             DllCall("DestroyWindow", "handle", hWnd)                      
          EndIf  
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             MouseGetPos("x","y")             
             SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))    
          EndIf       
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func BTipWndProc(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           WM_CREATE       = 0x0001, _
           WM_DESTROY      = 0x0002, _
           WM_SHOWWINDOW   = 0x0018, _     
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202, _
           WM_RBUTTONUP    = 0x0205, _           
           TTM_TRACKACTIVATE = 1041, _
           TTM_TRACKPOSITION = 1042
    Static SM_CXDRAG  = 68, _
           SM_CYDRAG  = 69, _
           DragWidth  = GetSystemMetrics(SM_CXDRAG), _
           DragHeight = GetSystemMetrics(SM_CYDRAG), _
           StartX     = 0, _
           StartY     = 0
    Local x, y
    Static tx, ty, buf = Buffer(8)
    Switch uMsg
       Case WM_SHOWWINDOW
          If wParam = 0 Then DllCall("DestroyWindow", "handle", hWnd)
       Case WM_DESTROY
          If gDurationInfo Then
             gDurationBreak = true
             MsgBox("Операция отменена")
             Return 0
          EndIf
       Case WM_LBUTTONDOWN
          If IsDrag = 0 Then
             buf.Zero()
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             StartX = x
             StartY = y
             buf.SetNum(0, "int", x, "int", y)
             DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
             tx = buf.GetNum(0)
             ty = buf.GetNum(4)
             IsDrag = 1
             DllCall("SetCapture", "hwnd", hWnd, "hwnd")
          EndIf          
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             WinGetPos("gBTipX", "gBTipY", "", "", hWnd)
             IsDrag = 0
             DllCall("ReleaseCapture")
          Else   
             DllCall("DestroyWindow", "handle", hWnd)             
          EndIf  
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             If Abs(x - startX) > DragWidth Or Abs(y - startY) > DragHeight Then
                buf.Zero()             
                buf.SetNum(0, "int", x, "int", y)
                DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
                x = buf.GetNum(0)
                y = buf.GetNum(4)                 
                SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))
             EndIf   
          EndIf
       Case WM_RBUTTONUP
            BTipShowMenu(hWnd)
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc

Func BTipShowMenu(hWnd)
    ShowPopupMenu /D /F /I:0 "BTipCreateMenu"
EndFunc

Func BTipCreateMenu()
    Local txt
    txt &= 'MENUITEM "Лог операций", em_aucmd ' & (gDurationTXT <> "" ?  "" : "/D") & ' -1 DurationText' & auCRLF
    Return txt
EndFunc

Func DurationText()
    Local sLogFile = TEMP & "\duration.txt"
    FileWrite(sLogFile, gDurationTXT)
    ShellExec(sLogFile)
EndFunc

Func MediaHint(FileName, FieldIndex, UnitIndex)
    If FieldIndex > gHintLines Then Return
    If StrPos(FileGetAttr(FileName), "D") Then Return "" 
    Local bCaps = DllCall("GetKeyState", "int", 0x14, "short")
    Local bCtrl = BitAND(bCaps, 1), bShift = IsPressed(0x10)
    
    If Not bCtrl then bCtrl = IsPressed (0x11)
    If gHintCaps And Not bCtrl Then Return
    
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "Wstr", sLib, "Ptr")
    
    Static sPath = FileGetDir(sLib) & "\"
    Static sLang ="file://" & sPath & "ru.csv", _
           sHint ="file://" & sPath & "hint.txt", _
           sSize ="file://" & sPath & "size.txt"
                   
    Static bLang = true, nWait = 0, _           
           pNew, pOpen, pDel, pOpt, pInfo
           
    If hLib = 0 And FieldIndex > 1 Then Return
    
    If FieldIndex = 1 Then

       If hLib = 0 Then Return "Error LoadLibrary " & sLib
       
       Idx = 0
       pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
       pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
       pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
       pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
       pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")
       nWait = 0
       bLang = true
       sMode = "Inform"
       If gHintWait > 0 Then Sleep(gHintWait)
       
       Local x, y, w, nCase = 0
       Local hWnd = RequestInfo(ItemAtCursor("panel"))
       WinGetPos("", "", "w", "", hWnd)
       If w > 0 Then
          MouseGetPos("x","y")
          Static buf = Buffer(8)	# POINT
          buf.Zero()
          buf.SetNum(0, "long", x, "long", y)
          DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
          x = buf.GetNum(0)
          Switch Round(x/w*100,0)
             Case 0 To gHintLayout[0]-1
                 nCase = 0
             Case gHintLayout[0] To gHintLayout[0]+gHintLayout[1]-1
                 nCase = 1             
             Case 100-gHintLayout[2] To 100
                 nCase = 2            
          EndSwitch
          nWait = gHintSleep[nCase]
          sMode = gHintContent[nCase]        
       EndIf
             
       If nWait > 0 Then Sleep(nWait)       
       If sMode = "" Then
          gHintPipe = ""
          Return
       ElseIf sMode <> "Inform" Then
          bLang = false
          sMode ="file://" & sPath & sMode
       EndIf
       
       Local hMI = DllCall(pNew, "Ptr")
       If hMI = 0 Then Return "MediaInfo.dll couldn't create new object"
              
       If DllCall(pOpen, 'Ptr', hMI, "Wstr", FileName, "Uint") <> 1 Then
          DllCall(pDel, "Ptr", hMI)        
          Return "MediaInfo.dll couldn't open file " &  FileName
       EndIf       
       
       If bShift Then 
          DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "1", "Wstr")
       Else
          DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")       
       EndIf
       
       DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", sMode, "Wstr")              
       DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", (Not bLang ? "" : sLang), "Wstr")
       
       gHintPipe = DllCall(pInfo, 'Ptr', hMI, "Uint", 0, "Wstr")
       #{
       If StrPos(sMode, "hint.txt") Then
          gHintPipe = StrReplace(gHintPipe, "DTS HD Master Audio", "DTS-HD MA")
          gHintPipe = StrReplace(gHintPipe, "Dolby Digital", "DD")           
       EndIf       
       #}
       If Not bLang Then gHintPipe = StrReplace(gHintPipe, Chr(32), Chr(160))       
       
       DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", "", "Wstr")
       DllCall(pDel, "Ptr", hMI)
    Endif
    If Not bLang Then Return StrPart(gHintPipe, auCRLF, FieldIndex)
    Return FixSpaces(StrPart(gHintPipe, auCRLF, FieldIndex))
EndFunc

Func FixSpaces(String)
    Local a, b
    If Not StrPos(String, ":") Then Return String    
    a = StrPart(String, ":", 1)
    b = StrPart(String, ":", 2) & StrPart(String, ":", 3)    
    Return StrTrim(a) & ":  " & FixCodePage(StrTrim(b)) 
EndFunc

Func FixCodePage(String)
   Local bUsedRepl
   # iso-8859-1 = 28591
   DllCall("WideCharToMultiByte", _
           "uint", 28591, _
           "dword", 0, _
           "wstr", String, _
           "int", -1, _
           "ptr", 0, _
           "int", 0, _
           "ptr", 0, _
           "bool*", @bUsedRepl)
    If bUsedRepl Then Return String
    Local nSize = StrLen(String)
    Local buf = Buffer(nSize)
    buf.Zero()
    DllCall("WideCharToMultiByte", _
            "uint", 28591, _
            "dword", 0, _
            "wstr", String, _
            "int", -1, _
            "ptr", buf.ptr, _
            "int", nSize, _
            "ptr", 0, _
            "ptr", 0)
    Local fixed = buf.GetStr(0, nSize, "ANSI")       
    Free(buf)
    Return fixed
EndFunc

Func FixCodePageEx(String)
   Local bUsedRepl
   # iso-8859-1 = 28591
   DllCall("WideCharToMultiByte", _
           "uint", 28591, _
           "dword", 0, _
           "wstr", String, _
           "int", -1, _
           "ptr", 0, _
           "int", 0, _
           "ptr", 0, _
           "bool*", @bUsedRepl)
    If bUsedRepl Then Return String
    Local nSize = StrLen(String)
    Local buf = Buffer(nSize)
    buf.Zero()
    buf.SetStr(String, 0, nSize, "CP:28591")
    Local fixed = buf.GetStr(0, nSize, "ANSI")       
    Free(buf)
    Return fixed
EndFunc

Func ShowPipeEx(lParam, nPage)
    Local sPipe, nLines = gHintLines
    Local aPipe = List(), j, nSect = 0
    Local nEnd = nPage*nLines, nStart = nEnd - nLines
    If gHintClipb Then ClipPut(gHintPipe)    
    aPipe.Text = gHintPipe
    For j = 0 To aPipe.Count - 1
        If aPipe[j] = "" Then nSect += 1
        If (j + 1) >= nStart And (j + 1) <= nEnd Then 
           sPipe &= StrLeft(FixSpaces(aPipe[j]),84) & auCRLF
        EndIf
    Next
    Free(aPipe)
    If sPipe = "" Then sPipe = "Out of range"
    ShowHint(StrTrim(sPipe))
    #Return -1
EndFunc

Func ChangeLeftsideHint()
    Static init = gHintContent[0]
    If gHintContent[0] = init Then    
       gHintContent[0] = gHintShift
    Else
       gHintContent[0] = init
    EndIf
    SetHintParam("ShowHint", "Font", 15, "Arial")
    SetHintParam("ShowHint", "BackColor", 0xFF0000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint("Left side is " & gHintContent[0], "", "", 1000, 1)
    Sleep(50)            
    SetHintParam("ShowHint", "Reload")    
EndFunc

Func SetHintFields()
    Local i, sHint
    Static c = 0, aHints = List("MediaHint", "ExifHint", "JoinHint")
    c += 1
    If c > 2 Then c = 0
    sHint = aHints[c]
    For i = 1 to 60
        SetFieldsParam("Func", "C" & i, sHint)
    Next
    SetHintParam("ShowHint", "Font", 15, "Arial")
    SetHintParam("ShowHint", "BackColor", 0xFF0000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint("Поля подсказки " & sHint, 0, 0, 1000, 1)
    WinAlign(LAST_HINT_WINDOW)    
    Sleep(100)
    SetHintParam("ShowHint", "Reload")
EndFunc

Func ExifHint(FileName, FieldIndex, UnitIndex)
    If FieldIndex > gHintLines Then Return
    If StrPos(FileGetAttr(FileName), "D") Then Return

    Local bCtrl = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)    
    If Not bCtrl then bCtrl = IsPressed (0x11)
    If gHintCaps And Not bCtrl Then Return
          
    If FieldIndex = 1 Then
       ProcessExecGetOutput gHintPipe %gMediaExifX32% ' -G -S "%FileName%"'
    Endif     
    Return StrPart(gHintPipe, auLF, FieldIndex)
EndFunc
[/cut]
К сожалению, полностью автономным этот модуль сделать нельзя, т.к. в файле основной конфигурации должны быть прописаны поля и объявлены переменные:
[cut="autorun.cfg"]

Код: Выделить всё

Pragma AutorunPluginFields "C1:::MediaHint" "C2:::MediaHint" "C3:::MediaHint" "C4:::MediaHint" "C5:::MediaHint" "C6:::MediaHint" "C7:::MediaHint" "C8:::MediaHint" "C9:::MediaHint" "C10:::MediaHint" "C11:::MediaHint" "C12:::MediaHint" "C13:::MediaHint" "C14:::MediaHint" "C15:::MediaHint" "C16:::MediaHint" "C17:::MediaHint" "C18:::MediaHint" "C19:::MediaHint" "C20:::MediaHint" "C21:::MediaHint" "C22:::MediaHint" "C23:::MediaHint" "C24:::MediaHint" "C25:::MediaHint" "C26:::MediaHint" "C27:::MediaHint" "C28:::MediaHint" "C29:::MediaHint" "C30:::MediaHint" "C31:::MediaHint" "C32:::MediaHint" "C33:::MediaHint" "C34:::MediaHint" "C35:::MediaHint" "C36:::MediaHint" "C37:::MediaHint" "C38:::MediaHint" "C39:::MediaHint" "C40:::MediaHint" "C41:::MediaHint" "C42:::MediaHint" "C43:::MediaHint" "C44:::MediaHint" "C45:::MediaHint" "C46:::MediaHint" "C47:::MediaHint" "C48:::MediaHint" "C49:::MediaHint" "C50:::MediaHint" "C51:::MediaHint" "C52:::MediaHint" "C53:::MediaHint" "C55:::MediaHint" "C55:::MediaHint" "C56:::MediaHint" "C57:::MediaHint" "C58:::MediaHint" "C59:::MediaHint" "C60:::MediaHint"

Global gHintPipe     =   "", _
       gHintClipb    =   true, _
       gHintLines    =   60, _
       gHintWait     =   0, _      
       gHintShift    =   "duration.txt", _
       gHintCaps     =   true
       
Global gHintLayout   =   List(10, 75, 15), _
       gHintContent  =   List("size.txt", "Inform", "hint.txt"), _
       gHintSleep    =   List(0, 0, 0)
#{
       gHintCaps     =   false       
       gHintLayout   =   List(15, 70, 15)       
       gHintContent  =   List("Inform", "", "duration.txt")       
       
       gHintLayout   =   List(10, 80, 10)       
       gHintContent  =   List("size.txt", "hint.txt", "Inform")       
       gHintSleep    =   List(0, 0, 0)
#}

If SYSINFO_DESKTOPHEIGHT < 1080 Then gHintLines = 50
If SYSINFO_DESKTOPHEIGHT < 720 Then gHintLines = 40

Pragma Include %COMMANDER_PATH%\Ini\Scripts\MediaInfo.aucfg
[/cut]
С полями понятно: они должны быть прописаны первой строкой конфигурации, как требует Autorun. Глобальные переменные желательно объявлять следом или как можно скорее, поскольку при старте ТС плагин начинает вызывать функцию MediaHint, которая использует эти переменные для своей работы. Но если эти переменные еще не инициализированны (например, если подключено несколько модулей), то при старте ТС возникнет соответствующая ошибка.

Переменные отвечают за параметры подсказки - на сколько процентов делить панель и какие шаблоны для этого использовать. Подробнее здесь.

Шаблоны остались теми же. Я только добавил к size.txt пару дополнительных полей:
[cut="size.txt"]General;Name: %FileName%.%FileExtension%\r\nSize: %FileSize/String4%\r\nGeneral: [%StreamSize/String%]\r\n

Video;Video #%StreamKindID%: [%StreamSize/String%]\r\n
Audio;Audio #%StreamKindID%: %StreamSize/String%[ - %Language/String%][ | %Title%]\r\n[/cut]
Но можно сделать и свои шаблоны в зависимости от задач и целей.
Комбинация Alt+F12 переключает все поля подсказки. Т.е. на лету происходит переключение между этим:
[cut]Pragma AutorunPluginFields "C1:::MediaHint" "C2:::MediaHint" "C3:::MediaHint" "C4:::MediaHint" "C5:::MediaHint" "C6:::MediaHint" "C7:::MediaHint" "C8:::MediaHint" "C9:::MediaHint" "C10:::MediaHint" "C11:::MediaHint" "C12:::MediaHint" "C13:::MediaHint" "C14:::MediaHint" "C15:::MediaHint" "C16:::MediaHint" "C17:::MediaHint" "C18:::MediaHint" "C19:::MediaHint" "C20:::MediaHint" "C21:::MediaHint" "C22:::MediaHint" "C23:::MediaHint" "C24:::MediaHint" "C25:::MediaHint" "C26:::MediaHint" "C27:::MediaHint" "C28:::MediaHint" "C29:::MediaHint" "C30:::MediaHint" "C31:::MediaHint" "C32:::MediaHint" "C33:::MediaHint" "C34:::MediaHint" "C35:::MediaHint" "C36:::MediaHint" "C37:::MediaHint" "C38:::MediaHint" "C39:::MediaHint" "C40:::MediaHint" "C41:::MediaHint" "C42:::MediaHint" "C43:::MediaHint" "C44:::MediaHint" "C45:::MediaHint" "C46:::MediaHint" "C47:::MediaHint" "C48:::MediaHint" "C49:::MediaHint" "C50:::MediaHint" "C51:::MediaHint" "C52:::MediaHint" "C53:::MediaHint" "C55:::MediaHint" "C55:::MediaHint" "C56:::MediaHint" "C57:::MediaHint" "C58:::MediaHint" "C59:::MediaHint" "C60:::MediaHint"[/cut]
И этим:
[cut]Pragma AutorunPluginFields "C1:::JoinHint" "C2:::JoinHint" "C3:::JoinHint" "C4:::JoinHint" "C5:::JoinHint" "C6:::JoinHint" "C7:::JoinHint" "C8:::JoinHint" "C9:::JoinHint" "C10:::JoinHint" "C11:::JoinHint" "C12:::JoinHint" "C13:::JoinHint" "C14:::JoinHint" "C15:::JoinHint" "C16:::JoinHint" "C17:::JoinHint" "C18:::JoinHint" "C19:::JoinHint" "C20:::JoinHint" "C21:::JoinHint" "C22:::JoinHint" "C23:::JoinHint" "C24:::JoinHint" "C25:::JoinHint" "C26:::JoinHint" "C27:::JoinHint" "C28:::JoinHint" "C29:::JoinHint" "C30:::JoinHint" "C31:::JoinHint" "C32:::JoinHint" "C33:::JoinHint" "C34:::JoinHint" "C35:::JoinHint" "C36:::JoinHint" "C37:::JoinHint" "C38:::JoinHint" "C39:::JoinHint" "C40:::JoinHint" "C41:::JoinHint" "C42:::JoinHint" "C43:::JoinHint" "C44:::JoinHint" "C45:::JoinHint" "C46:::JoinHint" "C47:::JoinHint" "C48:::JoinHint" "C49:::JoinHint" "C50:::JoinHint" "C51:::JoinHint" "C52:::JoinHint" "C53:::JoinHint" "C55:::JoinHint" "C55:::JoinHint" "C56:::JoinHint" "C57:::JoinHint" "C58:::JoinHint" "C59:::JoinHint" "C60:::JoinHint" [/cut]
Меняется функция полей данных. В модуле присутствует функция ExifHint, которая выводит сведения из exiftool.exe, нужно только указать путь в заголовке, как и путь к библиотекам MediaInfo. При возможности можно добавить другие функции для вывода данных в поля Autorun, чтобы переключать их налету, расширяя функционал.

A55555
Если будете подключать модуль, не забудьте заменить первую строку - имя функции теперь другое.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Как-то я увлёкся описанием MediaHint, что совсем забыл про функции Duration и MediaInfoTest. Кнопка на Duration теперь выглядит так:

[cut]TOTALCMD#BAR#DATA
71000

%COMMANDER_PATH%\Icons\MediaInfo.ico
Подсчёт времени воспроизведения|Alt - Использовать TCMediaInfo.wdx|Ctrl - Глубина каталога = 1|Shift - Отключить фильтр расширений


-1[/cut]
CapsLock больше нет. Shift позволяет отключить фильтр расширений, указанных в заголовке модуля. По умолчанию фильтр включен, т.к. он ускоряет операцию подсчета, поскольку MediaInfo не приходится открывать каждый файл в каталоге. Но бывают случаи, когда нужно обработать все файлы. Если файл не содержит сведений о времени воспроизведения, в лог заносится "Empty".

Иногда при отключенном фильтре текстовые файлы субтитров могут возвращать информацию о времени воспроизведения. Не уверен, что это правильно, хотя это, видимо, кому-то требуется. В режиме MediaInfo.dll такие файлы в расчет не принимаются, в лог записывается "Warning". Но если по какой-то причине нужно посчитать длительность таких файлов, можно использовать режим плагина TCMediaInfo.wdx через запуск с Alt.

Лог сохраняется во временный каталог, но только при его открытии, во время следующей сессии он перезаписывается.

Кнопка MediaInfoTest только для теста, но может выводить информацию в режиме "Inform".
[cut]TOTALCMD#BAR#DATA
71010

%COMMANDER_PATH%\Icons\MediaInfo.ico
MediaInfoTest|Ctrl - Inform

1
-1[/cut]
Если нужно сделать подсказку с выборочными полями из MediaInfo.dll, можно использовать эту кнопку как заготовку.

Подсказку в стиле BaloonTip можно использовать в других целях, но без внесения изменений не обойтись. Отдельная кнопка для теста кода и его адаптации, если кому-то вдруг потребуется:
[cut]TOTALCMD#BAR#DATA
60031

%COMMANDER_EXE%
Baloon ToolTip


-1
[/cut]
[cut]

Код: Выделить всё

RegisterCommand 60031 TestToolTip

Global gTTipWndProc, aTTipWnd = List()
Global gTTipWP = Callback("TTipWndProc", "hwnd;uint;wparam;lparam")

Func TestToolTip()
    Static WM_SETFONT = 0x30, _
           TTM_TRACKACTIVATE   = 1041, _
           TTM_TRACKPOSITION   = 1042, _
           TTM_SETTIPBKCOLOR   = 1043, _
           TTM_SETTIPTEXTCOLOR = 1044, _
           TTM_SETMAXTIPWIDTH  = 1048, _
           TTM_SETMARGIN       = 1050, _
           TTM_SETTITLE        = 1057, _
           TTM_ADDTOOL         = 1074, _
           TTM_UPDATETIPTEXT   = 1081        
    Local hTip = DllCall("CreateWindowExW", _
                   "dword", 8, _
                   "wstr", "tooltips_class32", _
                   "wstr", "", _
                   "dword", 0x00000c0, _
                   "int", 0, "int", 0, "int", 0, "int", 0, _
                   "handle", AUTORUN_TCHANDLE, _
                   "handle", 0, "handle", 0, "ptr", 0, "handle")    
    If hTip = 0 Then Return
    Global gTX, gTY
    MouseGetPos("gTX","gTY")
    aTTipWnd.Add(hTip)
    gTTipWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                           "hwnd", hTip, "int", -4, "long_ptr", gTTipWP.Ptr, "ptr")    
    Local sTitle = "Title"
    Local sText = "Buffer text"
    Local txt = Buffer(255)
    txt.Zero()    
    txt.SetStr(sTitle & Chr(0))
    Local hIco = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
    SendMessage(hTip, TTM_SETTITLE, (IsPressed(0x11) ? hIco : 1), txt.ptr)
    txt.Zero()
    txt.SetStr(sText & Chr(0))
    Local buf = Buffer(auX64 ? 56 : 40)		# TTTOOLINFOW
    buf.Zero()
    If auX64 Then
       buf.SetNum(0, "uint", buf.size, _
                     "uint", 0x00a0, _
                     "hwnd", 0, _
                     "uint_ptr", 0)
       buf.SetNum(48, "ptr", txt.ptr)
    Else
       buf.SetNum(0, "uint", buf.size, _
                     "uint", 0x00a0, _
                     "hwnd", 0, _
                     "uint_ptr", 0, _
                     "long", 0, _
                     "long", 0, _
                     "long", 0, _
                     "long", 0, _
                     "ptr", 0, _
                     "ptr", txt.ptr)
    EndIf
    SendMessage(hTip, TTM_ADDTOOL, 0, buf.ptr)    
    SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, 100)
    Local BkgColor = 0x000000FF
    SendMessage(hTip, TTM_SETTIPBKCOLOR, BkgColor, 0)
    SendMessage(hTip, TTM_TRACKACTIVATE, 1, buf.ptr)    
    SendMessage(hTip, TTM_TRACKPOSITION, 0, MakeInt(gTX, gTY, (auX64 ? 0 : 0)))
    Sleep(1000)
    sText = "Updating text"
    txt.Zero()    
    txt.SetStr(sText & Chr(0))    
    SendMessage(hTip, TTM_UPDATETIPTEXT, 0, buf.ptr)
    Sleep(1000)
    txt.Zero()
    txt.SetStr("Bigger parts of text" & Chr(0))    
    SendMessage(hTip, TTM_UPDATETIPTEXT, 0, buf.ptr)    
EndFunc

Func TTipWndProc(hWnd, uMsg, wParam, lParam)
    Static IsDrag = 0, _
           WM_CREATE       = 0x0001, _
           WM_DESTROY      = 0x0002, _
           WM_SHOWWINDOW   = 0x0018, _     
           MK_LBUTTON      = 0x0001, _
           WM_MOUSEMOVE    = 0x0200, _
           WM_LBUTTONDOWN  = 0x0201, _
           WM_LBUTTONUP    = 0x0202, _
           TTM_TRACKACTIVATE = 1041, _
           TTM_TRACKPOSITION = 1042
    Static SM_CXDRAG  = 68, _
           SM_CYDRAG  = 69, _
           DragWidth  = GetSystemMetrics(SM_CXDRAG), _
           DragHeight = GetSystemMetrics(SM_CYDRAG), _
           StartX     = 0, _
           StartY     = 0
    Local x, y
    Static tx, ty, buf = Buffer(8)
    Switch uMsg
       Case WM_SHOWWINDOW
          If wParam = 0 Then DllCall("DestroyWindow", "handle", hWnd)
       Case WM_DESTROY
       
       Case WM_LBUTTONDOWN
          If IsDrag = 0 Then
             buf.Zero()
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             StartX = x
             StartY = y
             buf.SetNum(0, "int", x, "int", y)
             DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
             tx = buf.GetNum(0)
             ty = buf.GetNum(4)
             IsDrag = 1
             DllCall("SetCapture", "hwnd", hWnd, "hwnd")
          EndIf          
       Case WM_LBUTTONUP
          If IsDrag = 1 Then
             WinGetPos("gTX", "gTY", "", "", hWnd)
             IsDrag = 0
             DllCall("ReleaseCapture")
          EndIf  
       Case WM_MOUSEMOVE
          If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
             x = BitAND(lParam, 0xFFFF)
             y = BitAND(BitShift(lParam,16), 0xFFFF)
             If Abs(x - startX) > DragWidth Or Abs(y - startY) > DragHeight Then
                buf.Zero()             
                buf.SetNum(0, "int", x, "int", y)
                DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
                x = buf.GetNum(0)
                y = buf.GetNum(4)                 
                SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gTX+(x-tx), gTY+(y-ty), 0))
             EndIf   
          EndIf          
    EndSwitch
    Return DllCall("CallWindowProcW", _
                   "ptr", gTTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
[/cut]
[cut]Изображение[/cut]
P.s.

Эх маэстро маэстро... Ну почему нельзя было сразу так сделать? Сколько же драгоценных часов я потерял, пытаясь найти нужный для себя цвет фона :mrgreen:

[cut]Изображение[/cut]
Ответить