| 
 
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| Orion9 
 
  
 Joined: 01 Jan 2024
 Posts: 915
 
 
 | 
			
				|  (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: 915
 
 
 | 
			
				|  (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 textTOTALCMD#BAR#DATA
64000
 
 %COMMANDER_EXE%,1
 Иконка в трее
 
 1
 -1
 
   Hidden textTOTALCMD#BAR#DATA
64001
 
 %COMMANDER_EXE%,1
 Смена икоки в трее|ALT - Только сообщение|CTRL - Добавление второй
 
 1
 -1
 
   Hidden textTOTALCMD#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: 1639
 
 
 | 
			
				|  (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: 915
 
 
 | 
			
				|  (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: 1639
 
 
 | 
			
				|  (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: 915
 
 
 | 
			
				|  (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: 1639
 
 
 | 
			
				|  (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: 454
 
 
 | 
			
				|  (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: 915
 
 
 | 
			
				|  (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: 454
 
 
 | 
			
				|  (Separately) Posted: Mon Mar 03, 2025 18:22    Post subject: |   |  
				| 
 |  
				|  	  | Orion9 wrote: |  	  | Скорее всего вам придется, как и мне, избавляться от таких записей: | 
 Я еще в прошлый раз от них избавился по наводке Loopback. А сейчас посмотрел, есть еще одна такая запись.
 |  |  
		| Back to top |  |  
		|  |  
		| Loopback 
 
 
 Joined: 07 Sep 2009
 Posts: 1639
 
 
 | 
			
				|  (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: 454
 
 
 | 
			
				|  (Separately) Posted: Mon Mar 03, 2025 21:38    Post subject: |   |  
				| 
 |  
				|  	  | Loopback wrote: |  	  | Так, а анонс-то для чего? | 
 Все ясно. Просто хотелось вашего разъяснения. Сразу стало наглядно понятно, как должны выглядеть правильные записи.
 А то я левым полушарием разбираюсь с Autorun, правым WinDjView, написанным на MFC. Сделал плагин для него. А там полно рогаток, пришлось кодить. И тут и там методом тыка. Аж самому смешно
  |  |  
		| Back to top |  |  
		|  |  
		| Orion9 
 
  
 Joined: 01 Jan 2024
 Posts: 915
 
 
 | 
			
				|  (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: 915
 
 
 | 
			
				|  (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: 1639
 
 
 | 
			
				|  (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
 
 |