Страница 243 из 243

Добавлено: Чт окт 08, 2026 15:48
AkulaBig
Orion9
Прописал If StrPos(u, wrong) Then u = FixFFFD(u, a). Сразу посыпалась ошибки:
Изображение
Не на всех файлах. Возможно где были крякозябры. Надо тестить.
Но есть еще очень неприятный момент, который только сейчас увидел. Для MI функцию конвертации делал сансей. А сегодня увидел, как наша отображает тот тестовый файл:
MI с преобразованием от сансея
Изображение
ET с нашим преобразованием
Изображение
С тайм-аутом колонки не работают. Может сейчас у вас изменения. Потестю еще, но пока надо с крякозябрами разобраться.
А, посмотрел внимательно. Вы тайм-аут все с временными файлами используете. Это не рабочий вариант, с колонками не будет работать. Так что не буду тестить. Подсказка обязательно должна быть через потоки. Конечно я имею ввиду рабочий вариант совместной работы подсказки и колонок в сборке. Естественно ваши тестовые функции можно основывать хоть на чем.

Добавлено: Чт окт 08, 2026 18:16
Orion9
AkulaBig писал(а):Сразу посыпалась ошибки:
У себя такого не наблюдаю, скиньте файл, на котором возникает эта ошибка.

С кракозябрами тоже проблем не вижу, скрин с Таней Булановой выше как раз это показывает.

Добавлено: Чт окт 08, 2026 21:15
AkulaBig
Orion9
Файл с крякозябрами я выложил в том-же архиве, на который выше ссылку дал. А файлы с ошибкой не вижу смысла выкладывать. Посмотрел сейчас, не нашел где у вас начало кода, на который вы ссылаетесь. Можете выложить полный код, который вы используете? Пусть он даже с временными файлами, но полностью рабочий. А то вы пишите заменил то, заменил се. Смотри функции выше. Но я не смог найти начала.

Добавлено: Пт окт 09, 2026 12:03
Orion9
AkulaBig писал(а):Можете выложить полный код, который вы используете?
Полный код MediaInfo.aucfg

[cut]

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

Pragma IncludeOnce

# 71000-71099

RegisterCommand 71000 "Duration"
RegisterCommand 71010 "MediaInfoTest"

# Alt+F12
SetHotkeyAction /K:A /H:F12 SetHintFields

# Alt+1(..5)
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 LeftsideHintType

# Win+CapsLock
SetHotkeyAction /V:20 /K:W MediaHintType

# путь к библиотеке MediaInfo и утилите ExifTool
Global gMediaInfoX32 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo_i386.dll"
Global gMediaInfoX64 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo.dll"
Global gMediaExifX32 = COMMANDER_PATH & "\Tools\ExifTool\exiftool.exe"

# флаги запущенной операции, тип подсказки, лог операции
Global gDurationInfo = 0, gDurationBreak = false, gDurationBaloon = 1, gDurationLog = ""

# фильтр расширений для аудио файлов
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)
    
    # загрузка библиотеки MediaInfo в зависимости от рязрядности ТС
    Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
    Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
    
    # общий фильтр для медиа файлов    
    Static sExt = gFilterAudio & " " & gFilterVideo

    # модификатор Alt
    # выбор "движка" операции     
    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, extlog = false
    Local dirs = 0, files = 0, errs = 0, item = 0, aFiles = List()
    Local depth = (bCtrl ? 1 : 0), ms = 0, vc = "", ac = "", seconds = 0
        
    # загрузка файлов в массив    
    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 extlog Then DurationLogString("Duration.File:" & aFiles[i])

        # количество каталогов        
        If StrPos(FileGetAttr(aFiles[i]), "D") Then
           dirs += 1
           # расширенный лог
           If extlog Then DurationLogString("Duration.Directory:" & aFiles[i])
           Continue 
        EndIf
        
        item += 1
        
        If bAlt Then
           # поле плагина TCMediaInfo
           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
           
           # количество миллисекунд
           ms = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
                              "Wstr", "Duration", "Int", 1, "Int", 0, "Wstr")
           # количество видео дорожек 
           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 ms > 0 And vc = "" And ac = "" Then
              DurationLogString("Duration.Warning:" & aFiles[i])
              Continue
           EndIf                              
        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"
    Free(aFiles)
    
    # запись в лог
    DurationLogString(txt & auCRLF & auCRLF)    
    
    # копирование в буфер
    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)
    gDurationLog &= 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
    # при неиспользовании BaloonTip
    # используется подсказка Autorun    
    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)
             WinGetPos("gBTipX", "gBTipY", "", "", hWnd)             
             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 ' & (gDurationLog <> "" ?  "" : "/D") & ' -1 DurationText' & auCRLF
    Return txt
EndFunc

Func DurationText()
    Local sLogFile = TEMP & "\duration.txt"
    FileWrite(sLogFile, gDurationLog)
    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 gHintWdx Then bShift = true    
    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 bShift Then
          If gHintWdxList.Count <= nCase Then 
             gHintPipe = "" & auCRLF & "Autorun: No data in " & gHintWdxCfg
             Return
          EndIf
          gHintPipe = ""
          Static aWdx = List()
          aWdx.Count = 0
          aWdx.Split(gHintWdxList[nCase], ";")
          For i = 0 To aWdx.Count - 1
              gHintPipe &= MediaHintWDX(aWdx[i], FileName)
          Next
          gHintPipe = StrTrim(gHintPipe)
          If gHintPipe = "" Then 
             gHintPipe = "" & auCRLF & "Autorun: No data in " & gHintWdxCfg
             Return
          EndIf   
          gHintPipe = "" & auCRLF & gHintPipe
          Return
       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 LeftsideHintType()
    Static init = gHintContent[0]
    If gHintContent[0] = init Then    
       gHintContent[0] = gHintShift
    Else
       gHintContent[0] = init
    EndIf
    ShowRedInfoHint("Left side is " & gHintContent[0])
EndFunc

Global gExifPID = 0, gExifStay = 1, gExifOut = TEMP & "\exiftool_out.txt", gExifArgs = TEMP & "\exiftool_args.txt"

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
    ShowRedInfoHint("Поля подсказки " & sHint)
    If c = 1 Then
       If gExifStay Then
          FileWrite(gExifArgs, "", "UTF-8 NOBOM")       
          ShellExec /TT /SW_HIDE %gMediaExifX32% "-stay_open True -@ ""%gExifArgs%""" 
          gExifPID = ProcessGetId("exiftool.exe") 
          If gExifPID = 0 Then MsgBox("Процесс ExifTool не запущен")
       EndIf
    Else
       If gExifPID > 0 Then ProcessTerminate("~/TT", gExifPID)
    EndIf   
EndFunc

Func ShowRedInfoHint(HintText)
    SetHintParam("ShowHint", "Font", 15, "Arial")
    SetHintParam("ShowHint", "BackColor", 0xFF0000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(HintText, 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 /C:65001 gHintPipe %gMediaExifX32% ' -G -S -lang ru "%FileName%"'      
       gHintPipe = GetExifInfo(FileName)
    Endif     
    Return FixSpaces(StrPart(gHintPipe, auLF, FieldIndex))
    Return StrPart(gHintPipe, auLF, FieldIndex)   
EndFunc

Func GetExifInfo(FileName)
    Static a = List(), u = List()
    Local ansi, utf8, wrong = Chr(0xFFFD)
    If Not gExifStay Then
       ProcessExecGetOutput ansi %gMediaExifX32% ' -charset filename=Russian -G -S -lang ru "%FileName%"'
    Else         
       Local gExifOut  = GetTempFileName()       
       Local gExifBusy = true
       
       Local sArgs = "-G0"   & auCRLF & _
                     "-lang" & auCRLF & _
                     "ru"    & auCRLF & _                     
                     "-W+!"  & auCRLF & gExifOut & auCRLF & FileName & auCRLF & "-execute" & auCRLF
                     
       Static obj = BinaryFile(gExifArgs, "a")   
       obj.WriteStr(sArgs, "", "UTF-8")
       
       ansi = "Exiftool <time-out>"
       For i = 1 To 10
           Sleep(50)
           If i = 10 And gExifBusy Then
              ExiftoolBusyHint("Exiftool <time-out>")
              i = 1
              Continue
           EndIf
           If FileExist(gExifOut) Then
              ansi = FileRead(gExifOut, 0, "ANSI")
              If ERROR = 1 Then Continue
              DllCall("kernel32.dll\DeleteFileW", "Wstr", gExifOut)             
              Break
           EndIf
       Next
    EndIf   
    Local nSize = StrLen(ansi)
    Local buf = Buffer(nSize)
    buf.Zero()
    buf.SetStr(ansi, 0, nSize, "ANSI")
    utf8 = buf.GetStr(0, nSize, "CP:65001")
    Free(buf)
    a.Count = 0
    u.Count = 0   
    a.Text = ansi
    u.Text = utf8
    For i = 0 to u.Count - 1
       If StrPos(u[i], wrong) Then u[i] = FixFFFD(u[i], a[i]) & " " & wrong
    Next
    Return u.text   
EndFunc

Func GetTempFileName()
    Local tmpfile
    Do
      tmpfile = TEMP & "\exif_" & Hex(Random(1, 0xFFFFFF, 1), 6) & ".tmp"
    Until Not FileExist(tmpfile)
    Return tmpfile
EndFunc 

Func FixFFFD(uStr, aStr)
    Static FFFD = Chr(0xFFFD)
   
    Local uLen = StrLen(uStr), aPos = 1, outStr = "", uChar, byte
   
    For i = 1 To uLen
       uChar = StrMid(uStr, i, 1)
       code = Asc(uChar)
       If code < 0x80 Then
          byte = 1
       ElseIf code < 0x800 Then
          byte = 2
       ElseIf code < 0xFFFF Then         
          byte = 3
          # High Surrogate (0xD800 - 0xDBFF)
          If code >= 0xD800 And code <= 0xDBFF And i < uLen Then
             # Low Surrogate (0xDC00 - 0xDFFF)
             low = Asc(StrMid(uStr, i+1, 1))             
             If low >= 0xDC00 And low <= 0xDFFF Then
                # Истинный код = ((High - 0xD800) * 0x400) + (Low - 0xDC00) + 0x10000
                code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000
                byte = 4
                i += 1
                uChar &= Chr(low)
             EndIf
          EndIf       
       EndIf
       If uChar = FFFD Then
          byte = 1
          uChar = StrMid(aStr, aPos, 1)
       EndIf
       #OutputDebugString('char=' & uChar & ' asc=' & code & ' pos=' & aPos & ' byte=' & byte)
       aPos += byte   
       outStr &= uChar       
    Next
   
    Return outStr
EndFunc 

Func ExiftoolBusyHint(HintText)
    #SetHintParam("ShowHint", "Font", 11, "Arial")
    SetHintParam("ShowHint", "BackColor", 0xFF0000)
    SetHintParam("ShowHint", "Text", 0xFFFFFF)
    ShowHint(HintText, "", "", 500, 1) 
    Sleep(50)
    SetHintParam("ShowHint", "Reload")
EndFunc

ReadWdxHintCfg()

Func ReadWdxHintCfg()
    gHintWdxList.Count = 0
    gHintWdxList.LoadFromFile(gHintWdxCfg)
EndFunc

Func MediaHintWDX(WdxName, Filename)
    If Not FileExist(Filename) Then 
       Return auCRLF & auCRLF & "Файл не существует " & Filename
    Endif
    Local obj = Plugin(WdxName)
    If ERROR <> 0 Then 
       Return auCRLF & auCRLF & "Autorun: " & WdxName & " plugin error " & ERROR    
    EndIf
    Local i, txt, data    
    obj.FileName = Filename    
    For i = 0 To obj.FieldCount -1
        data = obj.GetValue(i)       
        If data = "" Then Continue        
        txt &= obj.FieldName(i) & ":  " & data & auCRLF
    Next    
    Free(obj)    
    txt = StrTrim(txt)
    If StrLen(txt) > 0 Then txt = auCRLF & auCRLF & txt
    Return txt  
EndFunc

Func MediaHintType()
    # переключение переменной
    gHintWdx = Not gHintWdx
    ShowRedInfoHint("WdxHint.cfg " & (gHintWdx ? "включен" : "выключен"))
EndFunc
[/cut]

Замените этот модуль в последней сборке.

Всё работает

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

Добавлено: Пт окт 09, 2026 13:30
AkulaBig
Orion9 писал(а):Полный код MediaInfo.aucfg
Теперь хоть понятно, на чем ваш код основан. Вообще я тоже из него тестировал изначально. Но в какой-то момент запутался.
А посмотрите, какая конфетка получилась на основе кода перекодировки сансея:
Изображение
Обратите внимание, показывает даже лучше, чем в MI. Для которой этот код писался. Ни одного крякозябра.
Но вот обычные крякозябры увы, не перекодирует:
Изображение

Добавлено: Пт окт 09, 2026 14:09
FallenAngel
Orion9 писал(а): Полный код MediaInfo.aucfg
А можно в шапку пару предложений что это и зачем?
И как пользоваться...

Добавлено: Сб окт 10, 2026 13:07
Orion9
AkulaBig писал(а): Но вот обычные крякозябры увы, не перекодирует:
Для этого я и сбросил модуль, чтобы найти, где несостыковка.
FallenAngel писал(а): И как пользоваться...
Да, по сути, никак. Все полезное я уже вытащил и оформил в отдельные модули:
https://forum.wincmd.ru/viewtopic.php?t=17741
https://forum.wincmd.ru/viewtopic.php?t=17748

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

AkulaBig
Всё, цугундер. Жена не разрешает мне бухать, т.ч. сообразить с болваном на троих больше не получится. Очень жаль. Душа рвется в оперу по ночам.

Добавлено: Сб окт 10, 2026 16:00
AkulaBig
Orion9 писал(а):Всё работает
Даже на вашей гифке видно, что в Test.doc показывает крякозябры.
Orion9 писал(а):Замените этот модуль в последней сборке.
Да-а-а, вытащить нужные функции из этого файла мне практически нереально. Уж очень сильно код стал отличаться. У вас-же выше код был с функциями WriteLine(text), ReadResponse(), ... У меня на этих функциях код основан. Ладно, попробую все-же разобраться с перекодировкой.

Добавлено: Сб окт 10, 2026 19:40
FallenAngel
Orion9 писал(а):
Подсчетом времени воспроисведения часто приходится пользоваться, т.к. слушаю много подкастов и нужно правильно организовывать время. Над подсказкой MediaInfo можно еще работать и работать, но в целом это удобный функционал.
так а почему просто F3 не нажать? Если установлен TCMediaInfo.wdx...

Добавлено: Сб окт 10, 2026 21:50
AkulaBig
Orion9 писал(а):Всё, цугундер.
Ну если и вы исчезнете, теме каюк придет :( Я все понимаю, жизнь есть жизнь, но все-же хоть иногда появляйтесь.
Я вот наконец-то смог переписать вашу функцию перекодировки в более традиционный вид. Теперь все работает как часики. Хотелось бы чтобы вы посмотрели, нормально ли все?
[cut]

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

Func FixFFFD(String)
	Static a = List(), u = List()
	Local nSize = StrLen(String)
	Local buf = Buffer(nSize)
	buf.Zero()
	buf.SetStr(String, 0, nSize, "ANSI")
	utf8 = buf.GetStr(0, nSize, "CP:65001")
	Free(buf)
	a.Count = 0
	u.Count = 0
	a.Text = String
	u.Text = utf8

	Local aStr = a.Text, uStr = u.Text

	Static FFFD = Chr(0xFFFD)

	Local uLen = StrLen(uStr), aPos = 1, outStr = "", uChar, byte

	For i = 1 To uLen
		uChar = StrMid(uStr, i, 1)
		code = Asc(uChar)
		If code < 0x80 Then
			byte = 1
		ElseIf code < 0x800 Then
			byte = 2
		ElseIf code < 0xFFFF Then
			byte = 3
			# High Surrogate (0xD800 - 0xDBFF)
			If code >= 0xD800 And code <= 0xDBFF And i < uLen Then
				# Low Surrogate (0xDC00 - 0xDFFF)
				low = Asc(StrMid(uStr, i+1, 1))
				If low >= 0xDC00 And low <= 0xDFFF Then
					# Истинный код = ((High - 0xD800) * 0x400) + (Low - 0xDC00) + 0x10000
					code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000
					byte = 4
					i += 1
					uChar &= Chr(low)
				EndIf
			EndIf
		EndIf
		If uChar = FFFD Then
			byte = 1
			uChar = StrMid(aStr, aPos, 1)
		EndIf
		#OutputDebugString('char=' & uChar & ' asc=' & code & ' pos=' & aPos & ' byte=' & byte)
		aPos += byte
		outStr &= uChar
	Next

	Return outStr
EndFunc
[/cut]
Теперь буду разбираться, как вы подключили код от сансея к ET.
Разобрался. Достаточно было прописать Return FixCPMI(outStr) и все заработало.
Хотелось бы понять, почему в MI не получается перекодировать вот эти крякозябры?
Изображение
Ведь в ET все правильно отображается:
Изображение

Добавлено: Вс окт 11, 2026 13:04
Orion9
FallenAngel писал(а): так а почему просто F3 не нажать? Если установлен TCMediaInfo.wdx...
Можно. Но подсказка это другой уровень использования. Один раз попробовал - другого не хочется.
AkulaBig писал(а):Даже на вашей гифке видно, что в Test.doc показывает крякозябры.
Один FFFD специально оставлен, чтобы было видно преобразование (об этом писалось выше). Но я согласен, что так не смотрится, можно звездочку попробовать или вообще ничего не добавлять.
AkulaBig писал(а):У вас-же выше код был с функциями WriteLine(text), ReadResponse()
Вы же сами написали, что можно и с файлами, вот я и сделал то, что было быстрее и проще.

Вот обновленный модуль MediaInfo.aucfg, совместимый со сборкой по ссылке выше.

[cut]MIME-Version: 1.0
Content-Type: application/octet-stream; name="MediaInfo.7z"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="MediaInfo.7z"

N3q8ryccAARmCBPQcioAAAAAAABqAAAAAAAAADmoFOvgxJAqal0AKByIJpXabDq7rAXN8pLbjJqH
lWhBCMFVaY5148g9iZlrTM+p4CYfwiBSb4X+QX5roBhW9WzypV2Bn+YowAbNkmL0ZbS2UtvbJ5AS
+feSlASOM5PftZm7ElAIZydAYUYgEq5ZzJiLC7vyRv3/RuiV5OwXGPPZwWnKGNex26mdVULhrVQD
Yzl3QWFJU1lzfjdmiWi6ZYhB0orsZabnJgKCfK1rOpBz1OAXCU1Ry+CxZGcB6d9mazpCQhO0Xd7j
kgWjiRLSCzvm8y3c9ZEWGREpnpObhBTfz1Lh3VThbxBLt39guqHZkfKhg125C3ynU4R74FeqYGp0
X3+7TEBfCmPiGSlMsHFfkir1f4y6ETfD9BKhY7tiNGd78NPAgFMJ2XMqs3WeCk7NdCQ9h3Q/RaZA
xvaR+MQTlRjOgtQkeiyTMLTG/cd9bQGNRcQMjsIfSKNM668fAaeI3RuFZoR2BHzSghGILO6xAq+t
pAgDLOJoeXgz+AhPHkriKId/MhUpfsptat2OvKildpQXH4fNDh8OB1yQDkmLK61Y7VqfH8D2j8LD
wE+Mw/ZC1IBsMpEICA3NjBcnS5rPY3YQ0l8CGAHjlnn2Zq2U3g6IBpiWsSoNd1PDjIInbcZ9C/1W
8N0L00nEc3wn9dBBkBZ5Cq4K6y8tgl05vDEmOaEaH25kIupUqAV7cQ9jzLXk0I2kF0fF++W7Cdye
UuT9mtRvocCvsu9Cp5npFnh99anAe7cOlNNU1Swe6lmx7IbmIn7qamcuv6dZuCQxVOCrorcSr4BH
wLOlnQ1XnuHBelYCVKI0oJOEa8Zays3JjynOJRhTX8aK5FaD5WYNGr4oWNzViuEQy0s97mX94Owj
YdyCid3enk3SX9UDndTz5GeW7aRcLLrBpybtY6TwV/k561LjxH/nGVDToA5A3IHUPB1I3rXYE6bZ
SUkDNUjAgjmANkePSdT/OMWA8ejoSmXcYInJulDsKAItG92lfSNlEzcg7wJrtcMJhteTuL/6k3DW
Rhe6hBftPhOHtm+hbU0gneJ4PkebP6T1Ie1IEhrFjnKH1TZXN6JusyDFGVQLO/hbpoglY+wr5aOx
XfcrTw7Hn/GKXLnriesciJHnjLSTDkM7Ig0vMqGItztS7OVhS7z48DDXRQvUwOg9FCQ2hM4WMfus
d5jSh+PQUmsRLbU+DswoCcVPg4G8jzznS4FHnUzxGcVIdGzLqmqtqjkzsUHvUOITZqw3wOGIaPQd
4rmK6ao3o4qKYN+56Mrx1YYAqqeK8OGAxcu9tCS2U3tAfR4XoiogNnz4j0pZbFnTgPEd9jyD5BW+
qaNzu+jnbV5vrBid3NW6Pq9LNdgwHKwNGI+UCkNdb2aMQVZBcFJWRIJJwb8kiB3GVWUgev4ht5Nm
gGv9oQQHfeOfl4UsbMo2PtPm+3zFrCR0Vsfz6/OA3DNfKilfD5rJZcdI9LLAdhuHJ9pqGK3OyLh6
d3c/NzeI1qCiwc6Nil2VM4JuGpk+6C85+MEK98HtS96qTKRe46IyrX9HqR1n3p90/2USKTxZ+B/4
Oo43nLrEQdeU3b/Ti6Rhk+SKa4YfspfoeKtEsBW9kxHrhcR9qnAfqNmGt4mIeAlnzxXI68iFoAzP
BLK/3OeSsrFZ9JvL3Zpw2eYpkrDmjlFyb5D7p7SFMMbP5mJEVhljKPynv7JnXAHoOM/qggTRoC9Y
IY7+28i+ycvHOp142yXZ9QED1Jd2f/ctldXPliTnl6eKJztHnHnc5aTmtzkvksmHy3Gy4lsLQuzw
sM0E1O2SmyV37urGIDxMjzFJeIsVk3a88jQYPHDTWsgizExEIqixbGKjPP5slPo9P9xuHuQmi0ZV
b7k67KB4Lds2LGIfelExVHLrBOFmlo/qN9ypW5YT4A0sjgSrWIJeGZG0Rx2BLZf27Z5UxgWY3l1S
gBkFLVVLY7Lib0hT/3gCR6o1V2tX7XPGuoRBxWiPseR23dBNKRER8ZqBMlAqDm9hKcs5g/1lqkzG
FD96j23oR4N1uGRXnq+Jy2WPBWaumy7g3aQqE5aa1jUm99ByLGyl8fpDxMkoz+6gsBs1mWt/OQ8t
EXM1xTQOFK8XooOghvc0d2AliZvQ0cu939498P3uNgFJOYoEHdl2xUtxagqhnkKVSO132cZXJuxS
WJMAH7CEJMLII/6M4VHrov1nKhKongqJ0svcuynIQf1oXT2cWw4gKWpW1Hwuwun+GIBjQ6asWiRG
mFJAQDfSAnlVzo7EO7rPK6LllN7RLKOk9Y65k5kNzDztkFNDestQoZ5cdX3M4bmsZjFYIO0w9Ajw
UXIwGRsQSoEkLHooVqp1o3AVFzZj0KLJRjoINMYXeGKVg4MkQXQFZi5A2xmmaPFz24nZcvtkI11Z
zy0AK6Zfs34sV/EAdqE4e8LEflVEi5J07/xE8sjR6G9xgpzpjULCzYL8jrMSrKHsFNlLnNaR0qKS
y8kDDXUBtgjmUrYnDCCqo19pxgUndPpVKFGRU+p/QwOC/0uiCo8uVBAJ780n7Bwfq5KMEI8jFg32
7UtTzus2FMoRx5Y0CgO938sRLZ5+airGPilWVl920qtm9+6PR1T97k3JsxlWwk2038AoOEu7KuHC
ZImUigd5E04oNW1pbdZgnzyli64OuGjZgy5XZzWerTTMlHem/hCRhorhORU6gA7+kvQdqwiH7Jhc
QPPYwp6oQVOqNCidVCO6MqfO2cU3N4zFvTKeT7GazR3/D4OTK5dMQl8kDMXn7stq9AgPF2Z9SdLw
bE6Lv83ygMtz9T7YjTgkBGihy9n+lJtcB5jSXny21od2nA5HgCq5Te4v5VKChAqkZaiMMU6yK+gs
BkJDk2Sfi55PWbeKtI6nWW8ViC9XVGhvaj+v2if1DBcDPkAs1FVjxUkVQty5XVZn+F6vnj64LPQT
jFH1Gc5QpKm0GisKpvElsL9MpGmzzvhajspISV+CXO2hHvF0FYTkb8H3WS3DTg/4m80E77eF6Fd2
Geeg/JLz2qJ8LvBt4UEb/dQVeEJthWxO3ez3DFewYUo+hDt1xVnrQSiIosYIPKIWmgpEEP/P8iLX
pg/qteboDn0XjLIPp1+tXYSpr7m1arEvgcVoPW9h//VWK6HcWD74zUoBafeWkP/lNBOY2dWK7hV7
xfa/BJ/IASZ2vM/aWxchxzckUUo/lJN2373g0GJNQhtuJjyt6e7O75+rcpLftDjwh7H4S7MchoO6
9wZu5tnNiVmQYxsftj4IyMpaAsSbnzFGrWhydF5Q32ZNEJshc8qWDk0Su6fieMuW6vON4319uh/P
9ZhdJBVL4gJcjDg1MZDUAj/NucRBjFUxt6uLIacmq9WPE0gUsuuWrKtgas/9L13kBucntCjiBqK3
WmMGbWO4Rnn/j1A5zFjwkLmsz0Sx8rpHVcMunmCiz2GvNNzsjgcEI9d6kr90POmHJ78TEAZ06vQP
adIafxXMYcsH2xjE7AHvD0VOZkpsBz37D+OYSnbWunCP+NBd66nGyVQ4SW31bBZMZ0tOA4sWS1B/
lehAKgXB7B5okZ3E0JPNENM0fm8G73sn5KzgHkrg6N5sUBRDNGZ3Hw9ZoJdDLFp5R3kZXZN7Q85m
l5aqlnG21X6gU2MHuggb0bkEhk6BLaWVWjHFfGGI6rC1AP54pZlE2yeTKBCzUEisy/RnfmiIHMGm
E8VvxI8klY0ihbmBqCZRzU9GkI10mypgboOJhbXTMGrR68O7/Cx1AZxIyvftWDIJwDG3uxrZPbVv
zOi9vPA/rfJkHYuKIQXD14R06RKcOiwm3mJ8hzJaibYQshO2IXEXplIZDOWUFi0tI6+I9MVDEWhU
HPLFY3+97GwaPWekzS7F88CvX8QqPvrCRFMYAOojzrzwMnxt3Id0AXiPiUaE6zZuh8Cc6mzip8tK
9p7rFZuvCY3Ql6mc9HhB/83y4AEBdxEgL1GXPZdn3KH++KklAd5vYrKfk5tOnhsCrHOWgo0+d3oj
okYs2F3bm01LRzJ90McUW1Snx4UpPbDq3pWK1t9EWQdQ1KjOUzRaNcgDFy9QQd5YWke5AJy9bgXT
cV/G/JBuBW00iEMnaaiQ+k80FzNGwhL2ThDQkyjrkwIIgi8H/pvcLTj7P2fabFBhAXfPewVXQ5Ib
SUj4IYRPJPIj3XDNz/hU+le8oR723DqgtqL2yX9xvqK4RUzTGlgmRUyg2yoZi7SQ2pZeDa1kuBKD
iopKHSL6hlOx5yMp48UHCqsP9frAHeHt+fVRa7j2oopJsyAQuA1I9ibT1XR2OcGk83RfkOIErU0u
cHhcKt7JSTbEWsFh44ZgqwT2Oyi7Z4a4/EWgLbdtr+sdu4HE8QotqyIzuB4daLo9gzghrMPM9HcB
aKagaZ1fBkcxGD/u7FbrVpw47HrPyhEUaCfb6G1jhfEhIOim41V4NdLYT4BoSh6uLSJ3qbR0Ci1D
JUkZomj1qqVuN0AQMEyHd62ZKXMlAUphUzCK9dG5p3/60UZGQc8hOTxyhC7lKkwa4OJsYKOGbgo2
6atSLBLpcL59H4ChH1gjQSDmSq/1M6BeiuUZ+ghBn8mrPf7NLyRmxgcqzlnr9bsMwQn5DAF2K+Km
GItMwEQG5nvXbcVnTyirNadFvOBQPpjMeIP1m/pLF8VMbiPPsVsXqIikcL3L4IuddTkIVOrrbFaK
wYcksC/0KGFbfSJS0BTcBja9llnFla5RFeqmOAvl3qd3z3Nl9C2qjmyUWS2gowEIZfGDCkaXw6aP
HgEKZwy96wQIlFPoD5awDEOwLJqXPFj6pu0DDT+Eo6tFbP55QLF1q7lUFHfHbJbix3uiYFD5z52i
ak63VUbLJp/r8yQqbU8C3xpYsCMF/DtvQ+LlqKnnaDMQI5YYdZK0SNTyO8KoK6MgS2sxNVMaFSps
7HtVVyFMWQ4bffrZ+8v3FxkWT7+yLVzCN5X7DFcUForyQsclhYqP5Y9ZwCEHalHjkFCUu3MjyDzx
jIRbOHRjweik+Shf7fgzOQXeiBqXdp9mpT1KPxloWXSRqlRdT26nDDqVnJCRfyvVb7t41HrASi8v
eCP17nqq7Dg58+SpC2xGeKUfhxfeGaAHMPAdIHkPCAxsx5hurzttfExLlfnSg8PkdKBC48KQwIE8
rKk6KjzKPYY/SEfMp167TlVIAjhCTqEtOhwlX0ubOJ+SnOf2pDcmmbiKrxMmQtEldvOprXMgDACa
HS/kW6jdE8wSLzHP8KnLwc0eKnmi5bknbOrCW0Td15w7ilqB/qeDre6rEa9wDjcIzXCnzhyWAv/t
OTlrQEU5IHePB6SxJ64GIrndhjng4y9Mg2Fnteq2H0gl2IpCxNZLciGOzFVkfYQfa4S5YtBC6fO8
E0GDJsh2nYjA1XHYVw5Uv2fnnK0ffw8rLBfoYdVWbtPDY1E63wN855z6iGfec7OJllioCSduzYBv
zLCL82HTJqvRAAD2y7BLh8dDHD2VRzy7tda91cP7hCDpvTzY97Fak6DwkxtT+X/HEkdKRh5veDNG
ru3+ZU4vuo1LxjrLshoOv1T+k11+q8g+CeEWz81EMhlTzHRoU2UM1tyT2yKP9Pwg1vulbsuH2gOe
fG3kahcQBHX921ZeFFwQ5t8KBTwYtucdu4h0nqCUjH44mkuH7iJQ8siGp0V2EtHfVuOZY82aBfQf
silGpXRTfIntkjJeAdTOZa/+DOWKnWBj5AOPDsrisNgryVkiqzxJJnBFJWz2Cn++UGn98EZmffTV
I0QiWyuUsxZ3MRjgHVu2dWBQt4FG6/FW5HiVSGp/K3Wby4hxNLpphH/oy6qQE60hMqcD/0jmGi1M
DqjvnDJffrkIcRexyHJ6nXK+Vfe3RfEBDmpGqiAW0KyCBAvxEBGkRPVM4jA2fV3mEoNY8S8nGjxX
AgGIUuBsGCGtU4vaGwxpmYq6DaHk6tXrs0wrDQYCftxhdxqkU0AH62vTkvEUnMDCiD/012iDR15v
+8TpFP5yTVVgdfAF/JSsM4y43eZsecmyDmqaV/s6Duudck423r2H6twFk5/TyrWtT+x9BWEaFHgJ
Djsy+tw96pjb26DpOsrkCeWd2eVb54RFrAxwPIFXRTezoIYbsEBJz8dkKAMnVakz1VhgKlh4bXuT
eZw+WoAu887K/GomiJrxOvLzSDLkDX1ngDanLXnxaHwG1eNW3UnQUKH6fqILOIfHCQCrbE/dpIrT
dp7botGdvBqgRaOTyUKj0Cznnh/uvkM2jM0zyA8jAfMtp8jUEho46eUWIZ1xQG1BPBTiGPyqCgsD
QZWwJGcWi9+ytjuH9xaKYmF9vnhoICC6dS7DbkfHKDeIdayv0fs/ZJuXv850BSYOExzQ9yO/JFjI
7+JBDhG+IL/EldO1zvwZh0pwbwrkzIGc+/N/sgqJZMWxbkiYLVSjBISqlNhONQX4Yd9VX+7SMCzl
3o/qd1hwG4IX7TfzwcIrcTP/P7/C+yRAwDT12TkzyB0LOvfdBzQlTcBrK8HlVJFvSPhIQ4cIUpJZ
ePrXCTvdhaQPFOQO8HJn0TTnOvcTGYEoTxHt5qZDNAnJAm2gXmeedmhhExCM+85714CpM8eAJlVo
Msx95rjn66QyKQ80KhvQZfEy+w5thI8XXcGyq06ZUjn/KtoJxkYX8srDrLxnQpV9GMPF0iwBPHRs
RChE6X/Vmlm/JpFgCLzGEcyuKvbc1q/4BFSsWKruwjTmj8pFACerXA/sHSaiFZk25/Q307QeWv0E
c0TQXymeipp+kKEsyc4lcq/h5wuswj5u1K2nmo4HWypflCh22tXoq7wJaaWgmC1Y+l7dCTkb6C4a
ll6pRA+uLMSzl3DXENFtmAMU7nExNJKKz7gp8P0Mn4eYmUDPzPLb2Ka513KGxTFLIUTxHPyBZBFc
n3UXAYVTlzcawbHjEmQTDab037Jh5G+vfOPRnB806CzQ/LtvK0zWTa+rAe+HN2Ew+79B7JB6DEvj
y6JJfnQ2vSXwMohjo8plwyA9nRVax8KRI/3M6GBPi+HnmwlboN/JF7tQr0cGr5yYu3+D5T3LgLfC
npnNdpcOoRG/gzzlfc/kZGJX5IyidePsrcWPuW+7aeTutwlM3nubmtJDiwL2vlrzPYUaKrA7mFDY
xUxdUfewmoOy62YApUCsvJQFIxeTTuC4fTaHTUjkWkv1cmkhHMkxT4gUcg2mCuNAbNYCKW7lmfii
pl3iKCaDlrwHOGD3MqCG0ChPDTvJo6OJ8MmPq3J860M+i53zLlFSSSFtAdoJUqfd+6hu4SWFQsuo
zy3G3iuG8HEAlWKmctO2xMeqJnV5biuYvj3f9EJV2MpaQipvdf2YBIGBcOgO5AQk27ySD1xFeZSD
ZMYzMxQAYVeC5bLKK+XcyBA2kjV/VSWt28Izw4ohzIYLIrlxOFNwBLulPjDQ+pUsBdu4MzEpxzR0
v0WykicwmXR53i0QZDOqKbOo5lmKUplbNVyS80MMVeDJR1EHTIwA91UH+is3QbYo6RrPbyKwv4VX
iRb8Z9HzwuLbJ7ds0MKSEon0DOiZcjityd78xQ5rurkdVlQX+V3ylxd4SAsxDuf9sV8EL3XLGHuQ
DuOBMeqpm6ejwNNdQVt631O4YvnLxjwt1tzc6XM+hWKk7tWCTBuPlGuyll0io+/+9y9uHtHcYfpP
WgGkwQnzRbaBCyfZX+HtaQBuBdamHw/JI34AuPOv4c00mSq+vAXBYCukrjRSaKH0SepvVJdnMKw8
ZMusfSpdGIqR2Dl21N9/29ADKYkqPUsFItxDEZk5n1ZLooNVeD5ftiF1IDZkSHnTOXXuRXFApISq
CAqFr4pkqP087j4K5sgcoYoVZDWl8SVgtLSBOLYd1gYGE/oJofwLdgk6u0OCOMfi4wktXRchpmXb
RupxVbRS4uJH+yAkVbfs348JA6pWIyrzoqmA9x33/Q+icDi4+7tkcXn10Tn4Q7UdVa6ZSpXu2m+k
U7ThmN9RS4+z3WjH5E3XZ7ClQmCAH76YgHyXtfwgocHYn/nDuopJ9y2b50hDUuA3pfUIZ+Md9lL1
TZNOkTxgfe+Oa7bDdpvxMjXBFQ5FAucTbalH59gCLuI3Bq7IHW07JOnBniWcSPmpoNVMJPUTGUPZ
2Hm+DSs26YHMwHVRTQ0hrn9lmIcjyy1MMBlwgYr6OOL93qecQ5gcVYL4dbrp29ghwCXJDsQfqbOF
jh/yU2Gyrq7mwca9kJOs0YdHqs49sAQ+8GpAVqDHZ6Tn8dyhOJor3uzFizY5w/HbVJKo5FFiHYq/
2UUPCkHFF4FPMAdHw1jFkGsH2V8GjGWTaafBRh+w6zTVwRMGqQom3d+vDfcU0f2MtJbCPu2Xu7SB
UAG8CIBsp5WGALKW5VyC4nuiLVGGX4E5oMl3wl+3Mr42OBl/5pvLyiKmN/XahqX0EH8cfVK/D69W
5ToM1ndLr3cGodowD+PjnUpRTB3vOnY1SUjkt67un3V133aDl6XCz029KqewMiSIozJPA3DGOzHv
uHXKXq4/iLvdKAKUbxOM5jAXoxe5MnQcDYaY/7sjLK8F/+LvMIz911CYqMcnj5FsypLd6qprThtl
V+AhWC4JsJuAPYy0cbCBwXOPRCAnR+xKy7F5DCLygFq+cvDsNIYIBFB6QqolktOE0Ifp0XyK+Gom
9ZpdfXjeaMK2zLDYhApCea1/R9H8b0ffK83mwRhIzxkCpY+/z+keptEvTRu8YikoBci2zlAEXB4k
PVSXJoUgFPZqeiKxcpBX/p6HZ4KdE9ciafSKXouKZTbrBB3BdPZQOhTNNY+5laCSLf4bQtjBCBNv
Fqr7uvlDWZiVyvcI6leg36xCp6Mb6TruoCZCMrYvRh6MubJ3hKM7h4WH+nYRx6psaIV/pUi6jUCI
Osv3XaeR/Dhwvk3GlBbpTPjbIlXkEkBrt9p6sYJZZPtpyepFPl8+t9sE36RM06hpxOTGArloKmrj
HhbrR6gsOBeuNfu6VKh/M6T7qeSeH/stFy97uWuQoCrQcH3elMpK7Vxxc7I8wyrrPO3kjrCMEGhA
JUGEbVbNm8LH8vIJ2esSmhWyCAOpLHsprQkEhuUhTCpDegkPbw2dyDpnrZt3V/uOxAnZFiqgGgYs
i6WxjXw0NqJBngqYJqHcCuOlaBishVlRBg32Z+mdjnBbLFEpHAKsrh0tbZjBn40lrKu4ws5JxmnM
fVYyx/k8u2EtWF7anMVDN4cdZR7wTTqnH8mGTjs9yHSvFm8aW8ZoTRF4490Oc6AsF94hA+YXOQMC
g3TFJ6j725lun0NECeCPVEEvFzS1k1ORPdhen1U3gpEhg7Z3FoH4vumMXxsLMnZnGgUE6+3c/yJP
JTKNZG9djJP/Wf6Bti/oUUkPF4iNDPOUm3o8Uvfa4V4Pozr6JeJ6uVD173eJvzrrfCspK/ruaich
VZsQqJ1U4+TlrDdOsLCVdscezBCvZgCaTh5O2eJtj0+4F/O1EP1YPJAlb1kWJB8TPm7uicNrw8VH
YW2Wlh5sTXYBY4DxIJ376ciBAZnoE26mPG12HMoH9XzvItvmkwvZSgUVv9wMig1mUSUwrj7QR75d
ZxRtbCVCNRzpC3cCRSsBVtHA/+c401Cb0fOW/Fq4TD3+2tpqcz38mxSXg8iRDhdJKtx2MezQAnxX
NVMezr+gkpPRCC6uuqPUnOg0Gk4ef912Gjtlbwz25lrlb7euAwfILD5yeV5gDpNeJTAwv9Te47Vl
edTl7p1G/GxSWU96Wom9Qo3Im+89DDRFU8yRQpzEm4caOLnB1M6hpNxsNU76o9VyrWQxaNM59yER
Btg/dNQ5/yad0h6H/2zKTWEU+Oqn+TfoXjD9dZHaRT8+1CqiypnUpH2/k9TUme9f1anwKxMmFmOy
p/5UBNkLB98tEL1XmRhvVTvkfqKeu/c+kJ6VCcO2lfNhk4aR/pPOvO6iBVKr5gjQ0DsJsQpIKoe8
1LCl5+ybt5EjuCZPGKcBJU7LPGE3+Hbu+Kht+ISNLi3CeS3LCoHFCScBFWfreZSbIMgWbORKYDn6
aclU79obrr0FdVpSNRJpKAqw/wddGUAQZUg2qFwUD6q6vpxkZWBRAqbRnDwq5shtE1ol1IoT5Ux8
NntCspn4e/8mf1c17mHtqjTxYeWXyCaBB1OYRcFluKvsZqu7aWp6Pl8a9VtsYps6bz23+kfNcJ6d
pl2dO2e41epSG5gWzKlouu8vSusDz9by2/vBUWWoYgrxrZ354qCXB+ZYBiRn4IB65ZiyFDpLzPNy
GRuQSMl/Yfr1p5K0Gol9zJPmUdGKSJ+8DCzDMCzrATLHe9kSct0X5bCVtpcyEtM0Ib8pUJfuUM1y
Ef/5c/i43eieP29mNYwjKc2PR76e0Xgq4Yd+OFMDGJ9YgmDGvmO3740M+lP89taGUNClPxe1VQdu
IS4MvFyFCmWvgQqiOJlF9IKnFBRKRr7ELCp8ZoGU6JSLm+6O/UvdHRfqFxKg8A7CQp0AUrX6jUdP
maXNmNnzzzWxMI2Tw59k1gS0UtoGbcjWI7OMmh1mFvuUWk09soDfuvlwz7+7QQaV7OtxtBUh2PIy
JWKJlUK2onupn8SKkWJEE2pNOw3McY0YtZmlYvI0ZLJlRMBL6W7i5yOLkVNpJox7JJ82cbjcZAwh
tsI0nek8yJ3USWxLQoMbOHkrqr93rZHd6+tYsFqI5aTdAF8zUKimc2j7L6XE8eFoOSyGuG17nYDS
YM5ac8BqAfC6ZH11v9RzzuTQod/MmagJ9ge5+fJADH0PKwxUYsatAaf3ryQFHDJZ73yglCXrZz5F
UVbRSfPVxM3wQpGE0LgZ3DgvepAEBsDvEk+dpAE40Yf1Y8+BgvQm6K1QaYGbfZQ0aayJ9G7y8mHq
X0QeTD9wrFIuUTO23iIjasA7E7HMTXNNrLI61+Et7DA00qoq5QRxz1bf9TdqbDNsJKyTe+VmUC3A
jIwmhgAwj3EnylyihLD93qQ/HVr40Lo7MYWz5dmzywJg001PDWoDgQTBWBnzK/32R2tL+zfhzi58
4Y7d/O8BHesbRfzQ/O6OqysUEzlpEoG8h0KVGX9RYRzuZc+kU8mike4Q8XlfvkjvCOv7Y8F5bEUx
KxDMfEhnZGF/R4dDSG/DZpcBAArQyvB9Xe5UDpBw6cHXpBRpWUloZX2i0mSig7sHPJj2YTIJAU97
k9hU5yGN7lsh/b/bEeGJIssaVXq1showmLa476cujFhxsl9Y9ihl0eMQaEQ5vdUiYceMHtf0OeG1
iXypP5zt3NZul2W8WPQT/aYDEL7JkMqkksEmmCku+T9EdAfrpJiRG8pwrnY37pCoh0waV7KjIvms
84jZ0EpZWON8fD7IBcLnAE8LYiTHDA54yqT1BmUkOdgfQg/dU9tU412MA6pLbS1xxMwh0MPuxWoK
nT8fAqhWVOp47eZg3eVOP5DMTVXMbiNSQGD1NsCz+YT3o3dmpM7gWB4YXgyI3CjnJ+j1wo6GpaoS
25Q3KrFzAvl2jz+NTU+NjR7ENe6BvnmN9nLv4WxqHmp9d6MJuHAUEJsA1NjEIWsJ0meEb7h1IuKL
kCX4kGogqCj/tkmRtIO3BkBVtCPwZ6Nx0j+CeQNmlktu2YTwSwR61twyqXzcqq1GS2+o1kh5cYxx
Rm+ei1bS5+CLckgSox2h6XO9XGv5eSe5Ktoz51/vtbELMY8jklapNHUC4jnjbfk04rLolBd/JXA8
14DjdGXZTNjNUZ8cSXXMxaHuDEB0DQZ6eRd1DTQ4I6oO3t1mHDkGJkz5ZgY1zuIpvUmWSGa6noGW
nq3IIymw1XuUNQciiQYfc8SXBcv+jn9L/gQH8I/hfCOk9Fc+PS0rMPYS+eyC50BUcHGzxntJykTO
e6u4M+XP/m4CFdLJHInBTxZ00ZboFq4G3Lu2BRvaxjFli/gGtq3l61cwXRZjJkjE8hWCCz3y+6KH
kBmPRj7Cqhh1adZjhJx32BMZApR71mYKM+tUUx1VqoZSOYMLPLrr0+J73oBaiv+iJXcl7ceEDmaq
5ck9DdOsChiVNmWzxQ4RZhd7hIETBc0ODEOSBlTCuSFKjgV7LvtXhIQ23qCwxYcuEqPraK3U6AyS
J4Q+MTINCTInCGk5ACgnIvK2ODARZ4C/HJC1fDa52Q7g+izMxpxZu/Nzmr/TzXba8UcpSENcetYp
vAdOfG5hdbvipglt0ub64igMa6S4hK9LBvkNEqValpNXmMI/JNyJbeB0d0EdU7Z8g0R0rhJYRwHW
MPnas3no10exWxgFKFSYNqd9ndXBFzhsJmOJS2Nys3hHD/z2XvzJR/J8aOfxTLzS7nasjKB3s+9K
GevZi2ywOkr4PtqUzjqi2+bOzM932Xi80Z4PRoNp5Bt0TBb6XZRgfQYgX4dcMVKoroU55dajV4WA
iReFOdBGz8PtMDSBpdidXHgSqSMXxlNp0ai8jNzvyHwv5/1OgVkKhDuYChrSXD73m2z9g8GTdS8J
8OgSA2z95qZbOpx91nhVG5OKhCkx0jrnK9uP8pD5O4hJCrrxFRjDKTpna9Ota+vY9ApdT75zrOLk
bzt3PISFHGS57C+7D4GX2h3qe7yGvKWmPMBcIUe2EpedgqY8mdx7Kd1du7oHxWORko97ar/2aJnJ
PYmw9QITOdTBSzLMyuwHsqJgFt9W34QaZZhISbQmW/HrfqNC1VZMuPNiLOp+zdmBAjx1CrJiezP0
D0hgPwAoOOfbZraeizemb56AN+2KShyUMjchU3C9Kf+a66fVZxZEOrljjNXuadek2Kpp8GMMHFSi
W6b6aG2VcusQO6g4anJx6V8bGHRDtt/dDnGjfZ7vPPT5+0bzfM6610ex46lNAXx5xD3y7E7ynoqr
ffDqcSsNs6kZxsMkRcrwayX+WvADvsmZiqr9EMW2mHuJ6dLkfanrVmrNzkjKc/dncKqxRKnIPp0O
yL7BYT87WRNCdar9f+5xTOM1flDkAe3+HdmS9iOteQLtcdwFi0kKWNg0tGU9vnea8VSRtYrDLSro
67Y7VaaiXKhps8u7QDwkHZ4ermQZkq2dRY05lJQpH41dIzseDCfYB6JD5QSrgwpGjXMJn5jWcHzI
6Fw4j7n/m9h6efhHnKbxvGbRYpGCNkjurLyik4XCfsmoT9BF1yUwHeYLeL4JtoKy9b4M83c6i1pZ
KSWNkpL6wn9rYgNpSutgpNVejD33COx4QY54D1jJG+hCgQcWykndeqQIXCTYSXI/6aMy1pF8aGAW
0E5+ZMwMvRLXB6lV6ueBjvtF51aPCjdxS115P+dGiQsMEUMJ7InMagbgoxmJm/PQsDViUFVXWsIX
JiEmYGUlJTucshvkKb/QO/YXiiw5TERsOT5CHjcqXm704adwQtHuh4p7h5qWLODWCfk0rmABHqWV
jluAzM0gp1FrdFN18G1kgj4FpSOXITTmyXyYkzzeX7+s74Ez9wTuuHb992dSGzSHTHfNUgttegmX
fdmgSGQLXMV0SX/0yP97kggLLOQHY3PdhjpEgJc/9Sx7sJXMSzcZXdV4JsFo7qrL5SH0BX228Gvl
rzbJERJqBWC+wD0lfvAAlcaAcucNZ3uF15RDadBfcnZ3keQ1uwUcWPWv6e8k7x6r0tDMTwe6z4al
k+VjKEYZ2Cd3JssqoMhsFAGXqstHFetHwkeKyh2k7Br5uLi2f2aDdeEGjr7AzsSkhjuzJLxzqwTD
brNQUaTuZBbQe7NCqFZamkRUmpAd0f9uNom2innoVi88HkSUbdASAh3VioTMb6qZhLAqiWY5NSWe
8yqz7TriZElELQEJB4JyH230GxwSGaJJGqSQsW02eZz0cnGQga8yIYFEAtGfOn784r+2UqlFyc4m
nMaFnzupma9cL4Mv7CkxEecx8DCxMpgWZmlKEGksfh90urOsIbpnTLfCSIvl+R5uBjdCYAEbS/yy
quWNKM9VJiW/J+0NPMoqg5awMSVCIjVsF2ZOH9Xa9dzZvQI4VezpG1K3LSL/wZ2e57obeo5IyJyb
R/GCa9+mJcPecYRJmQoPMhU9JUkEO7GtwyKw8syYENQE7+o2wotEzIOoLKda/9jg5NuQ9sh35kz9
XNvBrQsgnyFFGF9EIVtz6u7tG5J5T9Yod3O2JerERyYz7263NNgQC6QJpgNnHNaiwpxGjiK74vp7
aK/9yaSGViGwnkAhAF8c1S+OMXVNRwBZFZ8oCtDkl70pFKHsndIlUV3nQpqSEOF2UN2LD4S/lrpr
NnA3fzpoPHRT+yro6s5AIQc2c4LWHHaIB4HskxSWv4h7URrkB3wiMD2oIT/aXIxJONnWOMENacWV
IjKKOcaegCqEvixHt3BO9FjEIUAEOWp0G6Lakj0P01/xkAQK80LIt2eXk1UsyJmXwEvrJBVMZEOr
NiJmnc9/lw5uuSLYN7kMM1LXw3l9wXOgMRKB8xhKz/+wL0ci1ZLmFSPSaF9gI6RzXm2ywC/orFqj
fZIq2XQi67aVlr3cJ2XoamGEocQWaVPG+lDPMvP0Go/5XNFyNQ2v1bUroCQv6j5/mR/qpLSljyG+
9lC3Y9sRV7t0AAABBAYAAQmqcgAHCwEAASEhAQgMwJHEAAgKAQf2g3QAAAUBGQkAAAAAAAAAAAAR
IQBNAGUAZABpAGEASQBuAGYAbwAuAGEAdQBjAGYAZwAAABkCAAAUCgEAw+ASJWFZ3QEVBgEAIAAA
AAAA

[/cut]
Добавлены глобальные переменные для управления параметрами конвертации gExifFixAnsi = 1, gExifFixFFFD = 1 и режима подсказки gExifBusy = 1, gExifTimeout = 0.

gExifStay = 1 для взаимодействия через файлы, gExifStay = 2 для взаимодействия через устройство вывода. Если оставить 0, то exiftool.exe будет запускаться без режима -StayOpen.

В режиме с файлами добавлен PID для более уникальных имен, чтобы каждая копия ТС работала со своими файлами. Stdout включен по умолчанию. На выходе из Autorun нужно поставить

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

ExifClose()
ExifArgsClose()
AkulaBig
Надеюсь, это поможет вам разобраться. У меня просто времени сейчас практически нет. Расчитывал, что будет больше, но увы.

Добавлено: Вс окт 11, 2026 13:45
AkulaBig
Orion9 писал(а):Один FFFD специально оставлен
Я позже вспомнил, что читал про это. Вопрос снят.
Orion9 писал(а):Вы же сами написали, что можно и с файлами
Я уже со всем разобрался. Выше выложил. А тайм-аут не работает с открытыми колонками. Но все равно спасибо, в копилку закину.