Autorun
Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер
-
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
А что тут думать? Нужно брать и делать, как вы написали )
Сначала считать ключ CompareTool и проверить путь в его значении: если путь существует, то выполнить cm_CompareFilesByContent, если не существует, то вывести MsgBox с вопросом, нужно ли скачивать WinMerge.
Опционально можно добавить возможность сравнения внутренним инструментом, если пользователь откажется от скачивания.
Небольшой пример:
Код: Выделить всё
RegisterCommand 60050 "CompareTwoFiles"
Func CompareTwoFiles()
Local sTool
# чтение ключа
sTool = IniRead("~/R", COMMANDER_INI, "Configuration", "CompareTool", 0)
# раскрытие переменных окружения в значении ключа, если они есть
sTool = Set(sTool)
# проверка существования файла
If FileExist(sTool) Then
# файл существует
# послать команду сравнения и выйти
SendCommand(2022) # cm_CompareFilesByContent
Return
EndIf
# файл не существует
MsgBox("Инструмент сравнения не найден " & sTool & auCRLF & auCRLF & _
"Загрузить из Интернета?", "Autorun", 3+0+48)
# кнопка "Да" не была нажата, выйти из скрипта
If EXTENDED <> 6 Then Return
# запуск батника для загрузки
ShellExec(COMMANDER_PATH & "\Scripts\WinMergedownload.bat")
EndFuncКстати, вместо батника можно использовать функцию WinInetDownloadFile для загрузки файла прямо из Autorun
Код: Выделить всё
Local url = "https://downloads.sourceforge.net/winmerge/winmerge-2.16.54-x64-exe.zip"
WinInetDownloadFile(url, TEMP & "\winmerge.zip")-
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
Спасибо, работает отлично. Единственное, т.к. сейчас Нет и Отмена делают одно и тоже, то лучше чтобы Нет открывал внутренний инструмент.
На bat\ps1 я неплохо пишу. Это не проблема.Orion9 писал(а): Как у вас со скриптингом
Может тогда лучше упростить? Просто повесить хоткей: нажал - и листер стал размером с окно ТС.Orion9 писал(а): Что касается Листера, если задача стоит добиться, чтобы его окно при открытии имело тот же размер и положение
Может тогда и InfoHeader.aucfg обновите с учетом этой новинки?Добавил переменную gTitleRound для указания количества знаков после точки у сетевого трафика.
Если у вас со скриптами PowerShell получается работать, то уверен, что и с Autorun получится. Вопрос времени.
Чтобы добавить действие на кнопку "Нет", нужно обработать код с номером 7 в макросе EXTENDED. Из справки Autorun на функцию MsgBox:
Код: Выделить всё
После закрытия диалога сообщения функция присвоит макросу EXTENDED числовой код, идентифицирующий нажатую кнопку:
1 «OK»
2 «Отмена»
3 «Прервать»
4 «Повтор»
5 «Пропустить»
6 «Да»
7 «Нет»
10 «Повторить»
11 «Продолжить»
Возможные сценарии при нажатии клавиши ESC:
Если есть кнопка «Отмена», функция присвоит 2 макросу EXTENDED.
Если нет кнопок «Отмена» и «OK», никакого эффекта не будет.
Если нет кнопки «Отмена», но есть «OK», функция присвоит 1 макросу EXTENDED.
Функция не всегда работает на 64-битной версии Total Commander. Код: Выделить всё
# кнопка "Нет"
If EXTENDED = 7 Then SendCommand(2040) #cm_IntCompareFilesByContent
# кнопка "Да" не была нажата, выйти из скрипта
If EXTENDED <> 6 Then Return Можно так сделать. Нужно зарегистрировать отдельный код на функцию SyncListerPosition и создать для него em_команду или сразу повесить функцию на хоткей.Может тогда лучше упростить? Просто повесить хоткей: нажал - и листер стал размером с окно ТС.
Код: Выделить всё
RegisterCommand 60051 "SyncListerPosition"
# Alt + "["
SetHotkeyAction /K:A /V:219 SyncListerPosition
Func SyncListerPosition()
Static c = 0
If IniRead("~/R", COMMANDER_INI, "Lister", "Maximized", 0) = 0 Then
WinGetPos("x", "y", "w", "h")
IniWrite("~/R", COMMANDER_INI, "Lister", "x", x)
IniWrite("~/R", COMMANDER_INI, "Lister", "y", y)
IniWrite("~/R", COMMANDER_INI, "Lister", "dx", w)
IniWrite("~/R", COMMANDER_INI, "Lister", "dy", h)
c += 4
#ShowHint("Запись ключей: " & c, SYSINFO_DESKTOPWIDTH/2-50, SYSINFO_DESKTOPHEIGHT/2, 1000, 1)
EndIf
EndFunc
Так он уже обновлен в последней версии на предыдущей странице, пропустили?Может тогда и InfoHeader.aucfg обновите с учетом этой новинки?
-
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
c += 4 не обнуляется, потому что цель была увидеть общее количество записей в ини-файл. Подключите последний модуль, захватите окно за заголовок и поводите им по экрану — количество записей быстро перевалит за сотни. Я боялся, что будет еще больше. Хотя в принципе все это не страшно.
Так вы и хотели вроде с погодой, даже ссылку давали на githubТам он вместе с погодой (ну или я не туда смотрю).
Код: Выделить всё
gInfoHeader = gTitle & ' ' & Date("d MMMM, ddd") & '. CPU: ' & StrFormat("%02d", GetCPUUsage()) & '% RAM: ' & GetMemStats() & '% NET: ↓ ' & Round(nRecvSpeed / 1000, 2) & ' ↑ ' & Round(nSendSpeed / 1000, 2) & ' mb/s' Вчера спешил, не подумал, что окно листера надо искать. Должно быть примерно так:
Код: Выделить всё
SetHotkeyAction /K:C /H:0 /DM /S "AlignListerWindow"
Func AlignListerWindow()
If IniRead("~/R", COMMANDER_INI, "Lister", "Maximized", 0) = 0 Then
WinGetPos("x", "y", "w", "h")
IniWrite("~/R", COMMANDER_INI, "Lister", "x", x)
IniWrite("~/R", COMMANDER_INI, "Lister", "y", y)
IniWrite("~/R", COMMANDER_INI, "Lister", "dx", w)
IniWrite("~/R", COMMANDER_INI, "Lister", "dy", h)
Local hWnd = WinFind(0, "TLister")
If hWnd = 0 Then Return ShowHint("Окно листера не найдено")
WinSetPos(x, y, w, h, "", hWnd)
EndIf
EndFunc -
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
Хм... не уверен что лучше. Нужно подумать. Но вот навеяло другую идея походу: почему "в спокойствии" у нас "0" ? По идеи должно быть "0.0".Orion9 писал(а): Т.е. вместо 1 теперь 2. Так реально лучше смотрится, на мой взгляд.
Это строка тут лишняя, ИМХО.Orion9 писал(а): If hWnd = 0 Then Return ShowHint("Окно листера не найдено")
Да, круто что окно Листера теперь сразу подстраивается, единственное, теряет фокус (возможно, нужно просто передать его обратно).
Нужно просто отформатировать строку через StrFormat. Т.е. вместо:
Код: Выделить всё
Round(nRecvSpeed / 1000, 2) & ' ↑ ' & Round(nSendSpeed / 1000, 2) & ' mb/s'Код: Выделить всё
StrFormat("%02.2f", Round(nRecvSpeed / 1000, 2)) & ' ↑ ' & StrFormat("%02.2f", Round(nSendSpeed / 1000, 2)) & ' mb/s'Ну если лишняя, можно убрать )Это строка тут лишняя, ИМХО.
А что на счет фокуса? У меня он не теряется. Но если у вас теряется, можно принудительно его вернуть через WinSetState:
Код: Выделить всё
WinSetPos(x, y, w, h, "", hWnd)
WinSetState(23, hWnd)[cut]
Код: Выделить всё
RegisterCommand 60043 "CompareTwoFiles"
RegisterCommand 60044 "CompareTwoFilesDialog"
Func CompareTwoFiles()
Local sTool, nDialogMode = 1
# чтение ключа
sTool = IniRead("~/R", COMMANDER_INI, "Configuration", "CompareTool", "")
# раскрытие переменных окружения
sTool = Set(sTool)
# проверка существования файла
If FileExist(sTool) Then
# файл существует
# послать команду сравнения и выйти
SendCommand(2022) # cm_CompareFilesByContent
Return
EndIf
If nDialogMode = 1 Then Return CompareTwoFilesDialog(sTool)
# файл не существует
MsgBox("Инструмент сравнения не найден " & sTool & auCRLF & auCRLF & _
"Загрузить из Интернета?", "Autorun", 3+0+48)
# нажата кнопка "Нет"
If EXTENDED = 7 Then SendCommand(2040) # cm_IntCompareFilesByContent
# не нажата кнопка "Да", выйти из скрипта
If EXTENDED <> 6 Then Return
# запуск батника для загрузки
ShellExec(COMMANDER_PATH & "\Scripts\WinMergeDownload.bat")
EndFunc
Func CompareTwoFilesDialog(FilePath)
Local lst = List()
lst.Add("Сравнить внутренним" & auLF & "Будет использован внутренний инструмент сравнения Total Commander")
lst.Add("Загрузить из интернета" & auLF & "https://winmerge.org/downloads/?lang=ru")
Local nRet = MsgBoxLinks(1, "Инструмент сравнения не найден", FilePath, lst)
Free(lst)
If nRet = 2 Then Return
If nRet = 1001 Then
SendCommand(2040) # cm_IntCompareFilesByContent
Else
ShellExec(COMMANDER_PATH & "\Scripts\WinMergeDownload.bat")
EndIf
EndFunc
#{
Icon:
1 - Warning
2 - Error
3 - Information
4 - Shield
ByRef: List() of 1-3 elements
Returns: 1001-1003, 2 for cancel
#}
Func MsgBoxLinks(Icon, Header, Message, ByRef Links)
If Abs(Icon) > 4 Then Icon = 2
Icon = 65536 - Icon
If Links.Count = 0 Then Return MsgBox("Links not specified")
Local Res, Ret
Local buf = Buffer(auX64 ? 160 : 96), _
ttl = Buffer(16), _
hdr = Buffer(StrLen(Header)*2+2), _
msg = Buffer(StrLen(Message)*2+2), _
lnk = Buffer(auX64 ? 48 : 24)
ttl.SetStr("Autorun" & Chr(0))
hdr.SetStr(Header & Chr(0))
msg.SetStr(Message & Chr(0))
Local b1 = Buffer(512), b2 = Buffer(512), b3 = Buffer(512)
b1.Zero()
b2.Zero()
b3.Zero()
b1.SetStr(Links[0] & Chr(0))
If Links.Count > 1 Then b2.SetStr(Links[1] & Chr(0))
If Links.Count > 2 Then b3.SetStr(Links[2] & Chr(0))
lnk.Zero()
lnk.SetNum(0, "int", 1001, _
"ptr", b1.ptr, _
"int", 1002, _
"ptr", b2.ptr, _
"int", 1003, _
"ptr", b3.ptr)
buf.Zero()
buf.SetNum(0, "uint", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"handle", 0, _
"dword", 0x0019, _
"dword", 0x0008, _
"ptr", ttl.ptr, _
"ptr", Icon, _
"ptr", hdr.ptr, _
"ptr", msg.ptr, _
"uint", Links.Count, _
"ptr", lnk.ptr)
Res = DllCall("TaskDialogIndirect", _
"ptr", buf.ptr, _
"int*", @Ret, _
"int*", 0, _
"bool*", 0, "hresult")
Free(buf, ttl, hdr, msg, lnk, b1, b2, b3)
Return Ret
EndFuncНу не персик ли?
[cut="PS"]Если персик не нужен, можно изменить nDialogMode = 1 на любое значение[/cut]
-
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
Пока так тестирую:Orion9 писал(а): Может вам так больше понравится.
Код: Выделить всё
StrFormat("%02.1f", Round(nRecvSpeed / 1000, 1)) & ' ↑ ' & StrFormat("%02.1f", Round(nSendSpeed / 1000, 1)) & ' mb/s'Код: Выделить всё
WinSetState(23, hWnd)https://www.upload.ee/files/19062762/TC.11.56.7z.html
[cut="Warning"]Сайт находится в 16-20 Кб блоке. С территории России без средств обхода скачать архив не получится. Адрес площадки пока не меняю, вдруг блокировку еще снимут. [/cut]
Обновил модуль Icons.aucfg.
[cut]
Код: Выделить всё
Pragma IncludeOnce
# 64000-65000
Global TrayShow = 0, TrayLog = List()
Global Tray1001 = 0, Tray1002 = 0, Tray1003 = 0, Tray1010 = 0
Global gNotifyIcon = COMMANDER_EXE
#Global gNotifyIcon = COMMANDER_PATH & "\Ini\Newsbar\notify-yes.ico"
# регистрация уникальных кодов
Global Code1003 = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1003", "uint")
Global Code1010 = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1010", "uint")
# коды кнопок
RegisterCommand 64000 "ToggleTrayIcon"
RegisterCommand 64001 "ChangeTrayIcon"
RegisterCommand 64002 "NotifyInfo"
RegisterCommand 64003 "RotateIcon"
# функции обратного вызова
SetMessageAction /P 99999 "AutorunTrayAction"
SetMessageAction /P %"Code1003" "MinTrayAction"
SetMessageAction /P %"Code1010" "TrayNotifyInfo"
# сворачивание в трей
ControlSetMouseAction /K:C /L /H:8 0 "MinimizeToTray"
# иконки окна уведомлений
Const NIIF_NONE = 0x00000000, _
NIIF_INFO = 0x00000001, _
NIIF_WARNING = 0x00000002, _
NIIF_ERROR = 0x00000003, _
NIIF_USER = 0x00000004
# без звука
Const NIIF_NOSOUND = 0x00000010
# большая иконка
Const NIIF_LARGE_ICON = 0x00000020
# сообщения окна уведомлений
Const NIN_BALLOONSHOW = 0x402, _
NIN_BALLOONHIDE = 0x403, _
NIN_BALLOONTIMEOUT = 0x404, _
NIN_BALLOONUSERCLICK = 0x405, _
NIN_POPUPOPEN = 0x406, _
NIN_POPUPCLOSE = 0x407
# флаги структуры
Const NIF_MESSAGE = 0x00000001, _
NIF_ICON = 0x00000002, _
NIF_TIP = 0x00000004, _
NIF_STATE = 0x00000008, _
NIF_INFO = 0x00000010
# системные сообщения
Const WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
WM_LBUTTONDBLCLK = 0x0203, _
WM_RBUTTONDOWN = 0x0204, _
WM_RBUTTONUP = 0x0205, _
WM_RBUTTONDBLCLK = 0x0206, _
WM_MBUTTONDOWN = 0x0207, _
WM_MBUTTONUP = 0x0208, _
WM_MBUTTONDBLCLK = 0x0209
# старт
TrayIcon()
# главная иконка
Func TrayIcon()
Local ico, idx = 0
# чтение конфигурации
IniRead TrayShow %AUTORUN_INI% "TrayIcon" "Show" 1
If Not TrayShow Then
Return
EndIf
IniRead ico %AUTORUN_INI% "TrayIcon" "Icon"
IniRead idx %AUTORUN_INI% "TrayIcon" "Index" 0
# раскрытие переменной окружения
ico = Set(ico)
# откат к умолчаниям
If ico = "" Or Not FileExist(ico) Then
idx = 0
ico = COMMANDER_EXE
EndIf
Local sHint = "Autorun " & FileGetVersion(AUTORUN_PATH & "\Autorun.wdx", "FileVersion")
If auX64 Then sHint &= " x64"
# дескриптор иконки
Local hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", ico, "uint", idx, "ptr")
# установка в трей с идентификатором 1001
If NotifyIcon("add", 1001, 99999, hIco, sHint) Then Tray1001 = 1
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco)
EndFunc
# главная иконка Autorun
# функция обратного вызова
Func AutorunTrayAction(hWnd, uMsg, wParam, lParam)
Local bCtrl = IsPressed(0x11)
Switch lParam
# движение над иконкой
Case WM_MOUSEMOVE
If LAST_HINT_WINDOW = 0 Then
If bCtrl Then ShowHint(GetState("threads"), "", "", 2000, 1)
EndIf
# левый клик
Case WM_LBUTTONDOWN
If bCtrl Then
ClipPut(GetState("threads"))
ShowHint(GetState("threads"))
#ShowDarkHint(GetState("threads"))
Return
EndIf
AutorunMenu(0)
# правый клик
Case WM_RBUTTONDOWN
If bCtrl Then
ShowDarkHint(GetState("libs"))
Else
ShowSetEnviroments()
EndIf
# клик по сообщению
Case NIN_BALLOONUSERCLICK
MsgBox("Baloon click")
#WinSetState(23)
# клик "закрыть сообщение"
Case NIN_BALLOONTIMEOUT
MsgBox("Time-out")
EndSwitch
EndFunc
# иконка уведомлений
Func TrayNotifyInfo(hWnd, uMsg, wParam, lParam)
Switch lParam
Case WM_LBUTTONDOWN
ShowPopupMenu /D /F "TrayNotifyInfoMenu"
Case WM_RBUTTONDOWN
#NotifyIcon("delete", 1010)
Case NIN_BALLOONUSERCLICK
Case NIN_BALLOONTIMEOUT
EndSwitch
EndFunc
# меню уведомлений
Func TrayNotifyInfoMenu()
Local txt, nIco, sIco, sTime, sInfo, sType, sFunc, i = 0, j = 0
For i = TrayLog.Count - 1 To 0 Step -1
nIco = -1
sIco = "-1"
sTime = StrPart(TrayLog[i], Chr(0), 1)
sInfo = StrPart(TrayLog[i], Chr(0), 2)
sType = StrPart(TrayLog[i], Chr(0), 4)
If BitAND(sType, 3) = 1 Then
nIco = 76
ElseIf BitAND(sType, 3) = 2 Then
nIco = 79
ElseIf BitAND(sType, 3) = 3 Then
nIco = 93
EndIf
If nIco <> -1 Then sIco = "imageres.dll," & nIco
sFunc = "TrayNotifyItem " & i & " " & nIco
txt &= 'MENUITEM "' & sTime & " " & sInfo & '", em_aucmd ' & sIco & " " & sFunc & auCRLF
j += 1
If j = 30 Then Break
Next
If TrayLog.Count = 0 Then txt &= 'MENUITEM "<Пусто>", em_aucmd' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Копировать", em_aucmd -1 TrayNotifyCopy' & auCRLF
txt &= 'MENUITEM "Скрыть иконку", em_aucmd -1 NotifyIcon "delete" 1010' & auCRLF
Return txt
EndFunc
Func TrayNotifyItem(nItem, nIco)
Local nFlag
Local sInfo = StrPart(TrayLog[nItem], Chr(0), 2)
Local sText = StrPart(TrayLog[nItem], Chr(0), 3)
Switch nIco
Case 76
nFlag = 64
Case 79
nFlag = 48
Case 93
nFlag = 16
Else
nFlag = ''
EndSwitch
MsgBox(sText, sInfo, nFlag)
EndFunc
Func TrayNotifyCopy()
Local txt = TrayLog.Text
txt = StrReplace(txt, Chr(0), ";")
ClipPut(txt)
ShowTransHint("Скопировано в буфер")
EndFunc
# переключение иконки
Func ToggleTrayIcon(lParam)
If Tray1001 > 0 Then
IniWrite %AUTORUN_INI% "TrayIcon" "Show" 0
If NotifyIcon("delete", 1001) Then Tray1001 = 0
Else
IniWrite %AUTORUN_INI% "TrayIcon" "Show" 1
TrayIcon()
EndIf
If Tray1001 > 0 Then
ShowTransHint("Иконка включена")
Else
ShowTransHint("Иконка отключена")
EndIf
EndFunc
# иконка свернутого окна
Func MinTrayAction(hWnd, uMsg, wParam, lParam)
If lParam = WM_LBUTTONDOWN Then
If NotifyIcon("delete", 1003) Then Tray1003 = 0
WinSetState(5)
WinSetState(23)
ElseIf lParam = WM_RBUTTONDOWN Then
EndIf
EndFunc
# сворачивание
Func MinimizeToTray()
Local sHint = "Click to restore Total Commander"
Local hIcon = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
If hIcon = 0 Then
MsgBox("Не удалось получить дескриптор иконки", "Autorun", 48)
Return
EndIf
If NotifyIcon("add", 1003, Code1003, hIcon, sHint) Then Tray1003 = 1
WinSetState(0)
EndFunc
# тестовая функция
Func ChangeTrayIcon(lParam)
Static sDLL = GetKnownFolderPath("System") & "\shell32.dll", i = 10
If Tray1001 = 0 Then
ShowHint("Иконка отключена")
Return
EndIf
i += 1
Local hIco
hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sDLL, "uint", i, "ptr")
If IsPressed(0x11) Then
If NotifyIcon("add", 1002, 99999, hIco, "Autorun #2", "Second icon added", "Autorun", NIIF_INFO) Then
Tray1002 = 1
EndIf
Else
If IsPressed(0x12) Then hIco = 0
NotifyIcon("set", 1001, 99999, hIco, "", "Icon changed to shell32.dll, " & i, "", NIIF_WARNING)
Sleep(2000)
NotifyIcon("set", 1001,, hIco,, "Icon changed to shell32.dll, " & i,, NIIF_ERROR)
EndIf
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
# тест уведомлений
Func NotifyInfo(lParam)
Local bCtrl = IsPressed(0x11)
Static i = 0
i += 1
If i > 3 Then i = 1
If bCtrl Then i = 1
If i = 1 Then
NotifyInfoMessage("Test message", "Test 1", NIIF_INFO)
If Not bCtrl Then Return
Sleep(2000)
EndIf
If bCtrl Or i = 2 Then
txt = "Pragma Include %COMMANDER_PATH%\Ini\Scripts\Test.aucfg"
NotifyInfoMessage(txt, "Test 2", NIIF_WARNING + NIIF_NOSOUND)
If Not bCtrl Then Return
Sleep(2000)
EndIf
If bCtrl Or i = 3 Then
txt = "Test message line 1" & auCRLF & "Test message line 2"
NotifyInfoMessage(txt, "Test 3", NIIF_ERROR)
EndIf
EndFunc
# проверка существования иконки
# функция имеет проблемы на Win10
Func IsIconOnTray(uId)
Local rc = Buffer(16) # RECT
rc.Zero()
Local id = Buffer(auX64 ? 40 : 28)
id.Zero()
If auX64 Then
id.SetNum(0, "dword", id.size)
id.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
id.SetNum(16, "uint", uId)
Else
id.SetNum(0, "dword", id.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", uId)
EndIf
Local hr = DllCall("Shell32.dll\Shell_NotifyIconGetRect", "ptr", id.ptr, "ptr", rc.ptr)
Free(id, rc)
Return hr = 0 ? true : false
EndFunc
#{
Вызов системных уведомлений:
InfoText - текст уведомления (255 символов)
InfoTitle - текст заголовка уведомления (63 символов)
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Функция использует идентификатор "1010"
#}
Func NotifyInfoMessage(InfoText, InfoTitle = "Autorun", InfoType = 0)
Local Offset = auX64 ? 40 : 24, sIcon
Static buf = Buffer(auPtrSize = 4 ? 956 : 976)
Static nFlags = BitOR(NIF_MESSAGE, NIF_ICON, NIF_INFO, NIF_TIP)
If FileExist(gNotifyIcon) Then
sIcon = gNotifyIcon
Else
sIcon = COMMANDER_EXE
EndIf
Static hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sIcon, "uint", 0, "ptr")
NotifyIcon("delete", 1010)
buf.Zero()
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", 1010, _
"uint", nFlags, _
"uint", Code1010)
buf.SetNum(32, "ptr", hIco)
buf.SetNum(296, "dword", 1, _
"dword", 1)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", 1010, _
"uint", nFlags, _
"uint", Code1010, _
"ptr", hIco)
buf.SetNum(280, "dword", 1, _
"dword", 1)
EndIf
buf.SetStr("Notify Messages" & Chr(0), Offset)
buf.SetStr(StrLeft(InfoText, 255) & Chr(0), Offset + 264) # 256 + 4 + 4
Offset += 264
If InfoTitle <> "" Then
buf.SetStr(StrLeft(InfoTitle, 63) & Chr(0), Offset + 516) # 512 + 4
EndIf
Offset += 516
If InfoType > 0 Then
buf.SetNum(Offset + 128, "dword", InfoType) # 128
EndIf
TrayLog.Add(Time() & Chr(0) & InfoTitle & Chr(0) & InfoText & Chr(0) & InfoType)
Tray1010 = 1
Return DllCall("Shell32.dll\Shell_NotifyIconW", "uint", 0, "ptr", buf.ptr)
EndFunc
#{
Добавление иконки в трей:
sAction - тип действия ("add", "set", "delete")
uID - внутренний уникальный идентификатор иконки
nCallback - код зарегистрированного сообщения для функции обратного вызова
hIcon - дескриптор иконки (только для "add")
sTip - текст подсказки в трее
sText - текст уведомления (только для "add" и "set")
sTitle - текст заголовка уведомления
nType - флаги NIIF_* (изменение вида и поведения окна уведомлений)
https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
#}
Func NotifyIcon(sAction, uID, nCallback = 0, hIcon = 0, sTip = "", sText = "", sTitle = "", nType = 0)
Local nAction, nFlags
Static TIP_MAXCHAR = 127, INFO_MAXCHAR = 255, TITLE_MAXCHAR = 63
Static buf = Buffer(auPtrSize = 4 ? 956 : 976)
buf.Zero()
nFlags = BitOR( hIcon = 0 ? 0 : NIF_ICON, _
nCallback = 0 ? 0 : NIF_MESSAGE, _
StrLen(sTip) = 0 ? 0 : NIF_TIP, _
StrLen(sText) = 0 ? 0 : NIF_INFO )
Switch sAction
Case "add"
nAction = 0
Case "set"
nAction = 1
Case "delete"
nAction = 2
Else
Return
EndSwitch
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", uID, _
"uint", nFlags, _
"uint", nCallback)
buf.SetNum(32, "ptr", hIcon)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", uID, _
"uint", nFlags, _
"uint", nCallback, _
"ptr", hIcon)
EndIf
Local nOffset = auX64 ? 40 : 24 # PtrSize*2 + 4*4 + padding for X64
If sTip <> 0 Then
buf.SetStr(StrLeft(sTip, TIP_MAXCHAR) & Chr(0), nOffset)
EndIf
If sText <> 0 Then
nOffset += 264
buf.SetStr(StrLeft(sText, INFO_MAXCHAR) & Chr(0), nOffset) # 256 + 4 + 4
If sTitle <> 0 Then
buf.SetStr(StrLeft(sTitle, TITLE_MAXCHAR) & Chr(0), nOffset + 516) # 512 + 4
EndIf
If nType > 0 Then
buf.SetNum(nOffset + 644, "dword", nType) # 128
EndIf
EndIf
Return DllCall("Shell32.dll\Shell_NotifyIconW", "uint", nAction, "ptr", buf.ptr, "bool")
EndFunc
Global ROTATE_THREAD = 0
Func RotateIcon()
If ROTATE_THREAD > 0 Then
ROTATE_THREAD = 0
Return
EndIf
RunThread("ThreadRotateIcon", IsPressed(0x11))
EndFunc
Func ThreadRotateIcon(FileIcons)
ROTATE_THREAD = 1
Local hIcon = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
While ROTATE_THREAD > 0
Sleep(150)
If FileIcons Then
IconRotateDraw()
Else
RotateDeviceContext()
EndIf
Wend
SendMessage(AUTORUN_TCHANDLE, 0x80, 0, hIcon)
WinRedraw(2)
EndFunc
Func IconRotateDraw()
Static nIco = 0
nIco += 1
If nIco > 4 Then nIco = 1
Local sFile = COMMANDER_PATH & "\Icons\TC\" & nIco & ".ico"
Local hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sFile, _
"uint", 0, _
"ptr")
Local hWnd = WinFind(AUTORUN_TCHANDLE, _
(AUTORUN_TCARCH = 32 ? "TMyPanel" : "Window"), _
(AUTORUN_TCARCH = 32 ? 6 : 10))
# Local hWnd = RequestInfo(15)
# hDC = DllCall("GetDC", "ptr", hWnd, "ptr")
Local hDC = DllCall("GetWindowDC", "ptr", hWnd, "ptr")
Local x, y, w, h
WinGetPos("x", "y", "w", "h", hWnd)
DllCall("DrawIconEx", _
"ptr", hDC, _
"int", w - 20, _
"int", 1, _
"ptr", hIco, _
"int", 16, _
"int", 16, _
"uint", 0, _
"ptr", 0, _
"uint", 0x0003)
SendMessage(AUTORUN_TCHANDLE, 0x80, 0, hIco)
SendMessage(AUTORUN_TCHANDLE, 0x80, 1, hIco)
DllCall("ReleaseDC", "ptr", AUTORUN_TCHANDLE, "ptr", hDC)
DllCall("DestroyIcon", "ptr", hIco)
EndFunc
Func RotateDeviceContext()
Static c = 0
c += 1
If c > 4 Then c = 1
Local x, y, w, h
Local hIco = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
Local hWnd = WinFind(AUTORUN_TCHANDLE, _
(AUTORUN_TCARCH = 32 ? "TMyPanel" : "Window"), _
(AUTORUN_TCARCH = 32 ? 6 : 10))
Local DC = DllCall("GetDC", "int", 0)
Local nDPI = DllCall("GetDeviceCaps", "handle", DC, "int", 88)
Local nScale = DllCall("MulDiv", "int", 100, "int", nDPI, "int", 96)
Local nSize = Round(16*nScale/100,0)
# Local hWnd = RequestInfo(15)
Local hdcWndDC = DllCall("GetWindowDC", "ptr", hWnd, "ptr")
Local hdcMemDC = DllCall("CreateCompatibleDC", "ptr", hdcWndDC, "ptr")
Local hdcBltDC = DllCall("CreateCompatibleDC", "ptr", hdcWndDC, "ptr")
Local hbmDB1 = DllCall("CreateCompatibleBitmap", "ptr", hdcWndDC, "int", nSize, "int", nSize,"ptr")
Local hbmDB2 = DllCall("CreateCompatibleBitmap", "ptr", hdcWndDC, "int", nSize, "int", nSize,"ptr")
DllCall("SelectObject", "ptr", hdcMemDC, "ptr", hbmDB1, "ptr")
DllCall("SelectObject", "ptr", hdcBltDC, "ptr", hbmDB2, "ptr")
DllCall("DrawIconEx", _
"ptr", hdcMemDC, _
"int", 1, _
"int", 1, _
"ptr", hIco, _
"int", nSize, _
"int", nSize, _
"uint", 0, _
"ptr", 0, _
"uint", 0x0003)
Local pt = Buffer(24)
pt.Zero()
If c = 1 Then
pt.SetNum(0, "int", nSize, "int", 0, _
"int", 0, "int", 0, _
"int", nSize, "int", nSize)
ElseIf c = 2 Then
pt.SetNum(0, "int", nSize, "int", nSize, _
"int", nSize, "int", 0, _
"int", 0, "int", nSize)
ElseIf c = 3 Then
pt.SetNum(0, "int", 0, "int", nSize, _
"int", nSize, "int", nSize, _
"int", 0, "int", 0)
ElseIf c = 4 Then
pt.SetNum(0, "int", 0, "int", 0, _
"int", 0, "int", nSize, _
"int", nSize, "int", 0)
EndIf
DllCall("PlgBlt", _
"ptr", hdcBltDC, _
"ptr", pt.Ptr, _
"ptr", hdcMemDC, _
"int", 0, _
"int", 0, _
"int", nSize, _
"int", nSize, _
"ptr", 0, _
"int", 0, "int", 0)
WinGetPos("x", "y", "w", "h", hWnd)
DllCall("BitBlt", _
"ptr", hdcWndDC, _
"int", w - 20, _
"int", 2, _
"int", nSize, _
"int", nSize, _
"ptr", hdcBltDC, _
"int", 1, _
"int", 1, _
"dword", 13369376)
DllCall("DeleteObject", "ptr", hbmDB1)
DllCall("DeleteObject", "ptr", hbmDB2)
DllCall("DeleteObject", "ptr", hdcMemDC)
DllCall("DeleteObject", "ptr", hdcBltDC)
DllCall("ReleaseDC", "ptr", AUTORUN_TCHANDLE, "ptr", hdcWndDC)
EndFuncВ модуле есть две универсальные функции для показа системных уведомлений и создания иконок в трее: NotifyInfoMessage и NotifyIcon. Коды кнопок 64000-64002 тестирую функционал. Созданные идентификаторы иконок нужно добавить в секцию финализации, чтобы при выхода из ТС они не оставались висеть в трее.
[cut="Pragma AutorunFinalizeSection"]
Код: Выделить всё
# удаление иконок
If Tray1001 > 0 Then NotifyIcon("delete", 1001)
If Tray1002 > 0 Then NotifyIcon("delete", 1002)
If Tray1003 > 0 Then NotifyIcon("delete", 1003)
If Tray1010 > 0 Then NotifyIcon("delete", 1010)Модуль можно накатить на тот, что в сборке, для удобного и быстрого теста.
-
FallenAngel
- Сообщения: 47
- Зарегистрирован: Вт дек 30, 2025 20:01
Почему просто не использовать приличный хостинг? terabox.com, mega.nz или pixeldrain.com ?Orion9 писал(а):Перезаливка.
Добавляйте небольшое описание в самом начале файла, модуль возможно и интересный, но не ясно что он делает (как и остальные 13к строк).Orion9 писал(а):Обновил модуль Icons.aucfg.
Повторюсь, намного полезнее (понятнее, удобнее, логичнее, ...) было бы выкладывать просто модулями. Возможно и найдется самурай, который скачает сборку и осилит часть написанного... но это 1-2 юзера (с огромным запасом свободного времени) и не более.
Cамурай звучит громо, скорее фрик, как я )FallenAngel писал(а):Возможно и найдется самурай, который скачает сборку и осилит часть написанного
А я ведь предупреждал Loopback, что у нас с Autorun всё всьерёз и надолго, а он мне не верил ) Могу только повторить свой пледж и коммитмент:
[cut]Till death us do part, Auto
Первый всё в том же 16 Кб блоке, остальные, судя по всему, в белых списках, но требуют регистрацию, а оно мне вроде как не надо.FallenAngel писал(а):terabox.com, mega.nz или pixeldrain.com
Сделать перманентную ссылку на том же гугл диске (или любом другом диске) не проблема. Но не раньше, чем Loopback сделает перманентную ссылку на финальную версию Autorun
А пока все это для тестов и эксперементов. Если кто-то может извлечь из этого пользу — без проблем. Буду только рад, что помимо меня кому-то ещё пригодилось.
Ранний функционал довольно хорошо документирован, просто на последние модули я не нашел возможности сделать описание. Думал, сейчас у меня будет большое окно и смогу наверстать упущенное, но нет, судя по всему, опять не получится.FallenAngel писал(а):Добавляйте небольшое описание в самом начале файла, модуль возможно и интересный, но не ясно что он делает (как и остальные 13к строк).
Но не все так плохо. В этом топике осталось практически всё, правда мотать придется чуть дальше.
Конкретно по этому модулю. Имхо, он неплохо документирован самими комментариями. Да, возможно, сейчас вам так не кажется, но со временем все прояснится, если вы не бросите заниматься Autorun.
Когда-то, глянув на этот модуль, я подумал, надо быть реально повернутым, чтобы полностью в нем разобраться. Однако сейчас я на него смотрю и он мне кажется довольно простым и понятным. Одна мальнькая ремарка: с тех пор прошло два года
Так что верно говорят, что путь осилит идущий, а нет кто с него сходит или топчется на месте)
P.s. Ссылка на модуль за CloudFlare, т.ч. приложу его сюда.
[cut]
Код: Выделить всё
;https://www.autohotkey.com/boards/viewtopic.php?t=113308
;======================================================================================================================
; ToolTipOptions - additional options for ToolTips
;
; Tooltip control -> https://learn.microsoft.com/en-us/windows/win32/controls/tooltip-control-reference
; TTM_SETMARGIN = 1050
; TTM_SETTIPBKCOLOR = 1043
; TTM_SETTIPTEXTCOLOR = 1044
; TTM_SETTITLEW = 1057
; WM_SETFONT = 0x30
; SetClassLong() -> https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongw
; ======================================================================================================================
Class ToolTipOptions {
; -------------------------------------------------------------------------------------------------------------------
Static HTT := DllCall("User32.dll\CreateWindowEx", "UInt", 8, "Str", "tooltips_class32", "Ptr", 0, "UInt", 3
, "Int", 0, "Int", 0, "Int", 0, "Int", 0, "Ptr", A_ScriptHwnd, "Ptr", 0, "Ptr", 0, "Ptr", 0)
Static SWP := CallbackCreate(ObjBindMethod(ToolTipOptions, "_WNDPROC_"), , 4) ; subclass window proc
Static OWP := 0 ; original window proc
Static ToolTips := Map()
; -------------------------------------------------------------------------------------------------------------------
Static BkgColor := ""
Static TktColor := ""
Static Icon := ""
Static Title := ""
Static HFONT := 0
Static Margins := ""
; -------------------------------------------------------------------------------------------------------------------
Static Call(*) => False ; do not create instances
; -------------------------------------------------------------------------------------------------------------------
; Init() - Initialize some class variables and subclass the tooltip control.
; -------------------------------------------------------------------------------------------------------------------
Static Init() {
If (This.OWP = 0) {
This.BkgColor := ""
This.TktColor := ""
This.Icon := ""
This.Title := ""
This.Margins := ""
If (A_PtrSize = 8)
This.OWP := DllCall("User32.dll\SetClassLongPtr", "Ptr", This.HTT, "Int", -24, "Ptr", This.SWP, "UPtr")
Else
This.OWP := DllCall("User32.dll\SetClassLongW", "Ptr", This.HTT, "Int", -24, "Int", This.SWP, "UInt")
OnExit(ToolTipOptions._EXIT_, -1)
Return This.OWP
}
Else
Return False
}
; -------------------------------------------------------------------------------------------------------------------
; Reset() - Close all existing tooltips, delete the font object, and remove the tooltip's subclass.
; -------------------------------------------------------------------------------------------------------------------
Static Reset() {
If (This.OWP != 0) {
For HWND In This.ToolTips.Clone()
DllCall("DestroyWindow", "Ptr", HWND)
This.ToolTips.Clear()
If This.HFONT
DllCall("DeleteObject", "Ptr", This.HFONT)
This.HFONT := 0
If (A_PtrSize = 8)
DllCall("User32.dll\SetClassLongPtrW", "Ptr", This.HTT, "Int", -24, "Ptr", This.OWP, "UPtr")
Else
DllCall("User32.dll\SetClassLongW", "Ptr", This.HTT, "Int", -24, "Int", This.OWP, "UInt")
This.OWP := 0
Return True
}
Else
Return False
}
; -------------------------------------------------------------------------------------------------------------------
; SetColors() - Set or remove the text and/or the background color for the tooltip.
; Parameters:
; BkgColor - color value like used in Gui.BackColor(...)
; TxtColor - see above.
; -------------------------------------------------------------------------------------------------------------------
Static SetColors(BkgColor := "", TxtColor := "") {
This.BkgColor := BkgColor = "" ? "" : BGR(BkgColor)
This.TxtColor := TxtColor = "" ? "" : BGR(TxtColor)
BGR(Color, Default := "") { ; converts colors to BGR
; HTML Colors (BGR)
Static HTML := {AQUA: 0xFFFF00, BLACK: 0x000000, BLUE: 0xFF0000, FUCHSIA: 0xFF00FF, GRAY: 0x808080,
GREEN: 0x008000, LIME: 0x00FF00, MAROON: 0x000080, NAVY: 0x800000, OLIVE: 0x008080,
PURPLE: 0x800080, RED: 0x0000FF, SILVER: 0xC0C0C0, TEAL: 0x808000, WHITE: 0xFFFFFF,
YELLOW: 0x00FFFF}
If HTML.HasProp(Color)
Return HTML.%Color%
If (Color Is String) && IsXDigit(Color) && (StrLen(Color) = 6)
Color := Integer("0x" . Color)
If IsInteger(Color)
Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16)
Return Default
}
}
; -------------------------------------------------------------------------------------------------------------------
; SetFont() - Set or remove the font used by the tooltip.
; Parameters:
; FntOpts - font options like Gui.SetFont(Options, ...)
; FntName - font name like Gui.SetFont(..., Name)
; -------------------------------------------------------------------------------------------------------------------
Static SetFont(FntOpts := "", FntName := "") {
Static HDEF := DllCall("GetStockObject", "Int", 17, "UPtr") ; DEFAULT_GUI_FONT
Static LOGFONTW := 0
If (FntOpts = "") && (FntName = "") {
If This.HFONT
DllCall("DeleteObject", "Ptr", This.HFONT)
This.HFONT := 0
LOGFONTW := 0
}
Else {
If (LOGFONTW = 0) {
LOGFONTW := Buffer(92, 0)
DllCall("GetObject", "Ptr", HDEF, "Int", 92, "Ptr", LOGFONTW)
}
HDC := DllCall("GetDC", "Ptr", 0, "UPtr")
LOGPIXELSY := DllCall("GetDeviceCaps", "Ptr", HDC, "Int", 90, "Int")
DllCall("ReleaseDC", "Ptr", HDC, "Ptr", 0)
If (FntOpts != "") {
For Opt In StrSplit(RegExReplace(Trim(FntOpts), "\s+", " "), " ") {
Switch StrUpper(Opt) {
Case "BOLD": NumPut("Int", 700, LOGFONTW, 16)
Case "ITALIC": NumPut("Char", 1, LOGFONTW, 20)
Case "UNDERLINE": NumPut("Char", 1, LOGFONTW, 21)
Case "STRIKE": NumPut("Char", 1, LOGFONTW, 22)
Case "NORM": NumPut("Int", 400, "Char", 0, "Char", 0, "Char", 0, LOGFONTW, 16)
Default:
O := StrUpper(SubStr(Opt, 1, 1))
V := SubStr(Opt, 2)
Switch O {
Case "C":
Continue ; ignore the color option
Case "Q":
If !IsInteger(V) || (Integer(V) < 0) || (Integer(V) > 5)
Throw ValueError("Option Q must be an integer between 0 and 5!", -1, V)
NumPut("Char", Integer(V), LOGFONTW, 26)
Case "S":
If !IsNumber(V) || (Number(V) < 1) || (Integer(V) > 255)
Throw ValueError("Option S must be a number between 1 and 255!", -1, V)
NumPut("Int", -Round(Integer(V + 0.5) * LOGPIXELSY / 72), LOGFONTW)
Case "W":
If !IsInteger(V) || (Integer(V) < 1) || (Integer(V) > 1000)
Throw ValueError("Option W must be an integer between 1 and 1000!", -1, V)
NumPut("Int", Integer(V), LOGFONTW, 16)
Default:
Throw ValueError("Invalid font option!", -1, Opt)
}
}
}
}
NumPut("Char", 1, "Char", 4, "Char", 0, LOGFONTW, 23) ; DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS
NumPut("Char", 0, LOGFONTW, 27) ; FF_DONTCARE
If (FntName != "")
StrPut(FntName, LOGFONTW.Ptr + 28, 32)
If !(HFONT := DllCall("CreateFontIndirectW", "Ptr", LOGFONTW, "UPtr"))
Throw OSError()
If This.HFONT
DllCall("DeleteObject", "Ptr", This.HFONT)
This.HFONT := HFONT
}
}
; -------------------------------------------------------------------------------------------------------------------
; SetMargins() - Set or remove the margins used by the tooltip
; Parameters:
; L, T, R, B - left, top, right, and bottom margin in pixels.
; -------------------------------------------------------------------------------------------------------------------
Static SetMargins(L := 0, T := 0, R := 0, B := 0) {
If ((L + T + R + B) = 0)
This.Margins := 0
Else {
This.Margins := Buffer(16, 0)
NumPut("Int", L, "Int", T, "Int", R, "Int", B, This.Margins)
}
}
; -------------------------------------------------------------------------------------------------------------------
; SetTitle() - Set or remove the title and/or the icon displayed on the tooltip.
; Parameters:
; Title - string to be used as title.
; Icon - icon to be shown in the ToolTip.
; This can be the number of a predefined icon (1 = info, 2 = warning, 3 = error
; (add 3 to display large icons on Vista+) or a HICON handle.
; -------------------------------------------------------------------------------------------------------------------
Static SetTitle(Title := "", Icon := "") {
Switch {
Case (Title = "") && (Icon != ""):
This.Icon := Icon
This.Title := " "
Case (Title != "") && (Icon = ""):
This.Icon := 0
This.Title := Title
Default:
This.Icon := Icon
This.Title := Title
}
}
; -------------------------------------------------------------------------------------------------------------------
; For internal use only!
; -------------------------------------------------------------------------------------------------------------------
Static _WNDPROC_(hWnd, uMsg, wParam, lParam) {
; WNDPROC -> https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc
Switch uMsg {
Case 0x0411: ; TTM_TRACKACTIVATE - just handle the first message after the control has been created
If This.ToolTips.Has(hWnd) && (This.ToolTips[hWnd] = 0) {
If (This.BkgColor != "")
SendMessage(1043, This.BkgColor, 0, hWnd) ; TTM_SETTIPBKCOLOR
If (This.TxtColor != "")
SendMessage(1044, This.TxtColor, 0, hWnd) ; TTM_SETTIPTEXTCOLOR
If This.HFONT
SendMessage(0x30, This.HFONT, 0, hWnd) ; WM_SETFONT
If (Type(This.Margins) = "Buffer")
SendMessage(1050, 0, This.Margins.Ptr, hWnd) ; TTM_SETMARGIN
If (This.Icon != "") || (This.Title != "")
SendMessage(1057, This.Icon, StrPtr(This.Title), hWnd) ; TTM_SETTITLE
This.ToolTips[hWnd] := 1
}
Case 0x0001: ; WM_CREATE
DllCall("UxTheme.dll\SetWindowTheme", "Ptr", hWnd, "Ptr", 0, "Ptr", StrPtr(""))
This.ToolTips[hWnd] := 0
Case 0x0002: ; WM_DESTROY
This.ToolTips.Delete(hWnd)
}
Return DllCall(This.OWP, "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam, "UInt")
}
; -------------------------------------------------------------------------------------------------------------------
Static _EXIT_(*) {
If (ToolTipOptions.OWP != 0)
ToolTipOptions.Reset()
}
}Если вкратце.
Функция NotifyIcon принимает следующие параметры:
Код: Выделить всё
sAction - тип действия ("add", "set", "delete")
uID - внутренний уникальный идентификатор иконки
nCallback - код зарегистрированного сообщения для функции обратного вызова
hIcon - дескриптор иконки (только для "add")
sTip - текст подсказки в трее
sText - текст уведомления (только для "add" и "set")
sTitle - текст заголовка уведомления
nType - флаги NIIF_* (изменение вида и поведения окна уведомлений)
Func NotifyIcon(sAction, uID, nCallback = 0, hIcon = 0, sTip = "", sText = "", sTitle = "", nType = 0)Все сводится к одному вызову, например:
Код: Выделить всё
NotifyIcon("add", 1005, gCode, hIco, "Иконка Autorun")uID - это просто внутренний код иконки, взятый буквально от балды. Приложение может держать в трее несколько иконок, оболочке Windows и нам самим нужно как-то их отличать. Код может быть любым числом. Здесь он 1005.
nCallback - это код, который использует оболочка, когда она посылает сообщения о событиях в трее назад приложению. И снова этот код мы должны сами придумать, но только в определенном диапазоне. Чтобы не забивать этим голову, мы просим систему выделить нам уникальный незанятый код. Каким именно будет этот код, нам не важно, мы просто запоминаем его в переменной gCode:
Код: Выделить всё
Global gCode = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1005", "uint")Код: Выделить всё
SetMessageAction /P %"gCode" "TestrayAction"Код: Выделить всё
Func TestrayAction(hWnd, uMsg, wParam, lParam)
If lParam = WM_LBUTTONDOWN Then
MsgBox("Клик по иконке")
ElseIf lParam = WM_RBUTTONDOWN Then
ShowPopupMenu("~/D", COMMANDER_PATH & "\Bars\Vertical.bar")
EndIf
EndFuncОстается только иконка. Дескриптор иконки hIcon можно получать по-разному. Самый простой способ — послать сообщение окну ТС с кодом 0x7f, тогда тотал вернет дескриптор своей иконки:
Код: Выделить всё
hIcon = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)Код: Выделить всё
sIco = GetKnownFolderPath("System") & "\shell32.dll"
hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sIco, "uint", 15, "ptr")
Нам, в свою очередь, остается передать этот дескриптор функции NotifyIcon вместе с другими параметрами. Итого, полученный код будет выглядеть так:
Код: Выделить всё
# регистрация кода для функции обратного вызова
Global gCode = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1005", "uint")
# привязка функции обратного вызова к полученному коду
SetMessageAction /P %"gCode" "TestrayAction"
# функция обратного вызова
Func TestrayAction(hWnd, uMsg, wParam, lParam)
If lParam = WM_LBUTTONDOWN Then
#MsgBox("Клик по иконке")
NotifyIcon("set", 1005, gCode, hIco, "", "Test message", "", NIIF_WARNING)
ElseIf lParam = WM_RBUTTONDOWN Then
ShowPopupMenu("~/D", COMMANDER_PATH & "\Bars\Vertical.bar")
EndIf
EndFunc
# путь к иконке
sIco = GetKnownFolderPath("System") & "\shell32.dll"
# получение дескриптора иконки с индексом 15
hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sIco, "uint", 15, "ptr")
# установка в трей с идентификатором 1005
NotifyIcon("add", 1005, gCode, hIco, "Иконка Autorun")Однако, чтобы этот фрагмент кода заработал самостоятельно, без привязки к модулю Icons.aucfg, необходимо перенести из него все константы и, собственно, саму функцию NotifyIcon:
[cut]
Код: Выделить всё
# иконки окна уведомлений
Const NIIF_NONE = 0x00000000, _
NIIF_INFO = 0x00000001, _
NIIF_WARNING = 0x00000002, _
NIIF_ERROR = 0x00000003, _
NIIF_USER = 0x00000004
# без звука
Const NIIF_NOSOUND = 0x00000010
# большая иконка
Const NIIF_LARGE_ICON = 0x00000020
# сообщения окна уведомлений
Const NIN_BALLOONSHOW = 0x402, _
NIN_BALLOONHIDE = 0x403, _
NIN_BALLOONTIMEOUT = 0x404, _
NIN_BALLOONUSERCLICK = 0x405, _
NIN_POPUPOPEN = 0x406, _
NIN_POPUPCLOSE = 0x407
# флаги структуры
Const NIF_MESSAGE = 0x00000001, _
NIF_ICON = 0x00000002, _
NIF_TIP = 0x00000004, _
NIF_STATE = 0x00000008, _
NIF_INFO = 0x00000010
# системные сообщения
Const WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
WM_LBUTTONDBLCLK = 0x0203, _
WM_RBUTTONDOWN = 0x0204, _
WM_RBUTTONUP = 0x0205, _
WM_RBUTTONDBLCLK = 0x0206, _
WM_MBUTTONDOWN = 0x0207, _
WM_MBUTTONUP = 0x0208, _
WM_MBUTTONDBLCLK = 0x0209
#{
Добавление иконки в трей:
sAction - тип действия ("add", "set", "delete")
uID - внутренний уникальный идентификатор иконки
nCallback - код зарегистрированного сообщения для функции обратного вызова
hIcon - дескриптор иконки (только для "add")
sTip - текст подсказки в трее
sText - текст уведомления (только для "add" и "set")
sTitle - текст заголовка уведомления
nType - флаги NIIF_* (изменение вида и поведения окна уведомлений)
https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
#}
Func NotifyIcon(sAction, uID, nCallback = 0, hIcon = 0, sTip = "", sText = "", sTitle = "", nType = 0)
Local nAction, nFlags
Static TIP_MAXCHAR = 127, INFO_MAXCHAR = 255, TITLE_MAXCHAR = 63
Static buf = Buffer(auPtrSize = 4 ? 956 : 976)
buf.Zero()
nFlags = BitOR( hIcon = 0 ? 0 : NIF_ICON, _
nCallback = 0 ? 0 : NIF_MESSAGE, _
StrLen(sTip) = 0 ? 0 : NIF_TIP, _
StrLen(sText) = 0 ? 0 : NIF_INFO )
Switch sAction
Case "add"
nAction = 0
Case "set"
nAction = 1
Case "delete"
nAction = 2
Else
Return
EndSwitch
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", uID, _
"uint", nFlags, _
"uint", nCallback)
buf.SetNum(32, "ptr", hIcon)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", uID, _
"uint", nFlags, _
"uint", nCallback, _
"ptr", hIcon)
EndIf
Local nOffset = auX64 ? 40 : 24 # PtrSize*2 + 4*4 + padding for X64
If sTip <> 0 Then
buf.SetStr(StrLeft(sTip, TIP_MAXCHAR) & Chr(0), nOffset)
EndIf
If sText <> 0 Then
nOffset += 264
buf.SetStr(StrLeft(sText, INFO_MAXCHAR) & Chr(0), nOffset) # 256 + 4 + 4
If sTitle <> 0 Then
buf.SetStr(StrLeft(sTitle, TITLE_MAXCHAR) & Chr(0), nOffset + 516) # 512 + 4
EndIf
If nType > 0 Then
buf.SetNum(nOffset + 644, "dword", nType) # 128
EndIf
EndIf
Return DllCall("Shell32.dll\Shell_NotifyIconW", "uint", nAction, "ptr", buf.ptr, "bool")
EndFunc
# регистрация кода для функции обратного вызова
Global gCode = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1005", "uint")
# привязка функции обратного вызова к полученному коду
SetMessageAction /P %"gCode" "TestrayAction"
# функция обратного вызова
Func TestrayAction(hWnd, uMsg, wParam, lParam)
If lParam = WM_LBUTTONDOWN Then
If IsPressed(0x11) Then
NotifyIcon("set", 1005, gCode, hIco, "", "Test message", "", NIIF_WARNING)
Return
EndIf
MsgBox("Клик по иконке")
ElseIf lParam = WM_RBUTTONDOWN Then
ShowPopupMenu("~/D", COMMANDER_PATH & "\Bars\Vertical.bar")
EndIf
EndFunc
# путь к иконке
sIco = GetKnownFolderPath("System") & "\shell32.dll"
# получение дескриптора иконки с индексом 15
hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sIco, "uint", 15, "ptr")
# установка в трей с идентификатором 1005
NotifyIcon("add", 1005, gCode, hIco, "Иконка Autorun")Работает у вас?
В этот код я добавил обработку CTRL:
Код: Выделить всё
If IsPressed(0x11) Then
NotifyIcon("set", 1005, gCode, hIco, "", "Test message", "", NIIF_WARNING)
Return
EndIfКод: Выделить всё
#{
Вызов системных уведомлений:
InfoText - текст уведомления (255 символов)
InfoTitle - текст заголовка уведомления (63 символов)
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Функция использует идентификатор "1010"
#}
Func NotifyInfoMessage(InfoText, InfoTitle = "Autorun", InfoType = 0)[cut]
Код: Выделить всё
lobal gNotifyIcon = COMMANDER_EXE
#Global gNotifyIcon = COMMANDER_PATH & "\Ini\Newsbar\notify-yes.ico"
# регистрация уникального кода
Global Code1010 = DllCall("RegisterWindowMessageW", "wstr", "TrayNotify1010", "uint")
SetMessageAction /P %"Code1010" "TrayNotifyInfo"
# иконка уведомлений
Func TrayNotifyInfo(hWnd, uMsg, wParam, lParam)
Switch lParam
Case WM_LBUTTONDOWN
ShowPopupMenu /D /F "TrayNotifyInfoMenu"
Case WM_RBUTTONDOWN
#NotifyIcon("delete", 1010)
Case NIN_BALLOONUSERCLICK
Case NIN_BALLOONTIMEOUT
EndSwitch
EndFunc
# меню уведомлений
Func TrayNotifyInfoMenu()
Local txt, nIco, sIco, sTime, sInfo, sType, sFunc, i = 0, j = 0
For i = TrayLog.Count - 1 To 0 Step -1
nIco = -1
sIco = "-1"
sTime = StrPart(TrayLog[i], Chr(0), 1)
sInfo = StrPart(TrayLog[i], Chr(0), 2)
sType = StrPart(TrayLog[i], Chr(0), 4)
If BitAND(sType, 3) = 1 Then
nIco = 76
ElseIf BitAND(sType, 3) = 2 Then
nIco = 79
ElseIf BitAND(sType, 3) = 3 Then
nIco = 93
EndIf
If nIco <> -1 Then sIco = "imageres.dll," & nIco
sFunc = "TrayNotifyItem " & i & " " & nIco
txt &= 'MENUITEM "' & sTime & " " & sInfo & '", em_aucmd ' & sIco & " " & sFunc & auCRLF
j += 1
If j = 30 Then Break
Next
If TrayLog.Count = 0 Then txt &= 'MENUITEM "<Пусто>", em_aucmd' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Копировать", em_aucmd -1 TrayNotifyCopy' & auCRLF
txt &= 'MENUITEM "Скрыть иконку", em_aucmd -1 NotifyIcon "delete" 1010' & auCRLF
Return txt
EndFunc
Func TrayNotifyItem(nItem, nIco)
Local nFlag
Local sInfo = StrPart(TrayLog[nItem], Chr(0), 2)
Local sText = StrPart(TrayLog[nItem], Chr(0), 3)
Switch nIco
Case 76
nFlag = 64
Case 79
nFlag = 48
Case 93
nFlag = 16
Else
nFlag = ''
EndSwitch
MsgBox(sText, sInfo, nFlag)
EndFunc
Func TrayNotifyCopy()
Local txt = TrayLog.Text
txt = StrReplace(txt, Chr(0), ";")
ClipPut(txt)
ShowTransHint("Скопировано в буфер")
EndFunc
#{
Вызов системных уведомлений:
InfoText - текст уведомления (255 символов)
InfoTitle - текст заголовка уведомления (63 символов)
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Функция использует идентификатор "1010"
#}
Func NotifyInfoMessage(InfoText, InfoTitle = "Autorun", InfoType = 0)
Local Offset = auX64 ? 40 : 24, sIcon
Static buf = Buffer(auPtrSize = 4 ? 956 : 976)
Static nFlags = BitOR(NIF_MESSAGE, NIF_ICON, NIF_INFO, NIF_TIP)
If FileExist(gNotifyIcon) Then
sIcon = gNotifyIcon
Else
sIcon = COMMANDER_EXE
EndIf
Static hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sIcon, "uint", 0, "ptr")
NotifyIcon("delete", 1010)
buf.Zero()
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", 1010, _
"uint", nFlags, _
"uint", Code1010)
buf.SetNum(32, "ptr", hIco)
buf.SetNum(296, "dword", 1, _
"dword", 1)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", 1010, _
"uint", nFlags, _
"uint", Code1010, _
"ptr", hIco)
buf.SetNum(280, "dword", 1, _
"dword", 1)
EndIf
buf.SetStr("Notify Messages" & Chr(0), Offset)
buf.SetStr(StrLeft(InfoText, 255) & Chr(0), Offset + 264) # 256 + 4 + 4
Offset += 264
If InfoTitle <> "" Then
buf.SetStr(StrLeft(InfoTitle, 63) & Chr(0), Offset + 516) # 512 + 4
EndIf
Offset += 516
If InfoType > 0 Then
buf.SetNum(Offset + 128, "dword", InfoType) # 128
EndIf
TrayLog.Add(Time() & Chr(0) & InfoTitle & Chr(0) & InfoText & Chr(0) & InfoType)
Tray1010 = 1
Return DllCall("Shell32.dll\Shell_NotifyIconW", "uint", 0, "ptr", buf.ptr)
EndFuncЭто только сами функции и их вызов. В реальности код разрастается из-за различных условий и проверок. Например, вряд ли есть необходимость всегда держать иконку в трее, а значит надо как-то учитывать это при запуске — считывать ключ из ини-файла, смотреть его значение, загружать или не загружать иконку в зависимости от этого значения и т.д. Именно поэтому модуль получился больше, чем эти две функции, ведь это мой рабочий модуль, т.е. модуль, который я использую у себя в ТС. Кое-что там лишнее и переплетается с другими модулями, поэтому сам модуль не универсальный, универсальны только эти две функции.
Как-то так
Раньше была возможность разделить панель на три области, чтобы отображать в каждой области свою подсказку. Теперь при удержании Shift в подсказке также отображаются данные из плагинов, тем самым общее количество подсказок возросло до шести!
Если добавить сюда переключение полей (функция реализована в модуле как SetHintFields, вызывается по Alt+F12), количество подсказок можно увеличивать до беспредела
Однако пока Alt+F12 ограничивается только переключением на ExifHint и JoinHint, при этом JoinHint больше не актульна, хотя может быть использована в качестве примера вывода данных в окно подсказки.
Алгоритм вывода данных из плагинов ранее был реализован в функции JoinHint. Я перенес его в модуль MediaInfo.aucfg и добавил небольшие изменения.
Как это работает. В подсказку выводятся все непустые поля из заранее указанных плагинов в файле WdxHint.cfg. Пример файла:
Код: Выделить всё
File.wdx;UnicodeTest.wdx;FileX.wdx
Permissions.wdx;NTLinks.wdx;NTFSFileStreams.wdx
anytag.wdx
Script.wdx;WinScriptsAdv.wdxКод: Выделить всё
Global gHintPipe = "", _
gHintClipb = true, _
gHintLines = 60, _
gHintWait = 0, _
gHintShift = "duration.txt", _
gHintCaps = true
Global gHintWdx = 0, _
gHintWdxList = List(), _
gHintWdxCfg = COMMANDER_PATH & "\Ini\WdxHint.cfg"
Global gHintLayout = List(10, 75, 15), _
gHintContent = List("size.txt", "Inform", "hint.txt"), _
gHintSleep = List(0, 0, 0)gHintPipe, gHintWdx и gHintWdxList используются для внутренних целей, менять их значения не нужно. Остальных переменные описавались ранее, как и примеры их использования:
[cut]gHintClipb - копировать в буфер всю подсказку при отображении в страничном режиме
gHintLines - число строк подсказки, больше 60 быть не может
gHintWait - задержка для всех секций перед отображением
gHintShift - шаблон для смены "на лету", только для левой секции
gHintCaps - если false, подсказка будет отображаться без CapsLock или Ctrl
gHintLayout - размер каждой секции в процентах
gHintContent - шаблон для каждой секции; если пустой "", в секцию ничего не попадает, кроме самой подсказки ТС или проводника; если "Inform" - стандартный отчет MediaInfo; если имя файла, то шаблон из файла (файлы должны находиться в каталоге MediaInfo.dll, существование файла не проверяется, в случае отсутствия сообщений об ошибке не будет, отобразится сырой результат отчета MediaInfo).
gHintSleep - задержка для каждой секции.
Пара примеров.
Код: Выделить всё
gHintCaps = false
gHintLayout = List(15, 70, 15)
gHintContent = List("Inform", "", "duration.txt")
gHintSleep = List(500, 0, 0)Код: Выделить всё
gHintCaps = true
gHintLayout = List(10, 80, 10)
gHintContent = List("size.txt", "hint.txt", "Inform")
gHintSleep = List(0, 0, 0)Дополнительно шаблон в левой секции может меняться "на лету" с тем, что указан в gHintShift. Комбинация для смены Alt+5.
Кроме Alt+5 действуют еще 4 комбинации: Alt+1..Alt+4. Каждая из этих комбинаций выводит одну страницу последней подсказки и опционально копирует ее в буфер. Такое применение удобно на очень больших подсказках, которые обрезаются на 60-и строках, оставляя одну страницу просмотра. Нажав Alt+2 можно переместиться на вторую страницу и так далее. Всего четыре страницы.[/cut]
В подсказке используются шаблоны MediaInfo: текстовые файлы с собственной разметкой и синтаксисом. Внося изменения в эти файлы, можно подстраивать под себя вывод из MediaInfo.dll. Сейчас используются три шаблона hint.txt, size.txt и duration.txt, можно создать другие или полностью передлать эти.
[cut="hint.txt"]General;"Name: %FileName%.%FileExtension%\nSize: %FileSize/String4%\n[Duration: %Duration%]\n[Duration: %Duration/String1%]\n[Duration: %Duration/String5%]\n
[General: %BitRate/String%][(%BitRate_Mode%)][, %Format%]$if(%Cover%,\, Cover)$if(%IsStreamable%,\, Streamable)[, %FrameRate/String%]"\n
Video;Video #%StreamKindID%: [%Width%x%Height%][, %Format%][(%Format/Family%)][, %Language%][, %AspectRatio/String% (%AspectRatio%)][, %Resolution/String%][, %FrameRate/String%][, %BitRate/String%][(%BitRate_Mode%)]\n
Video_Begin;
Video_Middle;
Video_End;\n
Audio;Audio #%StreamKindID%: [%Channel(s)%ch][, %SamplingRate/String%][, %BitRate/String%][ (%BitRate_Mode%)][, %Format%][, %Format_Profile%][, %Language%][, %FrameRate/String%]\n
Audio_Begin;
Audio_Middle;
Audio_End;\n
Text;Text #%StreamKindID%: %Format%[, %Language/String3%][, %StreamSize/String3%][, %BitRate/String%][, %FrameRate/String%][, %SamplingRate/String%]\n
Text_End;\n
Chapters;Chapters #%StreamKindID%: %Total% chapters\n
Image;Image #%StreamKindID%: [%Width%x%Height%pix][, %Format%][, %StreamSize/String5%][, %ColorSpace% (%ChromaSubsampling%)][, %BitDepth/String%][, %ColorSpace_ICC%]\n
Menu;Menu #%StreamKindID%: [%MenuID/String%][, Format:%Format/String%][ Chapters: \[%Chapters_Pos_Begin%-%Chapters_Pos_End%\]][/cut]
[cut="size.txt"]General;Name: %FileName%.%FileExtension%\r\nSize: %FileSize/String4%\r\nGeneral: [%StreamSize/String%]\r\n
Video;Video #%StreamKindID%: [%StreamSize/String%]\r\n
Audio;Audio #%StreamKindID%: %StreamSize/String%[ - %Language/String%][ | %Title%]\r\n[/cut]
[cut="duration.txt"]General;Name: %FileName%.%FileExtension%\r\nSize: %FileSize/String4%\r\nGeneral:\r\n [Duration: %Duration%]\r\n [Duration: %Duration/String1%]\r\n [Duration: %Duration/String5%]\r\n
Video;Video #%StreamKindID%: \r\n [Duration: %Duration%]\r\n [Duration: %Duration/String1%]\r\n [Duration: %Duration/String5%]\r\n
Audio;Audio #%StreamKindID%: \r\n [Duration: %Duration%]\r\n [Duration: %Duration/String1%]\r\n [Duration: %Duration/String5%]\r\n[/cut]
Шаблоны должны находиться в каталоге библиотеки.
Также в файле autorun.cfg самой первой строкой должны быть прописаны поля подсказки в инструкции Pragma AutorunPluginFields:
Код: Выделить всё
Pragma AutorunPluginFields "C1:::MediaHint" "C2:::MediaHint" "C3:::MediaHint" "C4:::MediaHint" "C5:::MediaHint" "C6:::MediaHint" "C7:::MediaHint" "C8:::MediaHint" "C9:::MediaHint" "C10:::MediaHint" "C11:::MediaHint" "C12:::MediaHint" "C13:::MediaHint" "C14:::MediaHint" "C15:::MediaHint" "C16:::MediaHint" "C17:::MediaHint" "C18:::MediaHint" "C19:::MediaHint" "C20:::MediaHint" "C21:::MediaHint" "C22:::MediaHint" "C23:::MediaHint" "C24:::MediaHint" "C25:::MediaHint" "C26:::MediaHint" "C27:::MediaHint" "C28:::MediaHint" "C29:::MediaHint" "C30:::MediaHint" "C31:::MediaHint" "C32:::MediaHint" "C33:::MediaHint" "C34:::MediaHint" "C35:::MediaHint" "C36:::MediaHint" "C37:::MediaHint" "C38:::MediaHint" "C39:::MediaHint" "C40:::MediaHint" "C41:::MediaHint" "C42:::MediaHint" "C43:::MediaHint" "C44:::MediaHint" "C45:::MediaHint" "C46:::MediaHint" "C47:::MediaHint" "C48:::MediaHint" "C49:::MediaHint" "C50:::MediaHint" "C51:::MediaHint" "C52:::MediaHint" "C53:::MediaHint" "C55:::MediaHint" "C55:::MediaHint" "C56:::MediaHint" "C57:::MediaHint" "C58:::MediaHint" "C59:::MediaHint" "C60:::MediaHint"Возможные сценарии.
1) Если в секции нет других расширений. Достаточно просто применить готовый вариант:
[cut]
Код: Выделить всё
[HintsCustomField]
0exts=*.*
0fields=[=autorun.C1]\n[=autorun.C2]\n[=autorun.C3]\n[=autorun.C4]\n[=autorun.C5]\n[=autorun.C6]\n[=autorun.C7]\n[=autorun.C8]\n[=autorun.C9]\n[=autorun.C10]\n[=autorun.C11]\n[=autorun.C12]\n[=autorun.C13]\n[=autorun.C14]\n[=autorun.C15]\n[=autorun.C16]\n[=autorun.C17]\n[=autorun.C18]\n[=autorun.C19]\n[=autorun.C20]\n[=autorun.C21]\n[=autorun.C22]\n[=autorun.C23]\n[=autorun.C24]\n[=autorun.C25]\n[=autorun.C26]\n[=autorun.C27]\n[=autorun.C28]\n[=autorun.C29]\n[=autorun.C30]
1exts=*.*
1fields=[=autorun.C31]\n[=autorun.C32]\n[=autorun.C33]\n[=autorun.C34]\n[=autorun.C35]\n[=autorun.C36]\n[=autorun.C37]\n[=autorun.C38]\n[=autorun.C39]\n[=autorun.C40]\n[=autorun.C41]\n[=autorun.C42]\n[=autorun.C43]\n[=autorun.C44]\n[=autorun.C45]\n[=autorun.C46]\n[=autorun.C47]\n[=autorun.C48]\n[=autorun.C49]\n[=autorun.C50]\n[=autorun.C51]\n[=autorun.C52]\n[=autorun.C53]\n[=autorun.C54]\n[=autorun.C55]\n[=autorun.C56]\n[=autorun.C57]\n[=autorun.C58]\n[=autorun.C59]\n[=autorun.C60]2) Если в секции есть другие шаблоны и маски. Нужно добавить по последнему номеру, например:
[cut]
Код: Выделить всё
[HintsCustomField]
0exts=>NTFS Ссылка
0fields=[=ntlinks.Obj_Type]\n[=ntlinks.Obj_RealPath.Natural]
1exts=*.apk
1fields=Название: [=apk.Application Name ru]\nВерсия: [=apk.Version] ([=apk.Version Code])\nПакет: [=apk.Package]\nAndroid: [=apk.Min SDK Name]
2exts=*.aucfg; autorun.cfg;*.ini;*.ahk; ;*.au3; *.vbs; *.bat; *.ps1
2fields=Число строк: [=linebreakinfo.CRLF Count]\nБайт прочитано: [=linebreakinfo.Bytes Read]Код: Выделить всё
[HintsCustomField]
0exts=>NTFS Ссылка
0fields=[=ntlinks.Obj_Type]\n[=ntlinks.Obj_RealPath.Natural]
1exts=*.apk
1fields=Название: [=apk.Application Name ru]\nВерсия: [=apk.Version] ([=apk.Version Code])\nПакет: [=apk.Package]\nAndroid: [=apk.Min SDK Name]
2exts=*.aucfg; autorun.cfg;*.ini;*.ahk; ;*.au3; *.vbs; *.bat; *.ps1
2fields=Число строк: [=linebreakinfo.CRLF Count]\nБайт прочитано: [=linebreakinfo.Bytes Read]
3exts=*.*
3fields=[=autorun.C1]\n[=autorun.C2]\n[=autorun.C3]\n[=autorun.C4]\n[=autorun.C5]\n[=autorun.C6]\n[=autorun.C7]\n[=autorun.C8]\n[=autorun.C9]\n[=autorun.C10]\n[=autorun.C11]\n[=autorun.C12]\n[=autorun.C13]\n[=autorun.C14]\n[=autorun.C15]\n[=autorun.C16]\n[=autorun.C17]\n[=autorun.C18]\n[=autorun.C19]\n[=autorun.C20]\n[=autorun.C21]\n[=autorun.C22]\n[=autorun.C23]\n[=autorun.C24]\n[=autorun.C25]\n[=autorun.C26]\n[=autorun.C27]\n[=autorun.C28]\n[=autorun.C29]\n[=autorun.C30]
4exts=*.*
4fields=[=autorun.C31]\n[=autorun.C32]\n[=autorun.C33]\n[=autorun.C34]\n[=autorun.C35]\n[=autorun.C36]\n[=autorun.C37]\n[=autorun.C38]\n[=autorun.C39]\n[=autorun.C40]\n[=autorun.C41]\n[=autorun.C42]\n[=autorun.C43]\n[=autorun.C44]\n[=autorun.C45]\n[=autorun.C46]\n[=autorun.C47]\n[=autorun.C48]\n[=autorun.C49]\n[=autorun.C50]\n[=autorun.C51]\n[=autorun.C52]\n[=autorun.C53]\n[=autorun.C54]\n[=autorun.C55]\n[=autorun.C56]\n[=autorun.C57]\n[=autorun.C58]\n[=autorun.C59]\n[=autorun.C60]После добавления полей в секцию, нужно зайти в диалог Настройки -> Содержимое панелей -> Пользовательские и поставить галочку "Объединять все подсказки, подходящие по типу файлов".
Всё. Предварительная часть установки завершена. Осталось подключить модуль.
Модуль подключается стандартно, директивой Pragma Include, в основной конфигурации Autorun:
Код: Выделить всё
Pragma Include %COMMANDER_PATH%\Ini\Scripts\MediaInfo.aucfgОкно панели поделится на 3 части: 10% справа, 75% центр, 15% слева. В каждой области отображается своя подсказка из MediaInfo.dll. Удержание Shift переключает отображение на плагины. Поскольку Shift не работает в TCx64, как и CTRL, переключением доступно только через Win+CapsLock. Данная комбинация работает и в TCx32.
Кроме подсказки, в модуле реализована кнопка для подсчета времени воспроизведения у выделенных файлов и каталогов. Код кнопки 71000. Подробнее о функционале здесь
Сам по себе модуль автономный, если не считать манипуляций описанных выше, связанных прежде всего с установкой подсказки в качестве альтернативной. В заголовке модуля требуется только указать корректные пути к библиотеке MediaHint.dll и утилите ExiTool:
[cut="MediaInfo.aucfg"]
Код: Выделить всё
Pragma IncludeOnce
# 71000-71099
RegisterCommand 71000 "Duration"
RegisterCommand 71010 "MediaInfoTest"
# Alt+F12
SetHotkeyAction /K:A /H:F12 SetHintFields
# Alt+1(..5)
SetHotkeyAction /K:A /H:1 /DM /S ShowPipeEx 0 1
SetHotkeyAction /K:A /H:2 /DM /S ShowPipeEx 0 2
SetHotkeyAction /K:A /H:3 /DM /S ShowPipeEx 0 3
SetHotkeyAction /K:A /H:4 /DM /S ShowPipeEx 0 4
SetHotkeyAction /K:A /H:5 /DM /S LeftsideHintType
# Win+CapsLock
SetHotkeyAction /V:20 /K:W MediaHintType
Global gMediaInfoX32 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo_i386.dll"
Global gMediaInfoX64 = COMMANDER_PATH & "\Ini\Tools\Libs\MediaInfo.dll"
Global gMediaExifX32 = COMMANDER_PATH & "\Plugins\wlx\ExifToolView\exiftool.exe"
Global gDurationInfo = 0, gDurationBreak = false, gDurationBaloon = 1, gDurationTXT
Global gFilterAudio = ".aac .ac3 .aif .aiff .aifc .afc .ape .au .snd .cda .dsf .dts .dtswav .dtshd .dtsma .eac3 .flac .fla .m1a .m2a .mka .mpa .mp1 .mp2 .mp3 .mp4 .m4a .m4b .m4r .mod .mpc .mp+ .mpp .oga .ogx .ogg .ra .spx .opus .qoa .svx .8svx .tak .tta .wav .wave .w64 .bwf .rf64 .wma .wv"
Global gFilterVideo = ".avi .wmv .wmp .wm .asf .mpg .mpeg .mpe .m1v .m2v .mpv2 .mp2v .ts .tp .tpr .trp .vob .ifo .ogm .ogv .mp4 .m4v .m4p .m4b .3gp .3gpp .3g2 .3gp2 .mkv .rm .ram .rmvb .rpm .flv .swf .mov .qt .amr .nsv .dpg .m2ts .m2t .mts .dvr-ms .k3g .skm .evo .nsr .amv .divx .webm .wtv .f4v .mxf"
Global gBTipWndProc, gBTipWnd = Map(), gBTip = 0
Global gBText = Buffer(1024*4), gBTool = Buffer(auX64 ? 56 : 40)
Global gBTipX, gBTipY
Global gBTipWP = Callback("BTipWndProc", "hwnd;uint;wparam;lparam")
Func Duration(lParam)
If gDurationInfo > 0 Then
gDurationBreak = true
Sleep(250)
Return
EndIf
If gDurationBaloon Then
gBTip = CreateBaloonTip("MediaInfo", 1, 200)
If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")
EndIf
RunThread DurationInfo
EndFunc
Func DurationInfo()
Local T1 = GetUptime(), T2 = T1
Local bCaps = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
Local bCtrl = IsPressed(0x11), bShift = IsPressed(0x10), bAlt = IsPressed(0x12)
Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
Static sExt = gFilterAudio & " " & gFilterVideo
If Not bAlt Then
If hLib = 0 Then
ShowMediaHint("Error LoadLibrary " & sLib)
Return
EndIf
Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
Local hMI = DllCall(pNew, "Ptr")
If hMI = 0 Then
ShowMediaHint("MediaInfo.dll couldn't create new object")
Return
Endif
Else
Local obj = Plugin("TCMediaInfo")
If ERROR <> 0 Then
ShowMediaHint("TCMediaInfo.wdx plugin error " & ERROR)
Return
Endif
EndIf
Local sDuration
Local aSel = List()
aSel.Text = GetSelectedItems(3, 0)
Local sPath = RequestCopyDataInfo("SP")
Local sName = RequestCopyDataInfo("SN")
Local sFile = sPath & sName
If aSel.Count = 0 Then
If Not FileExist(sFile) Then
ShowMediaHint("Файл не существует " & sFile)
Free(aSel)
If bAlt Then Free(obj)
Return
Endif
EndIf
If aSel.Count = 0 And Not StrPos(FileGetAttr(sFile), "D") Then
Free(aSel)
If bAlt Then
obj.FileName = sFile
sDuration = obj.GetValue(0) # duration
Free(obj)
Else
If DllCall(pOpen, "Ptr", hMI, "Wstr", sFile, "Uint") <> 1 Then
Return ShowMediaHint("MediaInfo.dll coudn't open file " & sFile)
EndIf
sDuration = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
"Wstr", "Duration/String3", "Int", 1, "Int", 0, "Wstr")
EndIf
Return ShowMediaHint("Файл: " & sName & auCRLF & "Длительность: " & sDuration, 1)
Endif
gDurationInfo = 1
gDurationBreak = false
ShowMediaHint("Загрузка", 1)
Local i, j, valid = 0
Local dirs = 0, files = 0, errs = 0, item = 0, aFiles = List(), seconds = 0, b_Hint = 0
Local depth = (bCtrl ? 1 : 0), ms = 0, vc, ac
bExtLog = false
# загрузка файлов в массив
If aSel.Count > 0 Then
For j = 0 To aSel.Count - 1
sFile = sPath & aSel[j]
If FileExist(sFile) Then
valid += 1
aFiles.Add(sFile)
If StrPos(FileGetAttr(sFile), "D") Then
If ListMediaFiles(sFile, aFiles, depth) > 0 Then aFiles.Count = 0
EndIf
EndIf
Next
sName = aSel.Count & "/" & valid
Else
aFiles.Add(sFile)
ListMediaFiles(sFile, aFiles, depth)
EndIf
Free(aSel)
If aFiles.Count > 1 Then
ShowMediaHint("Depth: " & depth & auCRLF & _
"Filter: " & (Not bShift ? "Yes" : "No") & auCRLF & _
(bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
"Элементов: " & aFiles.Count & auCRLF & _
"Подсчёт времени...", 1)
EndIf
T2 = GetUptime()
DurationLogString("Duration.Name:" & sName)
DurationLogString("Duration.Items:" & aFiles.Count)
For i = 0 To aFiles.Count - 1
If bExtLog Then DurationLogString("Duration.File:" & aFiles[i])
If StrPos(FileGetAttr(aFiles[i]), "D") Then
dirs += 1
If bExtLog Then DurationLogString("Duration.Directory:" & aFiles[i])
Continue
EndIf
item += 1
If bAlt Then
obj.FileName = aFiles[i]
ms = obj.GetValue(0,3) # duration -> milliseconds
Else
ext = FileGetExt(aFiles[i])
If Not bShift Then
If Not StrPos(sExt, '.' & ext) Then
DurationLogString("Duration.Filter:" & aFiles[i])
Continue
EndIf
EndIf
If DllCall(pOpen, "Ptr", hMI, "Wstr", aFiles[i], "Uint") <> 1 Then
errs += 1
DurationLogString("Duration.Error:" & aFiles[i])
Continue
EndIf
ms = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
"Wstr", "Duration", "Int", 1, "Int", 0, "Wstr")
vc = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
"Wstr", "VideoCount", "Int", 1, "Int", 0, "Wstr")
ac = DllCall(pGet, "Ptr", hMI, "Int", 0, "Int", 0, _
"Wstr", "AudioCount", "Int", 1, "Int", 0, "Wstr")
If ms > 0 And vc = "" And ac = "" Then
DurationLogString("Duration.Warning:" & aFiles[i])
Continue
EndIf
EndIf
If ms > 0 Then
seconds += ms
files += 1
Else
DurationLogString("Duration.Empty:" & aFiles[i])
EndIf
If gDurationBreak = true Or (IsPressed (0x11) And IsPressed (0x1B)) Then
ShowMediaHint("Операция прервана", 1)
Sleep(500)
If gDurationBaloon Then
Static buf = Buffer(160)
buf.Zero()
buf.SetStr("Прервано" & Chr(0))
SendMessage(gBTip, 1057, 3, buf.ptr)
EndIf
Break
EndIf
If Round(GetUptime() - T2, 0) > 500 Then
ShowMediaHint("Depth: " & depth & auCRLF & _
"Filter: " & (Not bShift ? "Yes" : "No") & auCRLF & _
(bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
"Элементов: " & aFiles.Count & auCRLF & _
"Обработка: " & i & " из " & aFiles.Count, 1)
T2 = GetUptime()
EndIf
Next
If bAlt Then Free(obj)
If Not bAlt And hMI <> 0 Then DllCall(pDel, "Ptr", hMI)
gDurationInfo = 0
gDurationBreak = false
seconds = Floor(seconds / 1000)
Local day = Floor(seconds / 86400)
Local hour = Floor((seconds - (day * 86400)) / 3600)
Local min = Floor(((seconds - (day * 86400)) - (hour * 3600)) / 60)
Local sec = seconds - (day * 86400 + hour * 3600 + min * 60)
Local total = StrFormat("%02d:%02d:%02d:%02d",day,hour,min,sec)
Local tl = Round(GetUptime() - T1, 0) / 1000
Local txt = "Имя: " & sName & auCRLF & _
"Каталогов: " & dirs & auCRLF & _
"Элементов: " & aFiles.Count & auCRLF & _
"Обработано: " & files & " из " & item & auCRLF & _
"Ошибки DLL: " & errs & auCRLF & _
"Секунды: " & seconds & auCRLF & _
"Минуты: " & Round(seconds / 60, 2) & auCRLF & _
"Часы: " & Round(seconds / 3600, 2) & auCRLF & _
"Сутки: " & Round(seconds / 86400, 2) & auCRLF & _
"Время: " & Chr(0x2211) & " "& total & auCRLF & _
"Powered by " & (bAlt ? "TCMediaInfo.wdx" : "MediaInfo.dll") & auCRLF & _
"Время операции: " & StrFormat("%.3f", tl) & " sec"
DurationLogString(txt & auCRLF & auCRLF)
Free(aFiles)
ClipPut(txt)
ShowMediaHint(txt, 1)
EndFunc
Func ListMediaFiles(sPath, ByRef aList, nDepth = 1)
Local sFile, nAttr
Local ffd = Buffer(604), bEsc = false
Local hf = DllCall("FindFirstFileW", "wstr", sPath & "\*.*", "ptr", ffd.Ptr)
If hf <> 0 then
While True
sFile = ffd.GetStr(44) # cFileName
nAttr = ffd.GetNum(0, "dword") # dwFileAttributes
If BitAND(nAttr, 16) Then
If Not ((sFile = ".") Or (sFile = "..")) Then
aList.Add(sPath & "\" & sFile)
If nDepth <> 1 Then
ListMediaFiles(sPath & "\" & sFile, aList, nDepth - 1)
EndIf
EndIf
Else
aList.Add(sPath & "\" & sFile)
Endif
If DllCall("FindNextFileW", "handle", hf, "ptr", ffd.Ptr) = 0 Then Break
If IsPressed (0x1B) Then
bEsc = true
Break
EndIf
Wend
DllCall("FindClose", "handle", hf)
Endif
Free(ffd)
Return bEsc
EndFunc
Func DurationLogString(LogString)
gDurationTXT &= LogString & auCRLF
EndFunc
Func ShowMediaHint(MediaHint, Persist = false)
# удаление подсказки тотала
If gDurationBaloon And gBTip > 0 Then
Local hTip = WinFind(0, "TToolTip")
If hTip > 0 Then SendMessage(hTip, 0x0010, 0, 0)
UpdateBaloonTip(gBTip, MediaHint)
Return
EndIf
SetHintParam("ShowHint", "Font", 11, "Arial")
#SetHintParam("ShowHint", "BackColor", 0x000000)
#SetHintParam("ShowHint", "Text", 0xFFFFFF)
SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
SetHintParam("ShowHint", "DarkText", 0xFFFFFF)
If Persist Then
ShowHint(MediaHint)
Else
ShowHint(MediaHint, "", "", 3000, 1)
EndIf
Sleep(10)
SetHintParam("ShowHint", "Reload")
EndFunc
Func MediaInfoTest(lParam)
Local sFile = RequestCopyDataInfo("SP") & RequestCopyDataInfo("SN")
If Not FileExist(sFile) Then
ShowHint("Файл не существует " & sFile)
Return
Endif
If StrPos(FileGetAttr(sFile), "D") Then
ShowHint("Каталог " & sFile)
Return
Endif
Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
If hLib = 0 Then
ShowHint("Error LoadLibrary " & sLib)
Return
EndIf
Static sPath = FileGetDir(sLib)
Static sLang ="file://" & sPath & "\ru.csv"
Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
Static pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
Static pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")
Local hMI = DllCall(pNew, "Ptr")
If hMI = 0 Then
ShowHint("MediaInfo.dll couldn't create new object")
Return
Endif
If DllCall(pOpen, 'ptr', hMI, "wstr", sFile, "uint") <> 1 Then
DllCall(pDel, "Ptr", hMI)
Return ShowHint("MediaInfo.dll couldn't open file " & sFile)
EndIf
Local sMI
sMI &= "Duration: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Duration", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Video: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "VideoCount", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Audio: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "AudioCount", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Recorded: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Recorded_Date", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Cover: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Cover Mime: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Cover_Mime", "int", 1, "int", 0, "wstr") & auCRLF
sMI &= "Track/Position: "
sMI &= DllCall(pGet, 'ptr', hMI, "int", 0, "int", 0, "wstr", "Track/Position", "int", 1, "int", 0, "wstr")
If IsPressed(0x11) Then
sMI = ""
DllCall(pOpt, "Ptr", hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", sLang, "Wstr")
DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", "Inform", "Wstr")
Local lst = List()
lst.Text = DllCall(pInfo, "Ptr", hMI, "Uint", 0, "Wstr")
For line in lst
sMI &= FixSpaces(line) & auCRLF
Next
Free(lst)
EndIf
DllCall(pDel, "Ptr", hMI)
If gDurationBaloon Then
gBTip = CreateBaloonTip("MediaInfo", 1, 300)
If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")
EndIf
If StrTrim(sMI) = "" Then sMI = "нет данных"
ShowMediaHint(sMI)
EndFunc
Func CreateBaloonTip(TipTitle, TipIcon, TipWidth)
Static TTM_TRACKACTIVATE = 1041, _
TTM_TRACKPOSITION = 1042, _
TTM_SETMAXTIPWIDTH = 1048, _
TTM_SETTITLE = 1057, _
TTM_ADDTOOL = 1074
Local hTip
hTip = DllCall("CreateWindowExW", _
"dword", 8, _
"wstr", "tooltips_class32", _
"wstr", "", _
"dword", 0x00000c0, _
"int", 0, "int", 0, "int", 0, "int", 0, _
"handle", AUTORUN_TCHANDLE, _
"handle", 0, "handle", 0, "ptr", 0, "handle")
If hTip = 0 Then Return 0
MouseGetPos("gBTipX","gBTipY")
#gBTipWnd.Set(hTip, MakeInt(gBTipX, gBTipY, 2))
gBTipWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", hTip, "int", -4, "long_ptr", gBTipWP.Ptr, "ptr")
Local buf = Buffer(160)
buf.Zero()
buf.SetStr(TipTitle & Chr(0))
SendMessage(hTip, TTM_SETTITLE, TipIcon, buf.ptr)
gBText.Zero()
gBText.SetStr("Инициализация" & Chr(0))
gBTool.Zero() # TTTOOLINFO
If auX64 Then
gBTool.SetNum(0, "uint", gBTool.size, _
"uint", 0x00a0, _
"hwnd", AUTORUN_TCHANDLE, _
"uint_ptr", 0)
gBTool.SetNum(48, "ptr", gBText.ptr)
Else
gBTool.SetNum(0, "uint", gBTool.size, _
"uint", 0x00a0, _
"hwnd", AUTORUN_TCHANDLE, _
"uint_ptr", 0, _
"long", 0, _
"long", 0, _
"long", 0, _
"long", 0, _
"ptr", 0, _
"ptr", gBText.ptr)
EndIf
SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, TipWidth)
SendMessage(hTip, TTM_ADDTOOL, 0, gBTool.ptr)
SendMessage(hTip, TTM_TRACKACTIVATE, 1, gBTool.ptr)
SendMessage(hTip, TTM_TRACKPOSITION, 0, MakeInt(gBTipX, gBTipY, 0))
Free(buf)
Return hTip
EndFunc
Func UpdateBaloonTip(hTip, TipText)
Static TTM_UPDATETIPTEXT = 1081
gBText.Zero()
gBText.SetStr(TipText & Chr(0))
SendMessage(gBTip, TTM_UPDATETIPTEXT, 0, gBTool.ptr)
EndFunc
Func BTipWndProcTest(hWnd, uMsg, wParam, lParam)
Static IsDrag = 0, _
MK_LBUTTON = 0x0001, _
WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
TTM_TRACKPOSITION = 1042
Static tx, ty
Switch uMsg
Case WM_LBUTTONDOWN
If IsDrag = 0 Then
MouseGetPos("tx","ty")
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(ty, tx, 2)) Then
IsDrag = 1
DllCall("SetCapture", "hwnd", hWnd, "hwnd")
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
WinGetPos("gBTipX", "gBTipY", "", "", hWnd)
IsDrag = 0
DllCall("ReleaseCapture")
Else
DllCall("DestroyWindow", "handle", hWnd)
EndIf
Case WM_MOUSEMOVE
If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
MouseGetPos("x","y")
SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))
EndIf
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func BTipWndProc(hWnd, uMsg, wParam, lParam)
Static IsDrag = 0, _
WM_CREATE = 0x0001, _
WM_DESTROY = 0x0002, _
WM_SHOWWINDOW = 0x0018, _
MK_LBUTTON = 0x0001, _
WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
WM_RBUTTONUP = 0x0205, _
TTM_TRACKACTIVATE = 1041, _
TTM_TRACKPOSITION = 1042
Static SM_CXDRAG = 68, _
SM_CYDRAG = 69, _
DragWidth = GetSystemMetrics(SM_CXDRAG), _
DragHeight = GetSystemMetrics(SM_CYDRAG), _
StartX = 0, _
StartY = 0
Local x, y
Static tx, ty, buf = Buffer(8)
Switch uMsg
Case WM_SHOWWINDOW
If wParam = 0 Then DllCall("DestroyWindow", "handle", hWnd)
Case WM_DESTROY
If gDurationInfo Then
gDurationBreak = true
MsgBox("Операция отменена")
Return 0
EndIf
Case WM_LBUTTONDOWN
If IsDrag = 0 Then
buf.Zero()
x = BitAND(lParam, 0xFFFF)
y = BitAND(BitShift(lParam,16), 0xFFFF)
StartX = x
StartY = y
buf.SetNum(0, "int", x, "int", y)
DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
tx = buf.GetNum(0)
ty = buf.GetNum(4)
IsDrag = 1
DllCall("SetCapture", "hwnd", hWnd, "hwnd")
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
WinGetPos("gBTipX", "gBTipY", "", "", hWnd)
IsDrag = 0
DllCall("ReleaseCapture")
Else
DllCall("DestroyWindow", "handle", hWnd)
EndIf
Case WM_MOUSEMOVE
If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
x = BitAND(lParam, 0xFFFF)
y = BitAND(BitShift(lParam,16), 0xFFFF)
If Abs(x - startX) > DragWidth Or Abs(y - startY) > DragHeight Then
buf.Zero()
buf.SetNum(0, "int", x, "int", y)
DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
x = buf.GetNum(0)
y = buf.GetNum(4)
SendMessage(hWnd, TTM_TRACKPOSITION, 0, MakeInt(gBTipX+(x-tx), gBTipY+(y-ty), 0))
EndIf
EndIf
Case WM_RBUTTONUP
BTipShowMenu(hWnd)
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gBTipWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func BTipShowMenu(hWnd)
ShowPopupMenu /D /F /I:0 "BTipCreateMenu"
EndFunc
Func BTipCreateMenu()
Local txt
txt &= 'MENUITEM "Лог операций", em_aucmd ' & (gDurationTXT <> "" ? "" : "/D") & ' -1 DurationText' & auCRLF
Return txt
EndFunc
Func DurationText()
Local sLogFile = TEMP & "\duration.txt"
FileWrite(sLogFile, gDurationTXT)
ShellExec(sLogFile)
EndFunc
Func MediaHint(FileName, FieldIndex, UnitIndex)
If FieldIndex > gHintLines Then Return
If StrPos(FileGetAttr(FileName), "D") Then Return ""
Local bCaps = DllCall("GetKeyState", "int", 0x14, "short")
Local bCtrl = BitAND(bCaps, 1), bShift = IsPressed(0x10)
If gHintWdx Then bShift = true
If Not bCtrl then bCtrl = IsPressed (0x11)
If gHintCaps And Not bCtrl Then Return
Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
Static hLib = DllCall("LoadLibrary", "Wstr", sLib, "Ptr")
Static sPath = FileGetDir(sLib) & "\"
Static sLang ="file://" & sPath & "ru.csv", _
sHint ="file://" & sPath & "hint.txt", _
sSize ="file://" & sPath & "size.txt"
Static bLang = true, nWait = 0, _
pNew, pOpen, pDel, pOpt, pInfo
If hLib = 0 And FieldIndex > 1 Then Return
If FieldIndex = 1 Then
If hLib = 0 Then Return "Error LoadLibrary " & sLib
Idx = 0
pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")
nWait = 0
bLang = true
sMode = "Inform"
If gHintWait > 0 Then Sleep(gHintWait)
Local x, y, w, nCase = 0
Local hWnd = RequestInfo(ItemAtCursor("panel"))
WinGetPos("", "", "w", "", hWnd)
If w > 0 Then
MouseGetPos("x","y")
Static buf = Buffer(8) # POINT
buf.Zero()
buf.SetNum(0, "long", x, "long", y)
DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
x = buf.GetNum(0)
Switch Round(x/w*100,0)
Case 0 To gHintLayout[0]-1
nCase = 0
Case gHintLayout[0] To gHintLayout[0]+gHintLayout[1]-1
nCase = 1
Case 100-gHintLayout[2] To 100
nCase = 2
EndSwitch
nWait = gHintSleep[nCase]
sMode = gHintContent[nCase]
EndIf
If bShift Then
If gHintWdxList.Count <= nCase Then
gHintPipe = "" & auCRLF & "Autorun: No data in " & gHintWdxCfg
Return
EndIf
gHintPipe = ""
Static aWdx = List()
aWdx.Count = 0
aWdx.Split(gHintWdxList[nCase], ";")
For i = 0 To aWdx.Count - 1
gHintPipe &= MediaHintWDX(aWdx[i], FileName)
Next
gHintPipe = StrTrim(gHintPipe)
If gHintPipe = "" Then
gHintPipe = "" & auCRLF & "Autorun: No data in " & gHintWdxCfg
Return
EndIf
gHintPipe = "" & auCRLF & gHintPipe
Return
EndIf
If nWait > 0 Then Sleep(nWait)
If sMode = "" Then
gHintPipe = ""
Return
ElseIf sMode <> "Inform" Then
bLang = false
sMode ="file://" & sPath & sMode
EndIf
Local hMI = DllCall(pNew, "Ptr")
If hMI = 0 Then Return "MediaInfo.dll couldn't create new object"
If DllCall(pOpen, 'Ptr', hMI, "Wstr", FileName, "Uint") <> 1 Then
DllCall(pDel, "Ptr", hMI)
Return "MediaInfo.dll couldn't open file " & FileName
EndIf
If bShift Then
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "1", "Wstr")
Else
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")
EndIf
DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", sMode, "Wstr")
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", (Not bLang ? "" : sLang), "Wstr")
gHintPipe = DllCall(pInfo, 'Ptr', hMI, "Uint", 0, "Wstr")
#{
If StrPos(sMode, "hint.txt") Then
gHintPipe = StrReplace(gHintPipe, "DTS HD Master Audio", "DTS-HD MA")
gHintPipe = StrReplace(gHintPipe, "Dolby Digital", "DD")
EndIf
#}
If Not bLang Then gHintPipe = StrReplace(gHintPipe, Chr(32), Chr(160))
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", "", "Wstr")
DllCall(pDel, "Ptr", hMI)
Endif
If Not bLang Then Return StrPart(gHintPipe, auCRLF, FieldIndex)
Return FixSpaces(StrPart(gHintPipe, auCRLF, FieldIndex))
EndFunc
Func FixSpaces(String)
Local a, b
If Not StrPos(String, ":") Then Return String
a = StrPart(String, ":", 1)
b = StrPart(String, ":", 2) & StrPart(String, ":", 3)
Return StrTrim(a) & ": " & FixCodePage(StrTrim(b))
EndFunc
Func FixCodePage(String)
Local bUsedRepl
# iso-8859-1 = 28591
DllCall("WideCharToMultiByte", _
"uint", 28591, _
"dword", 0, _
"wstr", String, _
"int", -1, _
"ptr", 0, _
"int", 0, _
"ptr", 0, _
"bool*", @bUsedRepl)
If bUsedRepl Then Return String
Local nSize = StrLen(String)
Local buf = Buffer(nSize)
buf.Zero()
DllCall("WideCharToMultiByte", _
"uint", 28591, _
"dword", 0, _
"wstr", String, _
"int", -1, _
"ptr", buf.ptr, _
"int", nSize, _
"ptr", 0, _
"ptr", 0)
Local fixed = buf.GetStr(0, nSize, "ANSI")
Free(buf)
Return fixed
EndFunc
Func FixCodePageEx(String)
Local bUsedRepl
# iso-8859-1 = 28591
DllCall("WideCharToMultiByte", _
"uint", 28591, _
"dword", 0, _
"wstr", String, _
"int", -1, _
"ptr", 0, _
"int", 0, _
"ptr", 0, _
"bool*", @bUsedRepl)
If bUsedRepl Then Return String
Local nSize = StrLen(String)
Local buf = Buffer(nSize)
buf.Zero()
buf.SetStr(String, 0, nSize, "CP:28591")
Local fixed = buf.GetStr(0, nSize, "ANSI")
Free(buf)
Return fixed
EndFunc
Func ShowPipeEx(lParam, nPage)
Local sPipe, nLines = gHintLines
Local aPipe = List(), j, nSect = 0
Local nEnd = nPage*nLines, nStart = nEnd - nLines
If gHintClipb Then ClipPut(gHintPipe)
aPipe.Text = gHintPipe
For j = 0 To aPipe.Count - 1
If aPipe[j] = "" Then nSect += 1
If (j + 1) >= nStart And (j + 1) <= nEnd Then
sPipe &= StrLeft(FixSpaces(aPipe[j]),84) & auCRLF
EndIf
Next
Free(aPipe)
If sPipe = "" Then sPipe = "Out of range"
ShowHint(StrTrim(sPipe))
#Return -1
EndFunc
Func LeftsideHintType()
Static init = gHintContent[0]
If gHintContent[0] = init Then
gHintContent[0] = gHintShift
Else
gHintContent[0] = init
EndIf
ShowRedInfoHint("Left side is " & gHintContent[0])
EndFunc
Func SetHintFields()
Local i, sHint
Static c = 0, aHints = List("MediaHint", "ExifHint", "JoinHint")
c += 1
If c > 2 Then c = 0
sHint = aHints[c]
For i = 1 to 60
SetFieldsParam("Func", "C" & i, sHint)
Next
ShowRedInfoHint("Поля подсказки " & sHint)
EndFunc
Func ShowRedInfoHint(HintText)
SetHintParam("ShowHint", "Font", 15, "Arial")
SetHintParam("ShowHint", "BackColor", 0xFF0000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
ShowHint(HintText, 0, 0, 1000, 1)
WinAlign(LAST_HINT_WINDOW)
Sleep(100)
SetHintParam("ShowHint", "Reload")
EndFunc
Func ExifHint(FileName, FieldIndex, UnitIndex)
If FieldIndex > gHintLines Then Return
If StrPos(FileGetAttr(FileName), "D") Then Return
Local bCtrl = BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1)
If Not bCtrl then bCtrl = IsPressed (0x11)
If gHintCaps And Not bCtrl Then Return
If FieldIndex = 1 Then
ProcessExecGetOutput gHintPipe %gMediaExifX32% ' -G -S -lang ru "%FileName%"'
Endif
Return StrPart(gHintPipe, auLF, FieldIndex)
EndFunc
ReadWdxHintCfg()
Func ReadWdxHintCfg()
gHintWdxList.Count = 0
gHintWdxList.LoadFromFile(gHintWdxCfg)
EndFunc
Func MediaHintWDX(WdxName, Filename)
If Not FileExist(Filename) Then
Return auCRLF & auCRLF & "Файл не существует " & Filename
Endif
Local obj = Plugin(WdxName)
If ERROR <> 0 Then
Return auCRLF & auCRLF & "Autorun: " & WdxName & " plugin error " & ERROR
EndIf
Local i, txt, data
obj.FileName = Filename
For i = 0 To obj.FieldCount -1
data = obj.GetValue(i)
If data = "" Then Continue
txt &= obj.FieldName(i) & ": " & data & auCRLF
Next
Free(obj)
txt = StrTrim(txt)
If StrLen(txt) > 0 Then txt = auCRLF & auCRLF & txt
Return txt
EndFunc
Func MediaHintType()
# переключение переменной
gHintWdx = Not gHintWdx
ShowRedInfoHint("WdxHint.cfg " & (gHintWdx ? "включен" : "выключен"))
EndFunc