| View previous topic :: View next topic |
| Author |
Message |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Tue Oct 28, 2025 13:51 Post subject: |
|
|
| Loopback wrote: | Ну да, с Ctrl вряд ли удастся случайно что-то утянуть  |
Ну а Гислеру что мешает сделать то же самое?
Кто не в курсе о чем речь, напоминаю ответ маэстро в этой теме.
Ну да, я торопился и забыл написать про CTRL, но что это меняет? Можно и на Shift заменить, результат будет тем же:
| Code: | Switch uMsg
Case WM_LBUTTONDOWN
If BitAND(wParam, 0x0004) Then |
Т.ч. мой вопрос остаётся в силе: ну и где здесь "случайное" перетаскивание кнопок? Что-то я его не наблюдаю.
Более того, можно было и без модификаторов обойтись, но у Гислера своя оконная процедура висит и мешает. В частности это приводит к тому, что при претаскивании кнопки на саму себя происходит ее запуск. Побороть может и получится, но будет сложно, поскольку простой выход из процедуры без вызова оригинальной приводит к другим проблемам.
| Code: | Case WM_LBUTTONDOWN
If BitAND(wParam, 0x0004) Then
MouseGetPos("x","y")
IsDrag = 0
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
Return 1
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
WinSetStyle(0x80000, 5, hWnd)
IsDrag = 0
Return 1
EndIf |
Кстати, вы заметили, что я использовал MakeInt? Руки так и чесались
В общем, хотел я по быстрому сделать модуль, ведь основная функция была уже готова, оставалось только ее разбить на блоки и внести небольшие изменения, но поскольку времени было совсем мало, процесс затянулся.
Однако удалось добиться состояния промежуточной готовности:
 Bars.aucfg | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
Global gDragIndex, gDropIndex
Global gHBarButtons = 0, gHBarDivs = 0
Global gHBarUpdSec = 2, gHBarVerb
Global gHBarName, gHBarFile, gHBarMap = List(), gHBarTxt, gHBarWincmd
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)
Switch uMsg
Case WM_LBUTTONDOWN
If BitAND(wParam, MK_CONTROL) Then
MouseGetPos("x","y")
IsDrag = 0
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
gDragIndex = HBarGetIdx()
#Return 1
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
gDropIndex = HBarGetIdx()
WinSetStyle(0x80000, 5, hWnd)
SetHintParam("ShowHint", "Font", 17, "Arial")
SetHintParam("ShowHint", "BackColor", 0xFF0000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
If WinFromPoint() = hWnd Then
ShowHint("Button Index: " & gDragIndex & " To Index: " & gDropIndex, "", "", 3000, 1)
Else
#ShowHint("Drag operation aborted, "", "", 3000, 1)
EndIf
Sleep(50)
SetHintParam("ShowHint", "Reload")
IsDrag = 0
#Return 1
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()
# состояние 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
gHBarFile = HBarGetFile()
If Not FileExist(gHBarFile) Then Return "Файл панели не найден " & gHBarFile
# загрузка панели
HBarLoad()
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 = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
# загрузка файла в массив
Local aBar = List()
aBar.LoadFromFile(gHBarFile)
# количество кнопок в файле
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 aBar.Count - 1
found = 0
If StrLeft(aBar[j], 6) = "button" Then
found = 1
ElseIf StrLeft(aBar[j], 3) = "cmd" Then
found = 2
EndIf
If found > 0 Then
key = StrLower(StrPart(aBar[j], "=", 1))
val = StrLen(StrPart(aBar[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(aBar, oButton, oCmd)
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded: " & gHBarFile & 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)
# информация о масштабировании экрана
Local nScale = 0, bRes
bRes = DllCall("Shcore.dll\GetScaleFactorForMonitor", "hwnd", hMon, "dword*", @nScale)
# буфер для структуры 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 x, y, w, h, mx, my, idx, row, rows, rowh, bar, txt, b, extra
# координаты и размеры окна панели
WinGetPos("x", "y", "w", "h", hBarWnd)
# координаты указателя мыши
MouseGetPos("mx", "my")
# чтение информации о высоте кнопок
IniRead b %COMMANDER_INI% "Buttonbar" "Buttonheight"
# масштабирование экрана
If nScale > 0 Then b = Round(b*nScale/100,0)
# количество рядов кнопок на панели
rows = Floor(h/b)
# If rows = 0 Then Return "Error number of rows = 0"
# количество дополнительных пикселей
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 & ")" & auCRLF & _
"buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _
"width=" & b & ", " & div & auCRLF & _
"mon=" & HMon & " 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 |
Сейчас подсказка вызывается по Ctrl, Shift и CapsLock. Ctrl добавляет карту панели и имеет возможность перетаскивания кнопок. Пока при перетаскивании показываются только индексы опрации. Пересобрать панель будет делом техники, но сначала нужно добавить дополнительные проверки и провести больше тестов. Например усовершенствовать блок с масштабированием экрана и оптимизировать количество вызовов. Также нужно что-то придумать, как обрабатывать временно загруженную панель, файл которой не находится в корне ТС или подкаталоге \Bars. Сейчас такая панель работать не будет.
| Loopback wrote: | | Думаю, можно и полностью исправить, но тогда придется отказаться от создания диалога с помощью DialogBox и полностью создать свое окно с нуля. |
А откуда уверенность, что это поможет?
| Loopback wrote: | | Что-то может быть, конечно, но проблема с потоком маловероятно что связана с ним. |
Согласен. Я больше имел в виду дурацкие приколы с загрузкой графического объекта.
| Loopback wrote: | | Из плагинов статистики нет, слишком много затрат для реализации. |
То, что некоторые вещи реализовать сложно, это понятно. Но какие сложности с SetHotkeyAction? Разве во время парсинга вы не можете собрать статистику, что привязано к этому вызову? У меня много модулей, и в каждом что-то висит на SetHotkeyAction. Со временем забываешь, что именно. Можно конечно простым поиском по всем файлам найти, но ведь лень же да и не удобно это. Куда лучше было бы вызвать GetState("SetHotkeyAction") и всё увидеть. |
|
| Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1646
|
(Separately) Posted: Tue Oct 28, 2025 14:25 Post subject: |
|
|
| Orion9 wrote: | | Побороть может и получится, но будет сложно, поскольку простой выход из процедуры без вызова оригинальной приводит к другим проблемам. |
Тут еще проблема с x64. Новый вариант не пробовал, но предыдущий валит тотал x64 при выходе. С похожей проблемой я столкнулся, когда пытался делать сабклассинг окна тотала. Ставится-то он без проблем, но уже не снимается и тотал крашится. Т.е. выгружать плагин нельзя. Похоже здесь та же проблема.
| Orion9 wrote: | | А откуда уверенность, что это поможет? |
Я делал тесты, меняя ID кнопки Отмена с IDCANCEL (2) на другой. В этом случае диалог появлялся всегда. Но тогда теряется возможность закрыть окно кнопкой Esc и что-то еще вроде было. При этом диалог, создаваемый DialogBox, имеет свой обработчик клавиш, не позволяющий что-то изменить.
| Orion9 wrote: | | Разве во время парсинга вы не можете собрать статистику, что привязано к этому вызову? |
Нет API для передачи этих данных из плагина. Это дело не пяти минут. Пока слишком много более приоритетных задач. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Tue Oct 28, 2025 20:31 Post subject: |
|
|
| Loopback wrote: | | Новый вариант не пробовал, но предыдущий валит тотал x64 при выходе. |
Похоже, что так. В Win11 это происходит "тихо", даже не сразу заметил. Ну и ладно. Я все-равно этой версией редко пользуюсь, в том числе из-за разных проблем с Autorun.
| Loopback wrote: | | Ставится-то он без проблем, но уже не снимается и тотал крашится. |
C окном ТС вероятно так и есть, однако в моем случае если добавить к секции финализации, то краш уходит даже на Win8:
| Code: | Pragma AutorunFinalizeSection
If gHBarWndProc > 0 Then
DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", hBarWnd, "int", -4, "long_ptr", gHBarWndProc, "ptr")
EndIf |
| Loopback wrote: | | Я делал тесты, меняя ID кнопки Отмена с IDCANCEL (2) на другой. В этом случае диалог появлялся всегда. |
Интересный ход. Возможно из этого получится что-то выжать и обойти проблему, но всё-таки хотелось докапаться до причины, почему это вообще происходит. Сдается мне, что все это может быть связано - вылеты потоков, окон диалога, глючная загрузка bitmap и т.д. Сделал на скорую руку кнопку для теста потока на основе вашей первоначальной функции перебора торрента:
 Hidden text | Code: | RegisterCommand 70508 "TorrentBugTest"
Func TorrentBugTest(lParam)
RunThread("TorrentThreadTest")
EndFunc
Func TorrentThreadTest()
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 20
TorrentInfo(hWnd, i, "d:\Temp\Jinn'sLiveUSB 11.2.2.torrent")
If WinGetState(1, hWnd) = 0 Then
MsgBox("Тестирование прервано", "Autorun", 48)
Return
EndIf
Next
MsgBox("Тестирование успешно завершено", "Autorun", 64)
DllCall("DestroyWindow", "handle", hWnd)
EndFunc
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
Local hHandle = DllCall(sLibName & "\TorrentOpen", "wstr", sFile, "handle")
If hHandle = 0 Then
DllCall("FreeLibrary", "handle", hDll)
Return
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 |
Почему-то был уверен, что баг проявится быстро, однако не всё так просто. У меня используется Jinn'sLiveUSB 11.2.2 на 9800 файлов, но можно прописать любой большой торрент и увеличить количество циклов в For..Next.
В общем, не сразу, но через какое-то время потоки, которые также запущены в фоне (заголовок, подсчет времени воспроизведения, пинг трех адресов и т.д.) начинают отваливаться. Удивительно, но сам поток TorrentThreadTest мне так и не удалось завалить. Видимо он слишком простенький для этого, не использует какие-то критические части Autorun. Но проблема определенно есть.
| Loopback wrote: | | Нет API для передачи этих данных из плагина. Это дело не пяти минут. |
Жалко, конечно, но что поделать. Как-нибудь пока проживем без этого ) |
|
| Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1646
|
(Separately) Posted: Wed Oct 29, 2025 21:36 Post subject: |
|
|
| Orion9 wrote: | | если добавить к секции финализации, то краш уходит |
Я это попробовал в первую очередь, но не помогло. Во всяком случае на 10.
| Orion9 wrote: | | Но проблема определенно есть. |
Ну это понятно. Как появится возможность, буду тестировать. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Thu Oct 30, 2025 20:48 Post subject: |
|
|
| Loopback wrote: | | Я это попробовал в первую очередь, но не помогло. Во всяком случае на 10. |
Если не ошибаюсь, на восьмерке тоже пару раз при выходе возникла ошибка даже с кодом финализации. Т.ч. возможно, что проблема не всегда просто проявляется, как и в случае с MsgBox().
Доделал я функцию drag-n-drop на панели, очень хотелось посмотреть, как она будет работать. Версия чисто DEMO, пока есть еще ряд недоработок, связанных прежде всего с масштабированием экрана. Все работает и при масштабировании, но если поменять размер кнопок, то индекс перестанет правильно определяться. При стандартном dpi проблем нет. В будущем надо будет и других улучшений добавить, например откат действия и бэкап панели. Пока бэкап нужно обязательно делать вручную, а то мало ли что.
В общем, если кто-то будет пробовать, только на свой страх и риск ) Но имхо, само перетаскивание классно смотрится и "ощущатся", жаль, что Гислер не хочет его реализовывать.
 Bars.aucfg | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
Global gDragIndex, gDropIndex
Global gHBarButtons = 0, gHBarDivs = 0
Global gHBarHint = 0, gHBarVerb
Global gHBarList = List(), gHBarMap = List()
Global gHBarName, gHBarFile, gHBarTxt, gHBarWincmd
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)
Switch uMsg
Case WM_LBUTTONDOWN
If IsDrag = 0 And BitAND(wParam, MK_CONTROL) Then
MouseGetPos("x","y")
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
gDragIndex = HBarGetIdx()
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
gDropIndex = HBarGetIdx()
If WinFromPoint() = hWnd Then
If gDragIndex <> gDropIndex Then
If gHBarHint Then ShowDragHint("Index " & gDragIndex & " To Index: " & gDropIndex)
HBarDragnDrop(gDragIndex, gDropIndex)
EndIf
EndIf
WinSetStyle(0x80000, 5, hWnd)
IsDrag = 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
gHBarFile = HBarGetFile()
If Not FileExist(gHBarFile) Then Return "Файл панели не найден " & gHBarFile
# загрузка панели
HBarLoad()
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 = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
# загрузка файла в массив
gHBarList.Count = 0
gHBarList.LoadFromFile(gHBarFile, "ANSI")
# количество кнопок в файле
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)
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded: " & gHBarFile & 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)
# информация о масштабировании экрана
Local nScale = 0, bRes
bRes = DllCall("Shcore.dll\GetScaleFactorForMonitor", "hwnd", hMon, "dword*", @nScale)
# буфер для структуры 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 x, y, w, h, mx, my, idx, row, rows, rowh, bar, txt, b, extra
# координаты и размеры окна панели
WinGetPos("x", "y", "w", "h", hBarWnd)
# координаты указателя мыши
MouseGetPos("mx", "my")
# чтение информации о высоте кнопок
IniRead b %COMMANDER_INI% "Buttonbar" "Buttonheight"
# масштабирование экрана
If nScale > 0 Then b = Round(b*nScale/100,0)
# количество рядов кнопок на панели
rows = Floor(h/b)
# If rows = 0 Then Return "Error number of rows = 0"
# количество дополнительных пикселей
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 & ")" & auCRLF & _
"buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _
"width=" & b & ", " & div & auCRLF & _
"mon=" & HMon & " 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
# временная замена индекса
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, "ANSI")
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)
ShowHint(DragHint, "", "", 3000, 1)
Sleep(10)
SetHintParam("ShowHint", "Reload")
EndFunc |
|
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Sat Nov 01, 2025 00:27 Post subject: |
|
|
Loopback
Почему-то вызов не работает:
| Code: | If DllCall("Ntdll.dll\IsWindows8Point1OrGreater", "bool") Then |
Есть идеи почему? |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Sat Nov 01, 2025 12:54 Post subject: |
|
|
Loopbak
Метод с явным указанием ANSI
| Code: | lst.LoadFromFile(sFile, "ANSI") |
загружает юникодный файл (UTF-16) полностью и без проблем. Так задумано, или ошибка? |
|
| Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1646
|
(Separately) Posted: Sat Nov 01, 2025 19:31 Post subject: |
|
|
| Orion9 wrote: | | Почему-то вызов не работает |
Макрос еrror возвращает ошибку 2 - отсутствие функции в dll.
А всё потому, что это не реальная функция в dll, а враппер. В файле VersionHelpers.h он задается так:
| Code: |
VERSIONHELPERAPI
IsWindows8Point1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
}
VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
DWORDLONG const dwlConditionMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
|
| Orion9 wrote: | | Так задумано, или ошибка? |
Так задумано. Если файл содержит BOM, он всегда читается в кодировке, определяемой BOM. Указываемые здесь значения служат для интерпретации файла без BOM. Наверно, это стоит уточнить в справке. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Sat Nov 01, 2025 20:41 Post subject: |
|
|
И всё-таки я ещё раз спрошу у Гислера: ну и где здесь "случайное" перетаскивание кнопок на панели?
 Hidden text
Ладно, шучу я. Понятно, что он просто не захотел этим заморачиваться, а я взял и заморочился
Последняя версия модуля.
 Bars.aucfg | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
# правый клик с удержанием Ctrl
ControlSetMouseAction /R /K:C 28 "HBarShowMenu"
Global gDragIndex, gDropIndex
Global gHBarButtons = 0, gHBarDivs = 0
Global gHBarHint = 0, gHBarVerb, gHBarCancel, gHBarCancelLoad
Global gHBarName, gHBarFile, gHBarTxt, gHBarCP = "ANSI", gHBarWincmd = 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)
Switch uMsg
Case WM_LBUTTONDOWN
If IsDrag = 0 And BitAND(wParam, MK_CONTROL) Then
MouseGetPos("x","y")
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
gDragIndex = HBarGetIdx()
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
gDropIndex = HBarGetIdx()
If WinFromPoint() = hWnd Then
If gDragIndex <> gDropIndex Then
If gHBarHint Then ShowDragHint("Index " & gDragIndex & " To Index: " & gDropIndex)
HBarDragnDrop(gDragIndex, gDropIndex)
EndIf
EndIf
WinSetStyle(0x80000, 5, hWnd)
IsDrag = 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 Return "Файл панели не найден " & gHBarFile
# загрузка панели
HBarLoad()
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 = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
# загрузка файла в массив
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)
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded: " & gHBarFile & 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 HBarSetCodePage 1' & auCRLF
txt &= 'MENUITEM "Открывать как UTF-16", em_aucmd ' & (gHBarCP = "UTF-16" ? "/C" : "") & ' -1 HBarSetCodePage 2' & 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 |
Добавлена отмена действия и возврат к первоначальной панели, а также возможность создания бэкапов. Исправлено масштабирование экрана. Ветка с загрузкой панели в ANSI или UTF-16 получается не сильно нужна и остается пока недоделанной по причинам описанным выше. Однако важное замечание: если панель хранится в юникоде, по умолчанию она сохраняться будет как ANSI, если не поставить соответствующую галочку в меню. Галочка между сессиями не сохраняется, тоже имейте это в виду. У меня все панели храняться в ANSI, а к модулю я могу еще вернуться не скоро, хотя автосохранение в корректной кодировке само напрашивается.
Окно панели хранит только имя файла, информация о пути недоступна. Поэтому файлы ищутся только в каталоге ТС или подкаталоге \Bars. Если и там, и там есть одинаковое имя файла, это может привести к проблемам.
У Гислера висит своя оконная процедура, во избежание проблем приходится передавать ей управление. Чтобы избавится от клика, которая посылает эта процедура, используется подмена х-координаты указателя мыши:
| Code: | MouseGetPos("x","y")
lParam = MakeInt(y, x + 200, 2) |
Клик происходит на 200 пикселей правее и не приводит к запуску кнопки. Но если используется слишком большое масштабирование, запуск может произойти.
В остальном проблем не замечено. Пользуюсь с большим удовольствием )
| Loopbak wrote: | | А всё потому, что это не реальная функция в dll, а враппер |
Понятно. Спасибо, что разобрались. Хотел было использовать что-то вроде:
| Code: | Local pX, pY
Local nScale = 0, bRes
If DllCall("Ntdll.dll\IsWindows8Point1OrGreater", "bool") Then
bRes = DllCall("Shcore.dll\GetDpiForMonitor", "hwnd", hMon, "int", 0, "uint*", @pX, "uint*", @pY)
bRes = DllCall("Shcore.dll\GetScaleFactorForMonitor", "hwnd", hMon, "dword*", @nScale)
nDPI = pX
EndIf |
Но почитав немного про эти функции и про DPI в целом, понял, что оно того не стоит.
| Loopbak wrote: | | Так задумано. Если файл содержит BOM, он всегда читается в кодировке, определяемой BOM. |
Имхо, правильно задумано. А если во взятом таким образом массиве есть маркер BOM то сохраняться через SaveToFile он тоже будет корректно?
Добавлено спустя 4 минуты:
Забыл написать, что меню вызывается по правому клику мыши с зажатым Ctrl. |
|
| Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1646
|
(Separately) Posted: Sat Nov 01, 2025 22:22 Post subject: |
|
|
| Orion9 wrote: | | В остальном проблем не замечено. |
Ну что же, как минимум с точки зрения "Proof of Concept" неплохо. Работает с указанным ограничением по расположению. Только пришлось добавить /R в IniRead, у меня перенаправление включено.
| Orion9 wrote: | | А если во взятом таким образом массиве есть маркер BOM то сохраняться через SaveToFile он тоже будет корректно? |
Маркер это принадлежность файла, после чтения текста он нигде не сохраняется. В SaveToFile необходимо явно указывать кодировку (если она отличается от умолчальной) и нужно ли записывать BOM. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Sun Nov 02, 2025 00:33 Post subject: |
|
|
| Loopbak wrote: | | Ну что же, как минимум с точки зрения "Proof of Concept" неплохо. |
А с точки зрения чего же ещё? ) Как говорится, могЁм когда умеем. А вот маэстро со своими ответами в стиле "это невозможно" лишь портит себе репутацию. Что вообще значит невозможно? Любой грамотный специалист знает, что нет такого слова в принципе: при правильно настроенном контроллере головного мозга и прямом драйвере руки.sys возможно всё
| Loopbak wrote: | | Только пришлось добавить /R в IniRead, у меня перенаправление включено. |
Ах да, как-то забыл об этом совсем, надо будет подправить в будущих версиях. Хотя кто знает, вдруг Гислеру загорится и он решит сделать свой драгендроп в ТС, тогда этот модуль потеряет в ценности. Правда там еще подсказка о кнопках всплывает, а для меня она значит больше, чем перетаскивание. Впрочем, Гислеру и подсказку ничего не мешает сделать такую же, или почти такую же.
| Loopbak wrote: | | В SaveToFile необходимо явно указывать кодировку (если она отличается от умолчальной) и нужно ли записывать BOM. |
Понятно. В общем, надо будет всё это исправить и учесть, но не в ближайшее время. Сейчас мне нужно, к сожалению, отправиться восвояси. Как говорится, теперь я свободен как udp-пакет в полете Но надеюсь не на долго ) |
|
| Back to top |
|
 |
ZiabrevLV
Joined: 15 Sep 2022 Posts: 2
|
(Separately) Posted: Thu Nov 06, 2025 14:18 Post subject: |
|
|
При выполнении команды:
| Code: |
RegisterCommand 60007 "BarCommand"
Func BarCommand(lParam)
IniWrite %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\Bars\Default_2.bar"
CommandExec cm_Exit 1
EndFunc
|
в wincmd.ini переменная переписываетса на абсолютный путь:
Buttonbar=D:\TotalCommander\Bars\Defaul_2t.bar
Как -то можно поправить, на переменную %COMMANDER_PATH%? |
|
| Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1646
|
(Separately) Posted: Fri Nov 07, 2025 11:50 Post subject: |
|
|
| ZiabrevLV wrote: | | Как -то можно поправить, на переменную %COMMANDER_PATH%? |
Да, добавить переключатель, чтобы значение записывалось как есть:
| Code: |
IniWrite /EV- %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\Bars\Default_2.bar"
|
|
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 944
|
(Separately) Posted: Fri Nov 07, 2025 13:53 Post subject: |
|
|
Loopback
А почему потоки, запускаемые из кнопок и горячих клавиш, не отображаются в GetState? Ведь эти функции тоже в отдельных потоках запускаются, верно? Если да, то какая разница между запуском из кнопки и запуском через RunThread?
Вопросы не на ровном месте. Убрал запуск окна прогресс-бара в отдельном потоке через переменную и условие:
| Code: | Global g_WinThread = 0
If g_WinThread Then
RunThread "WinFindTorrentData"
While g_FindTorrTask = 0
Sleep(50)
Wend
Else
WinFindTorrentData(0)
EndIf |
Окно теперь создается в том же потоке, что и функция запроса FileFindEv, при этом стабильности в х64 значительно прибавилось. Целый час тестировал, операция ни разу не зависла. Правда тотал все-таки один раз упал, а параллельные потоки заголовка и др. продолжали отваливаться и исчезать из GetState, но общая стабильность работы возрасла. Проверить это можно, если вернуть все назад через g_WinThread=1. Как только окно запускается через RunThread, зависания происходят через считанные секунды или минуты.
В общем, оставил запуск без второго потока по умолчания. Из минусов: при захвате и перемещении окна мышью операция поиска на данное время прерывается. Это понятно, т.к. окно создано в том же потоке, что и функция поиска, из которой этому окну посылаются сообщения. Второй минус - в GetState ничего не отображается, а хотелось бы.
Но плюс довольно большой: операция выполняется более стабильно, а значит выбор очевиден. Обновленный модуль:
 Torrent.aucfg | Code: | 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
Global gEvPath = COMMANDER_PATH & "\Everything.exe", gEvAuto = 0, gEvDelay = 100
Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0
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
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
# локальные переменные
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 |
|
|
| Back to top |
|
 |
A55555
Joined: 06 Feb 2011 Posts: 68
|
(Separately) Posted: Fri Nov 07, 2025 15:06 Post subject: |
|
|
| Orion9 wrote: |
Но плюс довольно большой: операция выполняется более стабильно, а значит выбор очевиден. Обновленный модуль:
 Torrent.aucfg | Code: | 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
Global gEvPath = COMMANDER_PATH & "\Everything.exe", gEvAuto = 0, gEvDelay = 100
Global gTorrentDbg = 0, gDbgStep, gCapsReverse = 0
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
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
# локальные переменные
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 |
|
Orion9
спасибо. Сегодня попробую.
Можно ли добавить к этому поиску такую фишку, чтоб "http://" торрента-файла по которому ты только что искал файлы сразу попадала в буфер обмена?
Т.е. можешь сразу идти в браузер и легко попасть на страницу релиза, если тебе это необходимо в силу каких-то причин.
И наверно опционально, потому как предположительно это кому-то может и наоборот помешать, затирая что-то.
Если это не космическое что-то, я не разбираюсь, просто спрашиваю. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|