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

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Thu Feb 27, 2025 00:23 Post subject: |
|
|
Loopback
Теперь работает )
Добавив такую функцию в Autorun, вы, конечно, дали ключ от всех дверей, но проблем хватает Я не имею в виду этот небольшой баг с "ulong_ptr". Чтобы в полной мере пользоваться WIN API, нужно много знать и понимать, как работает Windows. Одним лишь сайтом Microsoft тут не обойтись.
Но кое-что можно уже пробовать и воплощать. Например, я сначала увлёкся иконкой в трее ради интереса, но теперь понимаю, что жить без неё не могу
Многое ещё не доделано, но кое-что продемонстрировать уже можно:
 Hidden text Code: | Pragma IncludeOnce
# 64000-65000
RegisterCommand 64000 TrayIcon
RegisterCommand 64001 ChangeTrayIcon
RegisterCommand 64002 NotifyInfo
# коды клавиш клавиатуры
Const K_SHIFT = 0x10, K_CTRL = 0x11, K_ALT = 0x12, K_ESC = 0x1B, K_WIN = 0x5B
# дополнительные настроки
Global AUTORUN_INI = %COMMANDER_PATH% & "\Ini\Autorun.ini"
# иконки окна уведомлений
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
# функции обратного вызова
SetMessageAction /P 55555 TrayAction
SetMessageAction /P 55565 TrayNotifyInfo
Func TrayAction(hWnd, uMsg, wParam, lParam)
# движение над иконкой
If lParam = WM_MOUSEMOVE Then
If LAST_HINT_WINDOW = 0 Then
If IsPressed(K_CTRL) Then ShowHint(GetState("threads"), "", "", 2000, 1)
#If IsPressed(K_CTRL) Then ShowDarkHint(GetState("threads"), 2000, 1)
EndIf
EndIf
# левый клик
If lParam = WM_LBUTTONDOWN Then
If IsPressed(K_CTRL) Then
ShowDarkHint(GetState("threads"))
Return
EndIf
AutorunMenu(0)
# правый клик
Elseif lParam = WM_RBUTTONDOWN Then
ShowDarkHint(GetState("libs"))
# клик по сообщению
Elseif lParam = NIN_BALLOONUSERCLICK Then
MsgBox("Baloon click")
#WinSetState(23)
# клик "закрыть сообщение"
ElseIf lParam = NIN_BALLOONTIMEOUT Then
MsgBox("Time-out")
EndIf
EndFunc
Func TrayNotifyInfo(hWnd, uMsg, wParam, lParam)
NotifyIcon("delete", 1010)
EndFunc
Global TrayShow = 0, TrayIcon = 0
TrayIcon(0)
Func TrayIcon(lParam)
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"
If ico = "" Or Not FileExist(ico) Then
idx = 0
ico = %COMMANDER_PATH% & "\TOTALCMD.EXE"
EndIf
Local hint = "Autorun " & FileGetVersion(AUTORUN_PATH & "\Autorun.wdx", "FileVersion")
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", ico, "uint", idx, "ptr")
#NotifyIcon("add", 1001, 55555, hIco, hint, "Tray icon added", "Autorun", 1)
TrayIcon = NotifyIcon("add", 1001, 55555, hIco, hint)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func ChangeTrayIcon(lParam)
Static f = GetKnownFolderPath("System") & "\shell32.dll", i = 10
i += 1
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", f, "uint", i, "ptr")
If IsPressed(0x11) Then
NotifyIcon("delete", 1001)
ElseIf IsPressed(0x10) Then
NotifyIcon("add", 1001, 55555, hIco, "Autorun")
Else
If IsPressed(0x12) Then hIco = 0
NotifyIcon("set", 1001, 55555, hIco, "", "Icon changed to shell32.dll, " & i, "", 2)
Sleep(2000)
NotifyIcon("set", 1001,, hIco,, "Icon changed to shell32.dll, " & i,, 2)
EndIf
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func DeleteTrayIcon(lParam)
If NotifyIcon("delete", 1001) Then TrayIcon = 0
EndFunc
Func NotifyInfo(lParam)
Local idx = 15
Local file = GetKnownFolderPath("System") & "\shell32.dll"
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", file, "uint", idx, "ptr")
NotifyInfoMessage(hIco, "Test message", "", NIIF_INFO)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
EndFunc
Func NotifyInfoMessage(hIcon, InfoText, InfoTitle = "Autorun", InfoType = 0)
Local buf = Buffer((auPtrSize = 4 ? 956 : 976))
Local dwFlags = 27 # NIF_MESSAGE|NIF_STATE|NIF_INFO
buf.Zero()
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", 1010, _
"uint", dwFlags, _
"uint", 55565)
buf.SetNum(32, "ptr", hIcon)
buf.SetNum(296, "dword", 1, _
"dword", 1)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", 1010, _
"uint", dwFlags, _
"uint", 55565, _
"ptr", hIcon) )
buf.SetNum(280, "dword", 1, _
"dword", 1)
EndIf
buf.SetStr(StrLeft(InfoText, 263) & Chr(0), (auX64 ? 40 : 24) + 256 + 4 + 4)
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, 63) & Chr(0), (auX64 ? 40 : 24) + 256 + 4 + 4 + 512 + 4)
EndIf
If InfoType > 0 Then
buf.SetNum((auX64 ? 40 : 24) + 256 + 4 + 4 + 512 + 4 + 128, "dword", InfoType)
EndIf
Local Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", 0, "ptr", buf.ptr, "bool")
Free(buf)
Return Result
EndFunc
Func NotifyIcon(Action, ID, CallbackMessage = 0, hIcon = 0, Tip = "", InfoText = "", InfoTitle = "", InfoType = 0)
Local Message, Result
Local TIP_MAXCHAR = 127, INFO_MAXCHAR = 199, TITLE_MAXCHAR = 63
Local buf = Buffer((auPtrSize = 4 ? 956 : 976))
buf.Zero()
Local FLAGS = BitOR((CallbackMessage = 0 ? 0 : NIF_MESSAGE), _
(hIcon = 0 ? 0 : NIF_ICON), _
(StrLen(Tip) = 0 ? 0 : NIF_TIP), _
(StrLen(InfoText) = 0 ? 0 : NIF_INFO))
Switch Action
Case "add"
Message = 0
Case "set"
Message = 1
Case "delete"
Message = 2
Else
Return
EndSwitch
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage)
buf.SetNum(32, "ptr", hIcon)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage, _
"ptr", hIcon)
EndIf
If StrLen(Tip) > 0 Then
buf.SetStr(StrLeft(Tip, TIP_MAXCHAR) & Chr(0), (auX64 ? 40 : 24)) # auPtrSize*2 + 4*4 + padding for X64
EndIf
If StrLen(InfoText) > 0 Then
buf.SetStr(StrLeft(InfoText, INFO_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 264) # 256 + 4 + 4
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, TITLE_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 780) # 512 + 4
EndIf
If InfoType > 0 Then
buf.SetNum((auX64 ? 40 : 24) + 780 + 128, "dword", InfoType)
EndIf
EndIf
Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", Message, "ptr", buf.ptr, "bool")
Free(buf)
Return Result
EndFunc |
Вверху коды кнопок. Можно запустить два потока, чтобы иконка сама менялась в фоне с интервалом:
 Hidden text Code: | RunThread ThreadWatchLangFunc
Func ThreadWatchLangFunc
Local file = GetKnownFolderPath("System") & "\shell32.dll"
Local lng = AUTORUN_TCLANG, idx
While 1
OutputDebugString("lang=" & AUTORUN_TCLANG & " lng=" & lng)
If Not (lng = AUTORUN_TCLANG) Then
Switch AUTORUN_TCLANG
Case 'ENG'
# ChangeLangEN 0
idx = 13
Case 'RUS'
# ChangeLangRU 0
idx = 15
EndSwitch
lng = AUTORUN_TCLANG
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", file, "uint", idx, "ptr")
NotifyIcon("set", 1001, 55555, hIco)
#NotifyIcon("set", 1001, 55555, hIco, "", "Language changed to " & lng, "", 1)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco, "bool")
Endif
Sleep(1000)
Wend
EndFunc
RunThread ThreadFunction
# пример из справки
Func ThreadFunction
Local sPath, sName
Local ru = true
While 1
sPath = RequestCopyDataInfo("SP")
sName = RequestCopyDataInfo("SN")
sPath = sPath & sName
# выводим путь, просматривать можно с DebugView
# выполнение цикла при этом не блокируется
OutputDebugString("Autorun: Path = " & sPath)
Sleep(5000)
ru = Not ru
If ru Then
CommandExec("em_change_lang_ru")
Else
CommandExec("em_change_lang_en")
EndIf
Wend
EndFunc
|
Одмн поток меняет язык раз в 5 секунд, другой следит за сменой языка. Как только язык меняется, меняется и иконка. |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Sat Mar 01, 2025 00:20 Post subject: |
|
|
После внесения некоторых изменений можно считать, что данный вариант функций для работы с иконками в трее, более-менее законченный:
 Hidden text Code: | Pragma IncludeOnce
# 64000-65000
RegisterCommand 64000 ShowTrayIcon
RegisterCommand 64001 ChangeTrayIcon
RegisterCommand 64002 NotifyInfo
# иконки окна уведомлений
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
# функции обратного вызова
SetMessageAction /P 99999 TrayAction
SetMessageAction /P 99998 TrayNotifyInfo
# главная иконка Autorun
Func TrayAction(hWnd, uMsg, wParam, lParam)
# движение над иконкой
If lParam = WM_MOUSEMOVE Then
If LAST_HINT_WINDOW = 0 Then
If IsPressed(KEY_CTRL) Then ShowHint(GetState("threads"), "", "", 2000, 1)
#If IsPressed(KEY_CTRL) Then ShowDarkHint(GetState("threads"), 2000, 1)
EndIf
EndIf
Switch lParam
# левый клик
Case WM_LBUTTONDOWN
If IsPressed(KEY_CTRL) Then
ShowHint(GetState("threads"))
#ShowDarkHint(GetState("threads"))
Return
EndIf
AutorunMenu(0)
# правый клик
Case WM_RBUTTONDOWN
ShowDarkHint(GetState("libs"))
# клик по сообщению
Case NIN_BALLOONUSERCLICK
MsgBox("Baloon click")
#WinSetState(23)
# клик "закрыть сообщение"
Case NIN_BALLOONTIMEOUT
MsgBox("Time-out")
EndSwitch
EndFunc
# служебная иконка
Func TrayNotifyInfo(hWnd, uMsg, wParam, lParam)
# освобождение невидимой иконки
If lParam = NIN_BALLOONUSERCLICK or lParam = NIN_BALLOONTIMEOUT Then
NotifyIcon("delete", 1010)
EndIf
EndFunc
Global TrayShow = 0, Tray1001 = 0, Tray1002 = 0
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
# откат к умолчаниям
If ico = "" Or Not FileExist(ico) Then
idx = 0
ico = COMMANDER_PATH & "\TOTALCMD.EXE"
EndIf
Local hint = "Autorun " & FileGetVersion(AUTORUN_PATH & "\Autorun.wdx", "FileVersion")
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", ico, "uint", idx, "ptr")
If NotifyIcon("add", 1001, 99999, hIco, hint) Then Tray1001 = 1
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco)
EndFunc
Func ShowTrayIcon(lParam)
If Tray1001 > 0 Then
IniWrite %AUTORUN_INI% "TrayIcon" "Show" 0
HideTrayIcon()
Else
IniWrite %AUTORUN_INI% "TrayIcon" "Show" 1
TrayIcon()
EndIf
If Tray1001 > 0 Then
ShowHint("Иконка включена")
Else
ShowHint("Иконка отключена")
EndIf
EndFunc
Func HideTrayIcon()
If NotifyIcon("delete", 1001) Then Tray1001 = 0
EndFunc
Func ChangeTrayIcon(lParam)
Static f = GetKnownFolderPath("System") & "\shell32.dll", i = 10
If Tray1001 = 0 Then
ShowHint("Иконка отключена")
Return
EndIf
i += 1
Local hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", f, "uint", i, "ptr")
If IsPressed(KEY_CTRL) Then
NotifyIcon("add", 1002, 99999, hIco, "Autorun #2", "Second icon added", "Autorun", NIIF_NONE)
Tray1002 = 1
Else
If IsPressed(KEY_ALT) Then hIco = 0
NotifyIcon("set", 1001, 99999, hIco, "", "Icon changed to shell32.dll, " & i, "", NIIF_INFO)
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)
# тест 1
NotifyInfoMessage(1, "Test message", "", NIIF_INFO)
sleep(3000)
# тест 2
txt = "Pragma Include %COMMANDER_PATH%\Ini\Scripts\Test.aucfg"
NotifyInfoMessage(0, txt, "Script", NIIF_WARNING + NIIF_NOSOUND)
sleep(3000)
# тест 3
txt = "Test message line 1" & auCRLF & "Test message line 2"
NotifyInfoMessage(0, txt, "Script", NIIF_ERROR)
EndFunc
#{
Функция для показа системных уведомлений:
Icon - иконка в трее (1 - да, 0 - нет)
InfoText - текст уведомления (199 символов)
InfoTitle - текст заголовка уведомления (47 символов)
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Функция использует идентификатор "1010" и номер сообщения "99998"
#}
Func NotifyInfoMessage(Icon, InfoText, InfoTitle = "Autorun", InfoType = 0)
Local dwFlags = 0
Local buf = Buffer(auPtrSize = 4 ? 956 : 976)
Local hIco = 0, tc = COMMANDER_PATH & "\TOTALCMD.EXE"
hIco = DllCall("shell32\ExtractIconW", "ptr", AUTORUN_TCHANDLE, "wstr", tc, "uint", 0, "ptr")
If Icon Then
dwFlags = BitOR(NIF_MESSAGE, NIF_ICON, NIF_INFO)
Else
dwFlags = BitOR(NIF_MESSAGE, NIF_STATE, NIF_ICON, NIF_INFO)
Endif
buf.Zero()
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", 1010, _
"uint", dwFlags, _
"uint", 99998)
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", dwFlags, _
"uint", 99998, _
"ptr", hIco) )
buf.SetNum(280, "dword", 1, _
"dword", 1)
EndIf
Local offset = (auX64 ? 40 : 24) + 256 + 4 + 4
buf.SetStr(StrLeft(InfoText, 199) & Chr(0), offset)
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, 47) & Chr(0), offset + 512 + 4)
EndIf
If InfoType > 0 Then
buf.SetNum(offset + 512 + 4 + 128, "dword", InfoType)
EndIf
Local Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", 0, "ptr", buf.ptr)
If hIco > 0 Then DllCall("DestroyIcon", "ptr", hIco)
Free(buf)
Return Result
EndFunc
#{
Отображение иконки в трее:
https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
Action - тип операции ("add", "set", "delete")
ID - внутренний идентификатор иконки (1001, 1002, ...)
CallbackMessage - код сообщения для обратного вызова (99999, 99998, ...)
hIcon - дескриптор иконки (обязателен для "add", необязателен для "set")
Tip - текст подсказки в трее
InfoText - текст уведомления (только при операции "add" или "set")
InfoTitle - текст заголовка уведомления
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
#}
Func NotifyIcon(Action, ID, CallbackMessage = 0, hIcon = 0, Tip = "", InfoText = "", InfoTitle = "", InfoType = 0)
Local Message, Result
Local TIP_MAXCHAR = 127, INFO_MAXCHAR = 199, TITLE_MAXCHAR = 47
Local buf = Buffer((auPtrSize = 4 ? 956 : 976))
buf.Zero()
Local FLAGS = BitOR((CallbackMessage = 0 ? 0 : NIF_MESSAGE), _
(hIcon = 0 ? 0 : NIF_ICON), _
(StrLen(Tip) = 0 ? 0 : NIF_TIP), _
(StrLen(InfoText) = 0 ? 0 : NIF_INFO))
Switch Action
Case "add"
Message = 0
Case "set"
Message = 1
Case "delete"
Message = 2
Else
Return
EndSwitch
If auX64 Then
buf.SetNum(0, "dword", buf.size)
buf.SetNum(8, "hwnd", AUTORUN_TCHANDLE)
buf.SetNum(16, "uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage)
buf.SetNum(32, "ptr", hIcon)
Else
buf.SetNum(0, "dword", buf.size, _
"hwnd", AUTORUN_TCHANDLE, _
"uint", ID, _
"uint", FLAGS, _
"uint", CallbackMessage, _
"ptr", hIcon)
EndIf
If StrLen(Tip) > 0 Then
buf.SetStr(StrLeft(Tip, TIP_MAXCHAR) & Chr(0), (auX64 ? 40 : 24)) # auPtrSize*2 + 4*4 + padding for X64
EndIf
If StrLen(InfoText) > 0 Then
buf.SetStr(StrLeft(InfoText, INFO_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 264) # 256 + 4 + 4
If StrLen(InfoTitle) > 0 Then
buf.SetStr(StrLeft(InfoTitle, TITLE_MAXCHAR) & Chr(0), (auX64 ? 40 : 24) + 780) # 512 + 4
EndIf
If InfoType > 0 Then
buf.SetNum((auX64 ? 40 : 24) + 780 + 128, "dword", InfoType)
EndIf
EndIf
Result = DllCall("Shell32.dll\Shell_NotifyIconW", "uint", Message, "ptr", buf.ptr, "bool")
Free(buf)
Return Result
EndFunc |
Добавил туда важных комментариев, которые позволят быстрее разобраться, но если коротко, сейчас используются две функции: одна для добавления иконок в трей и работы с ними (NotifyIcon), другая - только для показа уведомлений (NotifyInfoMessage):
 Hidden text Code: | 1.Отображение иконки в трее:
https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
Action - тип операции ("add", "set", "delete")
ID - внутренний идентификатор иконки (1001, 1002, ...)
CallbackMessage - код сообщения для обратного вызова (99999, 99998, ...)
hIcon - дескриптор иконки (обязателен для "add", необязателен для "set")
Tip - текст подсказки в трее
InfoText - текст уведомления (только при операции "add" или "set")
InfoTitle - текст заголовка уведомления
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Func NotifyIcon(Action, ID, CallbackMessage = 0, hIcon = 0, Tip = "", InfoText = "", InfoTitle = "", InfoType = 0)
2.Функция для показа системных уведомлений:
Icon - иконка в трее (1 - да, 0 - нет)
InfoText - текст уведомления (199 символов)
InfoTitle - текст заголовка уведомления (47 символов)
InfoType - флаги NIIF_* меняющие вид и поведение окна уведомлений
Функция использует идентификатор "1010" и номер сообщения "99998"
Func NotifyInfoMessage(Icon, InfoText, InfoTitle = "Autorun", InfoType = 0) |
Кнопки для тестов:
 Hidden text TOTALCMD#BAR#DATA
64000
%COMMANDER_EXE%,1
Иконка в трее
1
-1
 Hidden text TOTALCMD#BAR#DATA
64001
%COMMANDER_EXE%,1
Смена икоки в трее|ALT - Только сообщение|CTRL - Добавление второй
1
-1
 Hidden text TOTALCMD#BAR#DATA
64002
%COMMANDER_EXE%,1
Тест уведомления
1
-1
Первая кнопка включает или отключает иконку в трее, вторая меняет иконку и показывает сообщения, третья тестируют уведомления.
В основном файле конфигурации важно не забыть удалить иконки при выходе в секции финализации:
 Hidden text Code: | Pragma AutorunFinalizeSection
# удаление иконок
If Tray1001 > 0 Then NotifyIcon("delete", 1001)
If Tray1002 > 0 Then NotifyIcon("delete", 1002) |
Loopback, хотел попробовать сделать по мотивам темы:
https://www.autohotkey.com/boards/viewtopic.php?t=110783
Там есть рабочий код на AutoHotkey, вроде ничего сложного:
 Hidden text Code: | class UCharDet
{
#DllLoad 'libuchardet.dll'
/**
* Create an encoding detector.
* @return an instance of uchardet_t.
*
* UCHARDET_INTERFACE uchardet_t uchardet_new(void);
*/
Ptr := DllCall('libuchardet\uchardet_new', 'CDecl Ptr')
/**
* Delete an encoding detector.
* @param ud [in] the uchardet_t handle to delete.
*
* UCHARDET_INTERFACE void uchardet_delete(uchardet_t ud);
*/
__Delete() => this.Ptr && DllCall('libuchardet\uchardet_delete', 'Ptr', this, 'CDecl')
/**
* Feed data to an encoding detector.
* The detector is able to shortcut processing when it reaches certainty
* for an encoding, so you should not worry about limiting input data.
* As far as you should be concerned: the more the better.
*
* @param ud [in] handle of an instance of uchardet
* @param data [in] data
* @param len [in] number of byte of data
* @return non-zero number on failure.
*
* UCHARDET_INTERFACE int uchardet_handle_data(uchardet_t ud, const char * data, size_t len);
*/
HandleData(pBytes, cBytes) => DllCall('libuchardet\uchardet_handle_data', 'Ptr', this, 'Ptr', pBytes, 'Ptr', cBytes, 'CDecl Int')
/**
* Notify an end of data to an encoding detector.
* @param ud [in] handle of an instance of uchardet
*
* UCHARDET_INTERFACE void uchardet_data_end(uchardet_t ud);
*/
DataEnd() => DllCall('libuchardet\uchardet_data_end', 'Ptr', this, 'CDecl')
/**
* Reset an encoding detector.
* @param ud [in] handle of an instance of uchardet
*
* UCHARDET_INTERFACE void uchardet_reset(uchardet_t ud);
*/
Reset() => DllCall('libuchardet\uchardet_reset', 'Ptr', this, 'CDecl')
/**
* Get an iconv-compatible name of the encoding that was detected.
* @param ud [in] handle of an instance of uchardet
* @return name of charset on success and "" on failure.
*
* UCHARDET_INTERFACE const char * uchardet_get_charset(uchardet_t ud);
*/
GetCharset() => DllCall('libuchardet\uchardet_get_charset', 'Ptr', this, 'CDecl AStr')
DetectBuffer(Buffer) {
this.Reset()
if res := this.HandleData(Buffer.Ptr, Buffer.Size)
throw Error("Internal 'libuchardet' error, uchardet_handle_data() returned " res)
this.DataEnd()
charset := this.GetCharset()
this.Reset()
return charset
}
}
UCD := UCharDet()
MsgBox UCD.DetectBuffer(FileRead('txt.txt', 'RAW')) ; GB18030 |
И вроде выложили последние библиотеки:
https://github.com/telppa/ahk-chardet/tree/main/Lib
Я проверил - скрипт на них работает. Решил сделать то же самое на Autorun, но последняя функция возвращает пустую строку. Если у вас будет время, посмотрите, пожалуйста, в чём может быть причина. Здесь даже два варианта )
 Hidden text Code: | Func DetectCharset()
Local sLib = COMMANDER_PATH & "\Ini\Tools\Libs\" & (auX64 ? "" : "x86") & "\uchardet.dll"
Local sFile = COMMANDER_PATH & "\Ini\Tools\Libs\test.txt", sBuf
Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
If hLib = 0 Then Return
ProcessExecGetOutput sBuf %COMSPEC% '/c type "%sFile%"'
Local hUC = DllCall('uchardet\uchardet_new', 'ptr:cdecl')
DllCall('uchardet\uchardet_reset', 'ptr', hUC, 'cdecl')
Local nBytes = StrLen(sBuf)
Local Res = DllCall('uchardet\uchardet_handle_data', 'ptr', hUC, 'str', sBuf, 'uint', nBytes, 'int:cdecl')
MsgBox(hLib & auCRLF & hUC & auCRLF & nBytes & auCRLF & Res)
DllCall('uchardet\uchardet_data_end', 'ptr', hUC, 'cdecl')
Local sCharSet = DllCall('uchardet\uchardet_get_charset', 'ptr', hUC, 'str:cdecl')
MsgBox(sCharSet)
DllCall('uchardet\uchardet_delete', 'ptr', hUC, 'cdecl')
#DllCall('uchardet\uchardet_reset', 'ptr', hUC, 'cdecl')
EndFunc
|
 Hidden text Code: | Func DetectCharset2()
Local sLib = COMMANDER_PATH & "\Ini\Tools\Libs\" & (auX64 ? "" : "x86") & "\uchardet.dll"
Local txt
txt = "* Feed data to an encoding detector." & auCRLF & _
"* The detector is able to shortcut processing when it reaches certainty" & auCRLF & _
"* for an encoding, so you should not worry about limiting input data." & auCRLF & _
"* As far as you should be concerned: the more the better."
Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
If hLib = 0 Then Return
Local hUC = DllCall('uchardet\uchardet_new', 'ptr:cdecl')
DllCall('uchardet\uchardet_reset', 'ptr', hUC, 'cdecl')
Local buf = Buffer(StrLen(txt))
buf.SetStr(txt, 0, "ANSI")
Local Res = DllCall('uchardet\uchardet_handle_data', 'ptr', hUC, 'ptr', buf.ptr, 'uint', buf.size, 'int:cdecl')
MsgBox(hLib & auCRLF & hUC & auCRLF & buf.size & auCRLF & Res)
DllCall('uchardet\uchardet_data_end', 'ptr', hUC, 'cdecl')
Local sCharSet = DllCall('uchardet\uchardet_get_charset', 'ptr', hUC, 'str:cdecl')
MsgBox(sCharSet)
#DllCall('uchardet\uchardet_delete', 'ptr', hUC, 'cdecl')
DllCall('uchardet\uchardet_reset', 'ptr', hUC, 'cdecl')
EndFunc |
|
|
Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1483
|
(Separately) Posted: Sun Mar 02, 2025 19:32 Post subject: |
|
|
Orion9 wrote: | Решил сделать то же самое на Autorun, но последняя функция возвращает пустую строку. |
В Autorun сейчас при задании cdecl тип параметра не опционален. Можно использовать int:cdecl для uchardet_get_charset. Сделаю опциональным.
Вторая проблема в том, что типы str/wstr в качестве возвращаемого значения по факту не работали. Я точно тестировал такой случай, но с тех пор, похоже, сломал. Исправил.
Есть обходной путь, но смысла нет, всё равно сегодня будет новая версия. |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Sun Mar 02, 2025 20:23 Post subject: |
|
|
Loopback wrote: | сегодня будет новая версия. |
Супер )
А можно ли сделать, чтобы GetState("threads") возвращала имена потоков в своём результате? А то сейчас не так просто понять "who is who" ))
 Hidden text Code: | Thread #1:
Origin: Main
ThreadID: 1648
Started: 02.03.2025 11:00:02
Thread #2:
Origin: RunThread
ThreadID: 10040
Started: 02.03.2025 11:00:03
Thread #3:
Origin: RunThread
ThreadID: 7736
Started: 02.03.2025 11:00:04
Thread #4:
Origin: RunThread
ThreadID: 9480
Started: 02.03.2025 11:00:04
Thread #5:
Origin: RunThread
ThreadID: 9796
Started: 02.03.2025 11:00:04 |
Два раза сбрасывал код и два раза забывал спросить. Параметры по-умолчанию, которые можно опускать в функциях, обязательно надо заменять пустыми кавычками? Первый вариант рабочий:
Code: | NotifyIcon("set", 1001, 99999, hIco, "", "Icon changed to shell32.dll, " & i, "", NIIF_INFO)
|
Второй приводит к неожиданным результатам:
Code: | NotifyIcon("set", 1001,, hIco,, "Icon changed to shell32.dll, " & i,, NIIF_ERROR)
|
Ещё пара вопросов по поводу переменных окружения в будущих версиях:
1. В дериктиве Pragma можно будет оставить всё без изменений? Такая запись и дальше будет рабочей?
Code: | Pragma Include %COMMANDER_PATH%\Ini\Scripts\Test.aucfg
|
2. Если есть переменная Local Dir = "%COMMANDER_PATH%\Ini\", то в командах: %"Dir%" равно "%COMMANDER_PATH%\Ini\", а %"%Dir%" равно "C:\Portable\TOTALCMD\Ini\"? Если да, то не изменится ли такое поведение в будущих версиях, или надо как-то по-другому раскрывать? |
|
Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1483
|
(Separately) Posted: Sun Mar 02, 2025 22:43 Post subject: |
|
|
Orion9 wrote: | имена потоков |
Если только имя вызываемой пользовательской функции, какие еще имена у потоков могут быть? Забавно, код для этого уже был сделан, но забыл включить. Хотя я до сих пор так и не понимаю, какой смысл в этой информации...
Orion9 wrote: | Параметры по-умолчанию, которые можно опускать в функциях, обязательно надо заменять пустыми кавычками? |
В настоящее время метод записи с пропусками официально не поддерживается и делать так я бы не рекомендовал, никаких гарантий, что это не изменится. Хотя сейчас такая запись генерирует правильное число параметров, пропущенные параметры для функции - пустые строки, которые там где требуется число - приводятся к 0.
Orion9 wrote: | Такая запись и дальше будет рабочей? |
Здесь ничего не планировалось менять.
Orion9 wrote: | Если да, то не изменится ли такое поведение в будущих версиях, |
Знал бы где упасть... Стопроцентной гарантии, конечно, нельзя дать, но конкретно в работу вычисляемых строк я не собирался вмешиваться, это уже своего рода legacy. Короче, в данный момент в планах нет. |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Sun Mar 02, 2025 23:35 Post subject: |
|
|
Loopback wrote: | Забавно, код для этого уже был сделан, но забыл включить. Хотя я до сих пор так и не понимаю, какой смысл в этой информации. |
Когда крутился один-два потока, смысла большого не было, согласен. Но сейчас у меня бывает по 5-6 потоков крутится, так как приходится часто эксперементировать. Как-то раз забыл закомментировать один поток, после того, как он перестал быть нужным, так я потом понять долго не мог, откуда он взялся
Имя потока - это я неправильно выразился. Речь идет об имени функции, как вы правильно отметили.
Loopback wrote: | В настоящее время метод записи с пропусками официально не поддерживается и делать так я бы не рекомендовал |
Не совсем понял. То есть обе записи следует избегать, и с кавычками тоже?
Loopback wrote: | конкретно в работу вычисляемых строк я не собирался вмешиваться, это уже своего рода legacy. |
Просто я пересматриваю сейчас код. Заметил, что в некоторых случаях у меня завязано именно на раскрытие переменных окружения, но в большинстве других используется избыточная запись, например:
Code: | i += 1
IniWrite %bar% "Buttonbar" %"'Menu' & %i%" %"%i%-2"
| Я все такие записи исправил на:
Code: | IniWrite %bar% "Buttonbar" %"'Menu' & i" %"i-2" |
Но иногда нужно, чтобы переменная раскрылась:
Code: | SetEnv COMMANDER_VIDEO %"%SoftVideo%" |
или:
Code: | ProcessExecGetOutput /OEM out %COMSPEC% "/c dir /s /b *.wav" %"%dir%" |
В общем, хотел убедиться, что такие записи допустимы, правильны и не будут в будущем как-то меняться.
Хотел еще про определения яыка спросить. Мне нужно узнать, является ли система англоязычной (UI), если нет, то считать её русской. Как вы думаете, такая функция подойдет?
 Hidden text Code: | Func GetSysLanguage()
Local Ret = DllCall("GetUserDefaultUILanguage")
# ru-RU 0x0419 1049
# en-US 0x0409 1033
# en-GB 0x0809 2057
# en-AU 0x0C09 3081
# en-CA 0x1009 4105
# en-NZ 0x1409 5129
# en-IE 0x1809 6153
# en-ZA 0x1C09 7177
# en-IN 0x4009 16393
# MsgBox("Return: " & Ret)
If Ret = 1033 Or Ret = 2057 Or Ret = 3081 Or Ret = 4105 Or Ret = 5129 Then Return "en"
Return "ru"
EndFunc
|
Хотел добавить возможность обработки англоязычной вкладки:
 Hidden text Code: | Func FileSecInfo(lParam)
Static SEE_MASK_INVOKEIDLIST = 0x0000000C, _
LPSHELLEXECUTEINFO = (auX64 ? 112 : 60) , _
SW_SHOWNORMAL = 1, SW_SHOW = 5
Local p = RequestCopyDataInfo("SP")
Local n = RequestCopyDataInfo("SN")
Local f = p & n
If Not FileExist(f) Then
ShowHint("Файл не существует " & f)
Return
Endif
Local buff = Buffer(LPSHELLEXECUTEINFO), verb = Buffer(10*2+2), file = Buffer(StrLen(f)*2+2), param = Buffer(12*2+2)
buff.Zero() # обнуляем память
verb.SetStr("properties" & Chr(0))
file.SetStr(f & Chr(0))
#param.SetStr("Security" & Chr(0))
param.SetStr("Безопасность" & Chr(0))
buff.SetNum(0, "dword", buff.size, _
"ulong", SEE_MASK_INVOKEIDLIST, _
"ptr", 0, _
"ptr", verb.Ptr, _
"ptr", file.Ptr, _
"ptr", param.Ptr, _
"ptr", 0, _
"int", SW_SHOWNORMAL)
DllCall("shell32\ShellExecuteExW", "ptr", buff.Ptr)
Free(buff, verb, file, param)
EndFunc |
|
|
Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1483
|
(Separately) Posted: Mon Mar 03, 2025 00:36 Post subject: |
|
|
Версия Autorun 2.2.17 beta
 Список изменений
- SendMessage/PostMessage не работали с HWND_BROADCAST
- в DllCall исправлены типы str и wstr для возвращаемого значения
- в List метод Split работал неправильно с разделителем в конце строки
+ ShellExec устанавливает значение макроса SYSERROR(TEXT) при ошибке
- ShellExec не запускала некоторые типы файлов (например, cpl)
- исправлена обрезка значений типа ptr/handle в DllCall
- ModifyDialogs: исправлена работа флага 4 центрирования AddDialog, если окно не имеет родителя
+ параметр в SendCommand для отправки команд через SendMessage
+ Runtime: добавлена функция GetCurrentPath, в GetCurrentItem изменен порядок индексов, добавлены новые
+ добавлено свойство SortMethod в List, добавлена натуральная сортировка (Windows7+)
+ LngRead при первом вызове будет использовать текущий язык, если второй параметр не задан
+ добавлен объект Map
+ добавлена функция MakeInt
+ в функции Ini* добавлена поддержка AlternateUserIni
* убрана функция Opt
* КРИТИЧНО: в функциональной записи убрано разворачивание переменных в тексте парамеров в ряде функций
- функция RegRead иногда возвращала мусор для REG_SZ и REG_EXPAND_SZ строк
В этой версии критическое изменение: исправление известной проблемы с лишним разворачиванием переменных в тексте параметров ряда функций в функциональной записи, что связано с разными принципами работы с параметрами в разных записях. Это касается всех функций, где было такое разворачивание.
 Список затронутых функций
CommandExec
ShellExec
LoadLibrary
LoadFont
LngRead
MsgBox
SetEnv
StrLeft
StrLen
StrLower
StrMid
StrPart
StrPos
StrReplace
StrRight
StrTrim
StrUpper
IniDelete
IniRead
IniReadSection
IniReadSectionNames
IniRenameSection
IniWrite
IniWriteSection
FileExist
FileGetAttr
FileGetSize
FileGetTime
FileGetVersion
FileSetAttr
FileSetTime
ProcessCount
ProcessExecGetOutput
ProcessGetId
ProcessExist
ProcessTerminate
К сожалению, в свое время критичность этого была недооценена. Найти приемлемое решение с полным сохранением совместимости не удалось, поэтому было принято решение радикально устранить проблему. Некоторые записи могут перестать работать, но исправить это в скриптах достаточно просто.
 Подробно про исправление
Перестанет работать код в функциональной записи, который основывался на разворачивании переменных прямо в тексте:
Code: | Например
FileGetAttr("%COMMANDER_PATH%\Totalcmd.exe")
нужно заменить на
FileGetAttr(COMMANDER_PATH & "\Totalcmd.exe")
или
FileGetAttr(Set("%COMMANDER_PATH%\Totalcmd.exe"))
|
Если текст с %переменной% содержится в другой переменной и раньше код основывался на разворачивании этого текста в параметре функции, то теперь в функциональной записи разворачивание производиться не будет. Чтобы достичь такого же результата, нужно будет добавить Set для явного разворачивания содержимого переменной:
Code: | path = "%COMMANDER_PATH%\Totalcmd.exe"
Было
FileGetAttr(path)
стало
FileGetAttr(Set(path)) |
Переключатель /EV-, встречающийся в ряде функций, теперь будет неприменим при записи в ФЗ.
Все записи функций в командном виде должны сохранить работоспособность без изменений.
Все же очень неудобна эта фича форума со склеиванием последовательных сообщений. Было бы куда логичнее выложить версию в одном посте, а ответы дать в другом...
Orion9 wrote: | То есть обе записи следует избегать, и с кавычками тоже? |
Это про вторую. С первой вопросов нет.
Orion9 wrote: | Я все такие записи исправил на: |
Правильно.
Orion9 wrote: | Но иногда нужно, чтобы переменная раскрылась: |
Похоже, я не совсем точно понял изначальный вопрос.
Quote: | Если есть переменная Local Dir = "%COMMANDER_PATH%\Ini\", то в командах: %"Dir%" равно "%COMMANDER_PATH%\Ini\", а %"%Dir%" равно "C:\Portable\TOTALCMD\Ini\"?
|
Разве? В первом случае лишний %, предполагаю опечатка. Вот код:
Code: | Local Dir = "%COMMANDER_PATH%\Ini\"
# тут содержимое не раскрывается OutputDebugString, поэтому выводит как есть
OutputDebugString %"Dir"
OutputDebugString %"%Dir%"
# тут содержимое второй раз раскрывается самим MsgBox
MsgBox %"Dir"
MsgBox %"%Dir%"
|
В любом случае выводит одинаковый результат.
Всё что внутри вычисляемой строки - считается выражением и подчиняется их правилам. А значит, в следующей версии такие записи %"%i%-2" тоже будут некорректны. Кстати забыл про этот вариант, надо его упомянуть в анонсе.
Такие записи идентичны, и правильной в будущем будет вторая:
Code: | SetEnv COMMANDER_VIDEO %"%SoftVideo%"
SetEnv COMMANDER_VIDEO %"SoftVideo" |
Но вообще-то SetEnv и без вычисляемых строк поддерживает переменные:
Code: | SetEnv COMMANDER_VIDEO %SoftVideo% |
И тут по тому же принципу:
Code: | ProcessExecGetOutput /OEM out %COMSPEC% "/c dir /s /b *.wav" %"dir" |
В общем поэтому и надо привести всё к одному знаменателю, а то неслабая путаница возникает.
Orion9 wrote: | такая функция подойдет? |
Мне кажется странной идея считать систему русской, если она не английская, а так с виду ок. Но не уверен. |
|
Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 262
|
(Separately) Posted: Mon Mar 03, 2025 15:20 Post subject: |
|
|
Loopback wrote: | Некоторые записи могут перестать работать |
Code: |
ShellExec %COMMANDER_PATH%\Utilities\MENUIMG\MENUIMG.exe %COMMANDER_PATH%\Bars\RESTART_RUS.BAR||#INPUT
IniRead /R flt %COMMANDER_INI% "Associations" "Filter1" ""
SetEnv AssocIco "%COMMANDER_PATH%\Images\Others\ICO\Light\LightOn.ico"
|
После обновления до Autorun 2.2.17 beta все эти выражения и подобные продолжают работать. Это правильно или надо их заранее переписать?
А переменные и до обновления только так работали:
Code: |
Local ini_WinTitle = %COMMANDER_PATH% & "\Ini\WinTitle.ini"
|
Тогда что изменилось? |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Mon Mar 03, 2025 18:11 Post subject: |
|
|
Loopback
Всё заработало влёт, я аж офигел ) Спасибо!
Code: | Pragma AutorunPluginFields "CharSet:::CharDetect"
Func CharDetect(FileName, FieldIndex, UnitIndex)
Static sLib = "uchardet" & (auX64 ? "" : "_x86") & ".dll", _
hLib = DllCall("LoadLibrary", "wstr", COMMANDER_PATH & "\Ini\Tools\Libs\" & sLib, "ptr")
If hLib = 0 Then Return "#Error# LoadLibrary " & sLib
Static hUC = DllCall(sLib & '\uchardet_new', 'ptr:cdecl')
If hUC = 0 Then Return "#Error# uchardet_new returned 0"
DllCall(sLib & '\uchardet_reset', 'ptr', hUC, 'cdecl')
ProcessExecGetOutput buf %COMSPEC% '/c type "%FileName%"'
Local size = StrLen(buf)
Local Res = DllCall(sLib & '\uchardet_handle_data', 'ptr', hUC, 'str', buf, 'uint', size, 'int:cdecl')
If Res > 0 Then Return "#Error# uchardet_handle_data returned " & Res
DllCall(sLib & '\uchardet_data_end', 'ptr', hUC, 'cdecl')
Return DllCall(sLib & '\uchardet_get_charset', 'ptr', hUC, 'str:cdecl')
#DllCall('uchardet\uchardet_delete', 'ptr', hUC, 'cdecl')
EndFunc
|
Знаю, что ProcessExecGetOutput для этих дел не годится, но это только эксперимент. Надеюсь, в будущем у Autorun найдутся свои функции для открытия файлов на чтение А пока можно через консольную утилиту гнать:
https://github.com/gentlehill/uchardet?tab=readme-ov-file
и код совсем простой:
Code: | Func EncDetect(FileName, FieldIndex, UnitIndex)
Local pipe, exe_tool = COMMANDER_PATH & "\Ini\Tools\uchardet.exe"
ProcessExecGetOutput pipe %exe_tool% '"%FileName%"'
Return pipe
EndFunc
|
И большое спасибо за имена функций в GetState. Теперь выглядит как надо:
Code: | Thread #1:
Origin: Main
ThreadID: 3388
Started: 03.03.2025 16:47:52
Thread #2:
Origin: RunThread
Function: ThreadTitle
ThreadID: 4704
Started: 03.03.2025 16:47:53
Thread #3:
Origin: RunThread
Function: ThreadNewsbar
ThreadID: 3404
Started: 03.03.2025 16:47:53
Thread #4:
Origin: RunThread
Function: ThreadSounds
ThreadID: 1536
Started: 03.03.2025 16:47:53 |
Это далеко не всё. Ещё позже отпишусь.
Добавлено спустя 4 минуты:
AkulaBig
Скорее всего вам придется, как и мне, избавляться от таких записей:
К сожалению, на ранних этапах использования Autorun я не разобрался с этой записью и допустил ошибку. Теперь приходится все исправлять. |
|
Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 262
|
(Separately) Posted: Mon Mar 03, 2025 18:22 Post subject: |
|
|
Orion9 wrote: | Скорее всего вам придется, как и мне, избавляться от таких записей: |
Я еще в прошлый раз от них избавился по наводке Loopback. А сейчас посмотрел, есть еще одна такая запись. |
|
Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1483
|
(Separately) Posted: Mon Mar 03, 2025 21:29 Post subject: |
|
|
AkulaBig wrote: | После обновления до Autorun 2.2.17 beta все эти выражения и подобные продолжают работать. Это правильно или надо их заранее переписать? |
Правильно. Я же специально акцентировал внимание, что изменения коснулись только функций по списку и только в функциональной записи.
Эти три функции хоть и в списке, но они записаны в командной записи, их трогать не нужно.
И в следующей версии эти три записи тоже не пострадают, т.к. в них нет вычисляемых строк.
AkulaBig wrote: | Тогда что изменилось? |
Так, а анонс-то для чего? Там же чётко написано, на какие случаи надо обратить внимание. Их всего-то два. В посте выше спойлер Подробно про исправление.
Для лучшего понимания, ваш первый пример. Если бы он был записан так:
Code: | ShellExec("%COMMANDER_PATH%\Utilities\MENUIMG\MENUIMG.exe", "%COMMANDER_PATH%\Bars\RESTART_RUS.BAR||#INPUT") |
то в предыдущей версии он бы работал, а в новой гарантированно сломался.
Orion9 wrote: | найдутся свои функции для открытия файлов на чтение |
Обязательно найдутся.
Orion9 wrote: | на ранних этапах использования Autorun я не разобрался с этой записью и допустил ошибку |
Не исключаю, что возможно я и сам когда-то где-то писал так же. В то время были такие, не самые удачные решения, типа для "облегчения перехода" и "сохранения совместимости". А в итоге всё равно приходится менять. |
|
Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 262
|
(Separately) Posted: Mon Mar 03, 2025 21:38 Post subject: |
|
|
Loopback wrote: | Так, а анонс-то для чего? |
Все ясно. Просто хотелось вашего разъяснения. Сразу стало наглядно понятно, как должны выглядеть правильные записи.
А то я левым полушарием разбираюсь с Autorun, правым WinDjView, написанным на MFC. Сделал плагин для него. А там полно рогаток, пришлось кодить. И тут и там методом тыка. Аж самому смешно  |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Tue Mar 04, 2025 00:19 Post subject: |
|
|
Loopback wrote: | Похоже, я не совсем точно понял изначальный вопрос. |
Просто мне не нужно было мудрить с ним ) Надо было просто спросить, равны ли эти две записи или нет. Да и вообще, стоило самому проверить прежде, чем на форум писать.
Loopback wrote: | В первом случае лишний %, предполагаю опечатка. |
Да, опечатка. Причём дурацкая и в самом ненужном месте )
Loopback wrote: | В любом случае выводит одинаковый результат. |
Не знаю, откуда у меня взялась идея, что проценты в вычисляемой строке раскрывают переменные окружения. Но иногда требуется именно раскрыть. Т.е. если SoftVideo = "%POT_PLAYER%", а POT_PLAYER = "%COMMANDER_PATH%\Soft\PotPlayer\PotPlayerMini.exe", то:
Code: | SetEnv COMMANDER_VIDEO %SoftVideo% |
Не раскроет переменную, и COMMANDER_VIDEO будет равен "%POT_PLAYER%". А запись:
Code: | SetEnv COMMANDER_VIDEO %"SoftVideo" |
Раскрывает, и тогда COMMANDER_VIDEO содержит в себе полный путь к PotPlayerMini.exe, что и требуется в одной задаче.
Loopback wrote: | Мне кажется странной идея считать систему русской, если она не английская |
А мне другого и не нужно Делать многоязычную поддержку планов нет, просто заметил, что при минимальных усилиях можно учесть в коде английский UI, добавив условие к:
Code: | param.SetStr("Security" & Chr(0))
param.SetStr("Безопасность" & Chr(0)) |
То же самое относится и к строке поиска окна выбора цвета, где предусмотрен только русский вариант:
Code: | h = WinFind(0, "#32770", "Цвет") |
А что касается релиза, то пока всё работает, но завтра я буду больше тестировать, тогда и посмотрим. Но надо сказать, что такими темпами, скоро и AutoHotkey будет не нужен  |
|
Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 716
|
(Separately) Posted: Wed Mar 05, 2025 18:14 Post subject: |
|
|
Проиграть звук в Autorun? Да без проблем!
Code: | file = "C:\Windows\Media\tada.wav"
DllCall("Winmm.dll\PlaySoundW", "wstr", file, "ptr", 0, "dword", 131072 + 1) |
Loopback, пока не поставил в конце имени PlaySoundW, функция не хотела работать, хотя в справке говорится, что такая подстановка должна происходить автоматически. Уже второй раз замечаю.
Решил переделать тёмный хинт под новые параметры задержки:
Code: | Func ShowDarkHint(DarkHint, Delay = 0, Flags = 0)
# формат подсказки
SetHintParam("ShowHint", "Font", 10, "Arial")
SetHintParam("ShowHint", "BackColor", 0x001C1C1C)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
# отображение подсказки
ShowHint(DarkHint, "", "", Delay, Flags)
# возвращение формата по умолчанию
Sleep(50)
SetHintParam("ShowHint", "Reload")
EndFunc
|
Поскольку у этой функции два необязательных параметра на конце, не будет ли каких проблем с простым вызовом вроде ShowDarkHint("Текст"), или лучше указывать хотя бы один параметр, т.е. ShowDarkHint("Текст", 0)?
Раньше у меня был второй вариант. |
|
Back to top |
|
 |
Loopback
Joined: 07 Sep 2009 Posts: 1483
|
(Separately) Posted: Wed Mar 05, 2025 21:32 Post subject: |
|
|
Orion9 wrote: | хотя в справке говорится, что такая подстановка должна происходить автоматически |
В справке говорится, что если
Quote: | ...такой функции не окажется в перечисленных выше библиотеках, будет произведена попытка... |
Т.е. схема применяется только к перечисленному списку, winmm.dll в нем отсутствует.
С другой стороны, получение адреса не сильно ресурсоемкая операция, наверно, можно распространить и на другие библиотеки. Но в любом случае лучше использовать суффикс W явно, будет чуть-чуть, но быстрее.
Orion9 wrote: | Поскольку у этой функции два необязательных параметра на конце, не будет ли каких проблем с простым вызовом вроде ShowDarkHint("Текст"), или лучше указывать хотя бы один параметр, т.е. ShowDarkHint("Текст", 0)? |
С чего бы им быть? Параметры со значением по умолчанию для таких задач и предназначены. |
|
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
|