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

Добавлено: Пн янв 13, 2025 16:30
Orion9
AkulaBig писал(а):Скорей всего без разницы.
Как бы сказал герой одного известного фильма: "Лёлик, но ведь это не эстетично" :lol:

Если запустить монитор процессов, то уже через несколько секунд все окно будет засыпано примерно этим:

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

TOTALCMD.EXE	5220	CreateFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	LockFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	QueryStandardInformationFile	D:\Temp\TotalCommanderPortable\wincmd.in
TOTALCMD.EXE	5220	ReadFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	UnlockFileSingle	D:\Temp\TotalCommanderPortable\wincmd.ini	
TOTALCMD.EXE	5220	CloseFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	CreateFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	LockFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	QueryStandardInformationFile	D:\Temp\TotalCommanderPortable\wincmd.in
TOTALCMD.EXE	5220	ReadFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	UnlockFileSingle	D:\Temp\TotalCommanderPortable\wincmd.ini	
TOTALCMD.EXE	5220	CloseFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	CreateFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	LockFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	QueryStandardInformationFile	D:\Temp\TotalCommanderPortable\wincmd.in
TOTALCMD.EXE	5220	ReadFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	UnlockFileSingle	D:\Temp\TotalCommanderPortable\wincmd.ini	
TOTALCMD.EXE	5220	CloseFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	CreateFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	LockFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	QueryStandardInformationFile	D:\Temp\TotalCommanderPortable\wincmd.in
TOTALCMD.EXE	5220	ReadFile	D:\Temp\TotalCommanderPortable\wincmd.ini	SUCCESS	
TOTALCMD.EXE	5220	UnlockFileSingle	D:\Temp\TotalCommanderPortable\wincmd.ini	
Но все же я склонен с вами согласиться, что в данном случае это "без разницы". Потому что если открыть Монитор Ресурсов или Process Explorer от Sysinternals, то можно увидеть, что I/O дисковых операций от процесса Totalcmd.exe есть, но самих дисковых операций (чтения/записи) нет. Видимо, всё это просто гоняется в кэше до тех пор, пока файл на диске действительно не изменится.

Все-равно я думаю, Гислеру можно было бы сделать такую переменную, тем более что это несложно.
sa писал(а):Ещё, если это %COMMANDER_EXE% или имя программы без пути (Totalcmd.exe/TOTALCMD64.EXE). Планируется добавление shell32.dll и, возможно, imageres.dll.
Это безусловно радует, но хотелось бы, чтобы и другие библиотеки значков тоже умел читать :)

Добавлено: Пн янв 13, 2025 16:51
sa
Orion9
Там проблема в производительности, если я правильно понял:
Help писал(а):New functions and fixes in Total Commander 11.50:
Menu: Use icon defined in em_command, but only from wcmicons.dll or .ico files or from the main program, for speed reasons (virus scanners)

Добавлено: Пн янв 13, 2025 18:56
Orion9
sa
Ну, если пользователь решит сделать меню, где у него десятки пунктов будут завязаны на значки из exe-файлов, то это его выбор. Только какое отношение это имеет к возможностям Total Commander? :)

Да и потом, речь больше идет о DLL и ICL, содержащие пользовательские значки, помимо стандартного wcmicons.dll.

P.S. Пересмотрел и адаптировал код, который делал еще в том году, для создания трёх панелей uwdx.

[cut]

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

RegisterCommand 70900 "Uwdx3Bars"

Func Uwdx3Bars(lParam)
   Local bar = %COMMANDER_PATH% & "\Bars\", usr
   Local b_Ctrl = IsPressed(0x11), b_Shift = IsPressed(0x10), b_Alt = IsPressed(0x12)
   
   #создание панелей   
   If b_Alt Then
      CreateUwdxBars()
      Return
   EndIf

   If b_Ctrl Then 
      usr = "em_auto_uwdxp"
      bar = bar & "Auto_uwdxp.bar"
   ElseIf b_Shift Then
      usr = "em_auto_uwdxa"   
      bar = bar & "Auto_uwdxa.bar"   
   Else
      usr = "em_auto_uwdxe"   
      bar = bar & "Auto_uwdxe.bar"   
   EndIf   
        
   If FileExist(bar) Then
      CommandExec(usr)
      #ShowPopupMenu /D %bar%
   Else   
      ShowHint("Не найден " & bar) 
   EndIf
EndFunc

Func CreateUwdxBars()
   Local f = 0
   ShowDarkHint("Создание панелей", 0)   
   f = f + CreateUwdxBar("Auto_uwdxa")
   f = f + CreateUwdxBar("Auto_uwdxe")
   f = f + CreateUwdxBar("Auto_uwdxp")   
   ShowDarkHint(f & " из 3 файлов было создано", 0)
EndFunc

Func CreateUwdxBar(Barname)
   Local i = 0
   Local bar, br2, wdx
   Local uwdx_dir = "\Plugins\uwdx\"
   Local uwdx_exe = "%COMMANDER_PATH%" & uwdx_dir & "uwdx.exe"
   Local uwdx_con = "%%COMMANDER_PATH%%" & uwdx_dir & "uwdx.exe"
   Local uwdx_obj = "%P%N" 
   
   bar = %COMMANDER_PATH% & "\Bars\" & barname & ".bar"
   br2 = %COMMANDER_PATH% & "\Bars\" & barname & ".br2"
  
   ShellExec /SW_HIDE /WAIT:2000 %COMSPEC% "/c del /f /q ""%bar%"""
   ShellExec /SW_HIDE /WAIT:2000 %COMSPEC% "/c del /f /q ""%br2%"""
   
   If FileExist(bar) Then   
      MsgBox("Ошибка удаления " & bar, "uwdx")
      Return 0
   Endif
   
   IniWrite %bar% "Buttonbar" "Buttoncount"  "0"
   If ERROR = 1 Then 
      MsgBox("Ошибка создания " & bar, "uwdx")
      Return 0   
   EndIf
     
   While i < 100
      IniRead /R wdx %COMMANDER_INI% "ContentPlugins" %"%i%" "stop"
      If wdx="stop" Then Break
     
      wdx = StrTrim(StrRight(wdx, StrLen(wdx)-StrPos(wdx, "\", -1)))
      
      IniWrite %bar% "Buttonbar" %"'Button'   & %i%+1" %uwdx_exe%
      IniWrite %bar% "Buttonbar" %"'Menu'     & %i%+1" %wdx%   
      IniWrite /EV- %bar% "Buttonbar" %"'Cmd' & %i%+1" "%COMSPEC% /k"
      
      Switch Barname
         Case "Auto_uwdxa"
            IniWrite %bar% "Buttonbar" %"'Param' & %i%+1"  '"""%uwdx_con%""" /I %wdx% ""%uwdx_obj%""'
         Case "Auto_uwdxe"
            IniWrite %bar% "Buttonbar" %"'Param' & %i%+1"  '"""%uwdx_con%""" /E /I %wdx% ""%uwdx_obj%""' 
         Else
            IniWrite %bar% "Buttonbar" %"'Param' & %i%+1"  '"""%uwdx_con%""" /I "%wdx%"'
      EndSwitch
              
      i = i + 1
   Wend
   IniWrite %bar% "Buttonbar" "Buttoncount"  %i%
   Return 1
EndFunc

Func ShowUwdxe
   CommandExec em_auto_uwdxe
EndFunc

Func ShowUwdxa
   CommandExec em_auto_uwdxa
EndFunc

Func ShowUwdxp
   CommandExec em_auto_uwdxp
EndFunc

[/cut]
[cut]

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

[em_auto_uwdxe]
cmd=OPENBARMENU %COMMANDER_PATH%\Bars\Auto_uwdxe.bar
[em_auto_uwdxa]
cmd=OPENBARMENU %COMMANDER_PATH%\Bars\Auto_uwdxa.bar
[em_auto_uwdxp]
cmd=OPENBARMENU %COMMANDER_PATH%\Bars\Auto_uwdxp.bar
[/cut]
[cut]

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

TOTALCMD#BAR#DATA
70900

%COMSPEC%
Панели Uwdx|Alt - Создать панели|Ctrl - Структура полей|Shift - Все поля плагина


-1
[/cut]
Пользовательски команды можно привязать к хоткеям или кликам мышки, например:

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

ControlSetMouseAction /R /K:C 3 ShowUwdxe
ControlSetMouseAction /R /K:C /K:S 3 ShowUwdxa

Добавлено: Пн янв 13, 2025 20:39
AkulaBig
Orion9 писал(а): Если запустить монитор процессов, то уже через несколько секунд все окно будет засыпано примерно этим:
Запустите какой-нибудь шпион и увидите, что там творится с любым окном.

Добавлено: Пн янв 13, 2025 22:56
Orion9
AkulaBig
Да это понятно. Просто речь шла о файловых операциях как раз, а не об окнах. Loopback же подтвердил, что макрос AUTORUN_TCLANG просто считывает ключ из wincmd.ini, что равноценно обычному вызову функции IniRead. Как по мне, то между:

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

IniRead /R lng %COMMANDER_INI% "Configuration" "LanguageIni"
If lng = "WCMD_RUS.LNG" Then

Endif

И:

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

If %COMMANDER_LANG% = "WCMD_RUS.LNG" Then

Endif
Я бы однозачно выбрал второе :)

P.S. И все-таки добрались у меня руки до функции SuperWDX. В прошлый раз ее доделать помешал плагин wdx4i, который не хотел загружаться в объект, но поскольку Loopback исправил ошибку, я решил придать всему этому какой-то законченный вид:

[cut]

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

Func GetSuperWdx(FileName, FieldIndex, UnitIndex)
   
   Static video_ext = ".mp4 .mkv .avi", _
          audio_ext = ".mp3 .flac .m4a", _
          picture_ext = ".jpg .bmp .gif .png", _
          archive_ext = ".7z .rar .zip .cab .zst"     

    If StrPos(FileGetAttr(FileName), "D") Then
       Return "<Dir>"
    Endif

   Local file_ext    
   Local ext_pos = StrPos(FileName, '.', -1)
   
   if ext_pos > 0 Then
   
      file_ext = StrMid(FileName, ext_pos+1, StrLen(FileName)-ext_pos)
      
      If StrPos(video_ext, '.' & file_ext) Then Return GetVideoInfo(FileName)
      
      If StrPos(audio_ext, '.' & file_ext) Then Return GetAudioInfo(FileName)
      
      If StrPos(picture_ext, '.' & file_ext) Then Return GetPicsInfo(FileName)
      
      If StrPos(archive_ext, '.' & file_ext) Then Return GetArchInfo(FileName)                  

   Endif

EndFunc

Func GetVideoInfo(FileName)
Local s
   obj = Plugin("TCMediaInfo")
   If ERROR = 0 Then
      obj.FileName = FileName
      # All video as string      
      s = obj.GetValue(28)
      Free(obj)
   Else
      s = "Plugin error " & ERROR
   Endif
   Return s
EndFunc

Func GetAudioInfo(FileName)
Local s
   obj = Plugin("TCMediaInfo")
   If ERROR = 0 Then
      obj.FileName = FileName
      # All audio as string
      s = obj.GetValue(39)
      Free(obj)
   Else
      s = "Plugin error " & ERROR
   Endif
   Return s
EndFunc

Func GetPicsInfo(FileName)
Local s
   obj = Plugin("wdx4i")
   If ERROR = 0 then
      obj.FileName = FileName
      # wdx4i.pixw, wdx4i.pixh, wdx4i.orient, wdx4i.depth
      s = obj.GetValue(5)  & " x " & obj.GetValue(6) & " , " & obj.GetValue(7) & " , " & obj.GetValue(13)
      Free(obj)
   Else
      s = "Plugin error " & ERROR
   Endif
   Return s
EndFunc

Func GetArchInfo(FileName)
Local s
   obj = Plugin("Total7zip")
   If ERROR = 0 then
      obj.FileName = FileName
      s = (obj.GetValue(5) <> "" ? obj.GetValue(5) & ", " : "")      
      s &= "Folders: " & obj.GetValue(6) & ", Files: " & obj.GetValue(7)
      s &= (obj.GetValue(11) = "+" ? ", Solid" : "")
      s &= (obj.GetValue(1) = "+" ? ", Encripted" : "")      
      s &= (obj.GetValue(9) <> "" ? ", Method: " & obj.GetValue(9) : "")      
      s &= ",Type: " & obj.GetValue(8)
      Free(obj)
   Else
      s = "Plugin error " & ERROR
   Endif
   Return s
EndFunc
[/cut]

Вывод в дополнительном поле выглядит примерно так:

[cut]

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

test 01.m4a	AAC, 44.1 kHz, 2 Ch, 491 Kbps
test 02.flac	FLAC, 44.1 kHz, 2 Ch, 16 Bits, 848 Kbps
test 03.flac	FLAC, 44.1 kHz, 2 Ch, 16 Bits, 768 Kbps
test 05.mp3	MPEG Audio, 44.1 kHz, 2 Ch, 320 Kbps
test 06.mp3	MPEG Audio, 44.1 kHz, 2 Ch, 320 Kbps
test 08.jpg	3840 x 2160 , Landscape , 24
test 09.7z	93%, Folders: 0, Files: 1, Method: LZMA2:18,Type: 7z
test 10.jpg	505 x 550 , Portrait , 24
test 11.jpg	100 x 100 , Quadrate , 24
test 12.JPG	1223 x 465 , Portrait , 24
test 13.JPG	465 x 1223 , Landscape , 24
test 14.7z	27%, Folders: 1, Files: 5, Method: LZMA2:6k,Type: 7z
test 15.7z	26%, Folders: 2, Files: 73, Solid, Method: LZMA2:26 LZMA:20 BCJ2,Type: 7z
test 16.zst	Folders: 0, Files: 1, Method: header-open-only: XXH64 single-segments wnd-MAX:29893,Type: zstd
test 17.zst	Folders: 0, Files: 1, Method: header-open-only: XXH64 single-segments wnd-MAX:29663,Type: zstd
test 18.mkv	1920x804 (2.39:1), 23.976 fps, HEVC, 6,96 MBps
test 18.mp4	1920x1080 (16:9), 23.976 fps, AVC, 3,96 MBps
test 19.mp4	1920x1080 (16:9), 30.000 fps, AVC, 2,65 MBps
test 19.png	676 x 757 , Portrait , 24
test 20.png	960 x 687 , Landscape , 24
test 21.png	1223 x 465 , Landscape , 24
test 22.zip	48%, Folders: 1, Files: 6,Type: zip
test 23.zip	61%, Folders: 1, Files: 18,Type: zip
test 24.zip	66%, Folders: 1, Files: 21,Type: zip
test 25.zip	41%, Folders: 3, Files: 106,Type: zip
test 26.zip	41%, Folders: 3, Files: 106,Type: zip
test 27.rar	23%, Folders: 1, Files: 15, Solid, Method: v6:16M:m5,Type: Rar5
[/cut]

Ну не знаю... Вам решать. В любом случае, в Autorun сейчас есть такая возможность. Можно, конечно, при желании, все более тонко подстроить под конкретную задачу, это был лишь пример. Но главный конфиг обязательно должен в первой строке объявлять дополнительное поле:

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

Pragma AutorunPluginFields "SuperWdx:::GetSuperWdx" 

Добавлено: Пн янв 13, 2025 23:28
AkulaBig
Orion9 писал(а):Я бы однозачно выбрал второе :)
Дак понятно, что эта переменная для удобства создана.
Orion9 писал(а):В любом случае, в Autorun сейчас есть такая возможность.
Я только что перевод DirMenu закончил. Следующий этап колонки пользователя. Может пригодиться.

Добавлено: Вт янв 14, 2025 23:20
Orion9
AkulaBig писал(а):Я только что перевод DirMenu закончил. Следующий этап колонки пользователя. Может пригодиться.
В смысле? Если Гислер сделает такую переменную? Конечно пригодится!

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

А пока приходится выходить из положения вот такими функциями :)

[cut]

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

# поиск индекса кнопки на панели
# примеры вызова:
#{
   BarsPath = %COMMANDER_PATH% & "\Bars"
   
   idx = FindButtonIdx(BarsPath & "Main.bar", "cmd", "61007")
   idx = FindButtonIdx(BarsPath & "Main.bar", "menu", "Auto_bars")   
   idx = FindButtonIdx(BarsPath & "Main.bar", "button", "WCMICONS.dll,72") 
   
   MsgBox(FindButtonIdx(BarsPath & "Main.bar", "param", '/ef "tcm(60011,1)"'))
#}

Func FindButtonIdx(ButtonBar, ButtonKey, ButtonVal)
   Local txt, pos, len, sub, idx = 0
   If Not FileExist(ButtonBar) Then
      ShowDarkHint("Панель не найдена " & ButtonBar, 0)   
      Return 0   
   EndIf   
   len = StrLen(ButtonKey)
   ProcessExecGetOutput txt %COMSPEC% '/c type "%ButtonBar%"'
   pos = StrPos(txt, "=" & ButtonVal)
   If pos = 0 Then Return 0
   For i = 0 To 3
      sub = StrMid(txt, pos-len-i, len)
      #OutputDebugString("Autorun: " & sub)
      If sub = ButtonKey Then
         idx = StrMid(txt, pos-i, i)
         #OutputDebugString("Autorun: idx = " & idx)
         If IsInt(idx) Then Break
      Endif
   Next
   # перепроверка индекса
   If idx > 0 Then
      IniRead txt %ButtonBar% "Buttonbar" %"%ButtonKey% & %idx%"
      #OutputDebugString("Autorun: Key = " & txt)      
      If StrPos(txt, ButtonVal) > 0 Then Return idx
      #OutputDebugString("Autorun: Idx = " & idx)         
   EndIf
   Return 0
EndFunc 
[/cut]

Добавлено: Ср янв 15, 2025 18:21
Orion9
AkulaBig
Кажется, я понял, в чём была сложность той задачи: склеенные панели имеют один серьёзный недостаток - изменения, сделанные на склеенных панелях, не применяются к панелям-источникам и не синхронизируются с ними, а значит, и смысла в такой склейке практически никакого.

Но всё-равно я пересмотрел и доработал код. Теперь панели можно выбирать из меню, открывать на главной панеле, объединять с главной панелью и закреплять для последующих быстрых вызовов.

В меню действуют модификаторы: Ctrl - выбрать и объединить, Shift - закрепить, Ctrl+Shift - перейти к файлу. Вызов без модификаторов загружает выбранную панель на главную панель инструментов.

У самой кнопки тоже есть модификаторы: Ctrl - объединить панель и открыть, Shift - открыть закрепленную панель, Ctrl+Shift - выбор типа меню, Alt - открыть объединенную панель, Win - пересоздать меню из *.bar файлов.

Под "закреплением" подразумевается выбор панели в качестве текущей для дальнейших операций. Информация о выбранной панеле записывается в секцию [Autorun] файла wincmd.ini, ключ AutoBars (например: AutoBars=Vertical.bar). Если ключа нет, то "Vertical.bar" считается умолчанием. Панели ищутся в папке, указанной в переменной BarsPath (у меня, наверное, как и у большинства, это %COMMANDER_PATH% & "\Bars\").

Выбор типа меню происходит между тремя вариантами: "ShowPopupMenu", "em_bars_panel", "DisplayOpenBar". Меню сохраняется в файле "Auto_bars.bar": ShowPopupMenu открывает этот файл встроенной функцией, "em_bars_panel" вызывает пользовательскую команду, "DisplayOpenBar" то же, что и "em_bars_panel", только с позиционированем (на основе примера от Loopback). Команда в usercmd.ini:

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

[em_bars_panel]
cmd=OPENBARMENU
param=%|COMMANDER_PATH|\Bars\Auto_bars.bar
Еще одна команда, которую нужно добавить в usercmd.ini:

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

[em_open_bar]
cmd=OPENBAR
param=%|COMMANDER_PATH|\Bars\%A0
Используется для загрузки панели на главную панель инструментов. Поскольку загруженная панель может не содержать кнопки возврата, не лишним будет сделать пользовательскую команду, которая будет загружать главную панель инструментов, и посадить ее на хоткей. Например, у меня это:

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

[em_open_main_bar]
cmd=OPENBAR
param=%|COMMANDER_PATH|\Bars\Main.bar
В общем, пока все это только в режиме тестирования, но некоторые удобства уже есть. Да и сам код пригодится для повторного использования в качестве наработок. Путь к Clip.vbs нужно указать в скрипте.

[cut="Clip.vbs"]

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

If WScript.Arguments.Count = 0 Then
   FileName = "Clip.txt"
Else 
   FileName = WScript.Arguments(0) 
End If

Set objHTML = CreateObject("htmlfile")
ClipboardText = objHTML.ParentWindow.ClipboardData.GetData("text")

Set objFSO = CreateObject("Scripting.FileSystemObject")   
Set objFile = objFSO.OpenTextFile(FileName, 2, true)
objFile.WriteLine ClipboardText
objFile.Close
[/cut]
[cut="Functions.aucfg"]

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

# модуль дополнительных функций

Func SaveClipToFile(Filename)
   Local vbsp = %COMMANDER_PATH% & "\Scripts\Vbs\"
   Local vbsf = vbsp & "Clip.vbs"
   If Not FileExist(vbsf) Then
      ShowDarkHint("Скрипт не найден " & vbsf, 0)   
      Return 0
   EndIf      
   ShellExec /SW_HIDE /WAIT:2000 %vbsf% '"%Filename%"' %vbsp%
   Return 1
EndFunc

Func ShowDarkHint(DarkHint, HintSleep = 1000)

   SetHintParam("ShowHint", "Font", 10, "Arial")
   SetHintParam("ShowHint", "BackColor", 0x001C1C1C)
   SetHintParam("ShowHint", "Text", 0xFFFFFF)   
  
   ShowHint(DarkHint)
   
   If HintSleep > 0 Then 
      Sleep(HintSleep)
      WinSetState(23)
   Else
      Sleep(100)   
   Endif   
   SetHintParam("ShowHint", "Reload")
   
EndFunc

Func CreateNewBar(BarPath, BarName, BackButton = true)
   
   Local bar, br2, def
   
   bar = BarPath & BarName & ".bar"
   br2 = BarPath & BarName & ".br2"   
   
   ShellExec /SW_HIDE /WAIT:2000 %COMSPEC% "/c del /f /q ""%bar%"""
   ShellExec /SW_HIDE /WAIT:2000 %COMSPEC% "/c del /f /q ""%br2%"""
   
   If FileExist(bar) Then   
      ShowDarkHint("Ошибка удаления " & bar, 0)
      Return false
   Endif
    
   IniWrite %bar% "Buttonbar" "Buttoncount"  "0"
   If ERROR = 1 Then 
      ShowDarkHint("Ошибка создания " & bar, 0)
      Return false
   EndIf
   
   IniRead def %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"   
   
   If BackButton Then
      IniWrite %bar% "Buttonbar" "Button1" "wcmicons.dll,15"
      IniWrite %bar% "Buttonbar" "Cmd1" %def%
      IniWrite %bar% "Buttonbar" "Menu1" "Вернуться"
   Endif
      
   Return true
EndFunc

Func DisplayOpenBar(UsercmdName)
   Local i, h
   MouseGetPos("x", "y")      
   CommandExec(UsercmdName)
   Sleep(20)   
   # ожидание панели    
   For i = 1 To 150
       h = WinFind(0, "#32768") 
       If h > 0 Then Break   
       Sleep(10)
   Next
   If h = 0 Then   
      ShowHint("Панель не найдена") 
      Return  
   Endif   
   WinSetPos(x, y,"","","", h)
EndFunc

# поиск индекса кнопки на панели
# примеры вызова:
#{
   BarsPath = %COMMANDER_PATH% & "\Bars\"
   
   idx = FindButtonIdx(BarsPath & "Main.bar", "cmd", "61007")
   idx = FindButtonIdx(BarsPath & "Main.bar", "menu", "Auto_bars")   
   idx = FindButtonIdx(BarsPath & "Main.bar", "button", "WCMICONS.dll,72") 
   
   MsgBox(FindButtonIdx(BarsPath & "Main.bar", "param", '/ef "tcm(60011,1)"'))
#}

Func FindButtonIdx(ButtonBar, ButtonKey, ButtonVal)
   Local txt, pos, len, sub, idx = 0
   If Not FileExist(ButtonBar) Then
      ShowDarkHint("Панель не найдена " & ButtonBar, 0)   
      Return 0   
   EndIf   
   len = StrLen(ButtonKey)
   ProcessExecGetOutput txt %COMSPEC% '/c type "%ButtonBar%"'
   pos = StrPos(txt, "=" & ButtonVal)
   If pos = 0 Then Return 0
   For i = 0 To 3
      sub = StrMid(txt, pos-len-i, len)
      #OutputDebugString("Autorun: " & sub)
      If sub = ButtonKey Then
         idx = StrMid(txt, pos-i, i)
         #OutputDebugString("Autorun: idx = " & idx)
         If IsInt(idx) Then Break
      Endif
   Next
   # перепроверка индекса
   If idx > 0 Then
      IniRead txt %ButtonBar% "Buttonbar" %"%ButtonKey% & %idx%"
      #OutputDebugString("Autorun: Key = " & txt)      
      If StrPos(txt, ButtonVal) > 0 Then Return idx
      #OutputDebugString("Autorun: Idx = " & idx)         
   EndIf
   Return 0
EndFunc 
[/cut]
[cut="Buttons.aucfg"]

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

Pragma IncludeOnce

Global BarsPath = %COMMANDER_PATH% & "\Bars\"

RegisterCommand 61007 "TwoBars"
RegisterCommand 61008 "SpliceBarItem"

Func SpliceBarItem(lParam)
   Local b_Ctrl = IsPressed(0x11), b_Shift = IsPressed(0x10)
   Local bar = BarsPath & "Auto_bars.bar", def, b, c = 0, mnu, idx, txt, pos, str
   IniRead b %bar% "Buttonbar" %"'Menu' & lParam"
   bar = BarsPath & b
   If Not FileExist(bar) Then
      ShowHint("Панель не найдена " & bar)   
      Return   
   EndIf   
   If Not b_Ctrl And Not b_Shift Then 
      CommandExec("em_open_bar", b)
      Return
   Endif
   If b_Ctrl And b_Shift Then 
      CommandExec /CD:S %bar%      
      Return
   Endif      
   IniWrite /R %COMMANDER_INI% "Autorun" "AutoBars" %b%
   IniRead c %bar% "Buttonbar" "Buttoncount"
   # обновление подсказки на главной панели
   IniRead def %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"   
   If StrPos(def, "%COMMANDER_PATH%") Then
      def = %COMMANDER_PATH% & StrReplace(def, "%COMMANDER_PATH%")
   Endif
   idx = FindButtonIdx(def, "cmd", "61007")
   If idx > 0 Then
      mnu = "menu" & idx
      IniRead txt %def% "Buttonbar"  %"%mnu%"
      #OutputDebugString("Autorun: txt = " & txt)
      pos = StrPos(txt, "Объединить панели")      
      If pos > 0 Then 
         str = StrMid(txt, pos)
         IniWrite %def% "Buttonbar" %"%mnu%" %"%b% & '|' & %str%"
      EndIf   
   EndIf   
   ShowDarkHint(b & auCRLF & "Панель закреплена." & auCRLF & "Кнопок = " & c, 0)
   If b_Ctrl Then 
      TwoBars(1)
      Return
   Endif   
EndFunc

Func Bars2PickMenu(AutoBars)
   Local menu_type = 2
   If Not FileExist(AutoBars) Then      
      ShowHint("Не найден " & AutoBars)
      Return
   Endif
   IniRead /R menu_type %COMMANDER_INI% "Autorun" "AutoBarsMenu" %"%menu_type%"   
   Switch menu_type
     Case 1
       ShowPopupMenu /D %AutoBars%
     Case 2
       CommandExec("em_bars_panel")            
     Else
      #DisplayOpenBar("em_bars_panel")            
      RunThread("DisplayOpenBar", "em_bars_panel")       
   EndSwitch     
EndFunc

Func TwoBars(lParam)
   
   Local b_Ctrl = IsPressed(0x11), b_Shift = IsPressed(0x10), b_Alt = IsPressed(0x12), b_Win = IsPressed(0x5B)
   
   Local bar = "Vertical.bar", usr, usr1 = "Auto_user.bar", bar1, def, brs, op = 0
   Static m = 0, _
          aMenuType = List("ShowPopupMenu","em_bars_panel","DisplayOpenBar")
   
   usr = BarsPath & usr1
   brs = BarsPath & "Auto_bars.bar"
   
   If b_Ctrl And b_Shift Then
      m += 1
      m = (m > 3 ? 1 : m)
      IniWrite /R %COMMANDER_INI% "Autorun" "AutoBarsMenu" %m%
      ShowHint("Тип меню: " & m & " : "& aMenuType[m-1])
      Return
   EndIf
   
   If lParam = 1 Then b_Ctrl = true
   
   If Not (b_Ctrl Or b_Shift Or b_Alt Or b_Win) Then
      If FileExist(brs) Then
         Bars2PickMenu(brs)
         Return
      Else
         b_Win = true
      EndIf   
   EndIf
   
   If b_Win Then
      Local aBars = List(), txt, pipe, j
      ProcessExecGetOutput pipe %COMSPEC% "/c dir /b *.bar" %BarsPath%
      aBars.Text = pipe
      txt = "[Buttonbar]"
      txt &= auCRLF & "Buttoncount=" & aBars.Count
      
      For j = 0 To aBars.Count - 1
          txt &= auCRLF &    "Cmd" & j+1 & "=cm_SpliceBarItem " & j+1
          #txt &= auCRLF &  "Param" & j+1 & "=" & j+1       
          txt &= auCRLF &   "Menu" & j+1 & "=" & aBars[j]
          txt &= auCRLF & "Button" & j+1 & "=wcmicons.dll,14" 
      Next
      
      Free(aBars)
      ClipPut(txt)
      If SaveClipToFile(brs) Then Bars2PickMenu(brs)   
      Return
   EndIf
   
   If b_Alt Then
      If Not FileExist(usr) Then
         ShowHint("Панель не найдена " & usr)   
      Else
         CommandExec("em_open_bar", usr1)
      EndIf            
      Return
   EndIf   
   
   IniRead /R bar1 %COMMANDER_INI% "Autorun" "AutoBars" %"%bar%"
   bar = BarsPath & bar1
   
   If Not FileExist(bar) Then
      ShowHint("Панель не найдена " & bar)   
      Return   
   EndIf
      
   If b_Shift Then
      CommandExec("em_open_bar", bar1)
      Return   
   EndIf
      
   ShowDarkHint("Объединение c " & bar1, 0)
   
   Local aBar = List(), _
         aItems = List("cmd","param","button","menu","path","iconic"), _
         offset, out, b, i, j, k, old, new, found
         
   IniRead def %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"   
   If StrPos(def, "%COMMANDER_PATH%") Then
      def = %COMMANDER_PATH% & StrReplace(def, "%COMMANDER_PATH%")
   Endif
   If Not FileExist(def) Then
      ShowDarkHint("Главная панель не найдена " & def, 0)   
      Return   
   EndIf   
   IniRead offset %def% "Buttonbar" "Buttoncount" 0      
   
   ProcessExecGetOutput def %COMSPEC% '/c type "%def%"'
   
   ProcessExecGetOutput out %COMSPEC% '/c type "%bar%"'
   IniRead b %bar% "Buttonbar" "Buttoncount" 0     
         
   aBar.Text = out
   For j = 0 To aBar.Count - 1
       found = false
       For i = 1 To b
           For k = 0 To aItems.Count - 1
              old = aItems[k] & i & "="
              new = aItems[k] & i + offset + 1 & "="       
              If StrPos(aBar[j], old) Then
                 aBar[j] = StrReplace(aBar[j], old, new)
                 found = true
                 break
              EndIf
           Next   
           if found then break
       Next
   Next
   #aBar.Remove(0, 2)
   aBar[0] = "button" & offset + 1 & "="
   aBar[1] = "iconic" & offset + 1 & "="      
   out = def & auCRLF & aBar.Text   
   Free(aBar)
   Free(aItems)
   
   ClipPut(out)
   op = SaveClipToFile(usr)
   IniWrite %usr% "Buttonbar" "Buttoncount"  %"%offset%+1+%b%"
   
   If op = 1 Then ShowDarkHint("Панели объединены", 0)
   
   If IsPressed(0x12) Then Return
   If IsPressed(0x10) Then 
      CommandExec /CD:S %usr% 
      Return
   EndIf            
   CommandExec("em_open_bar", usr1)   
EndFunc
[/cut]
[cut="Кнопка"]

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

TOTALCMD#BAR#DATA
61007

totalcmd.exe
Объединить панели| |Ctrl - объединить и открыть|Shift - открыть закрепленную|Ctrl+Shift - выбор типа меню| |Alt - открыть объединенную|Win - пересоздать меню *.bar


-1
[/cut]
[cut="TOTALCMD.INC"]

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

[________Autorun_________]=0
cm_SpliceBarItem=61008;Splice Bar Menu
[/cut]

Добавлено: Ср янв 15, 2025 19:20
AkulaBig
Orion9 писал(а):AkulaBig
склеенные панели имеют один серьёзный недостаток - изменения, сделанные на склеенных панелях, не применяются к панелям-источникам и не синхронизируются с ними, а значит, и смысла в такой склейке практически никакого.
Вот именно такая панель мне и нужна. И в этом ее смысл. Таким образом я не передаю свой мусор в сборку.

Добавлено: Ср янв 15, 2025 23:08
Orion9
AkulaBig, я понял.

Просто я почувствовал то же самое, что, вероятно, чувствовали и вы: не смог до конца понять, что мне нужно, и внятно сформулировать задачу :lol: Причину этого описал выше - склеенная панель несет больше проблем, чем пользы. Малейший рассинхрон - и можно окончательно запутаться в [s]трех соснах[/s] трех панелях: главной, вспомогательной и объединенной. Что самое плохое - склеенную панель уже не так просто разобрать на части, как ее собрать.

Но может быть для вашей задачи это и не нужно? Может быть, вам просто достаточно сделать две одинаковые главные панели и переключаться между ними по кругу: одна - официальная, другая - черновая. На вторую вы и будете докидывать кнопки, которые используются только для вашей работы, а первая будет оставаться в нетронутом виде. И алгоритм от этого будет гораздо проще, а значит и круче ))

Переключение по кругу между тремя панелями:

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

# Alt+F1
SetHotkeyAction /K:A /H:F1 MainBarCycle

Func MainBarCycle()
   Static j = -1, aBarName = List("Main","Help", "Vertical")
   j += 1
   j = (j > aBarName.Count - 1 ? 0 : j)
   bar = "%COMMANDER_PATH%\Bars\" & aBarName[j] & ".bar"         
   IniWrite /R %COMMANDER_INI% "Buttonbar" "Buttonbar" %bar%
   SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
   SendCommand 2901
   SendCommand 2901
   sleep(50)
   SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
   WinRedraw(1)
   ShowHint("Включена: " & aBarName[j] & ".bar")
   Sleep(800)
   WinSetState(23)
EndFunc
Если не нужно запоминать панель в wincmd.ini и посылать cm_VisButtonBar для обновления изменений в окне ТС, то можно просто загружать ее командой OPENBAR, как это сделано постом выше, т.е CommandExec("em_open_bar", aBarName[j] & ".bar")

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

[em_open_bar]
cmd=OPENBAR
param=%|COMMANDER_PATH|\Bars\%A0
Но тогда при выходе, главная панель будет оставаться одной и той же.

Добавлено: Чт янв 16, 2025 05:26
AkulaBig
Orion9 писал(а): Просто я почувствовал то же самое, что, вероятно, чувствовали и вы: не смог до конца понять, что мне нужно
Не поняли меня на форуме TCIMG. Поэтому пришлось самому команду доделывать. А я-то прекрасно знал, что мне нужно.
Orion9 писал(а):склеенная панель несет больше проблем, чем пользы.
Несколько лет уже пользуюсь и очень доволен.
Orion9 писал(а):можно окончательно запутаться в [s]трех соснах[/s] трех панелях: главной, вспомогательной и объединенной.
У меня всего две панели. Главная и пользователя. Если не лень, посмотрите видео про эту панель в папке моей сборки. Там все подробно показано.
Orion9 писал(а):Может быть, вам просто достаточно сделать две одинаковые главные панели
И все это будет храниться в папке ТС и передаваться вместе со сборкой. Вы предлагаете стандартный вариант, по которому все делают дополнительные панели и который меня совершенно не устраивает.
Изображение
Вот посмотрите. Я работаю в ТС. Когда мне надо воспользоваться какой-то программкой, я щелкаю по файлу и запускаю ПП. После перезагрузки ПП исчезла. Никакого мусора я через сборку не передаю.
Главный смысл моей панели, что она должна храниться в отдельном месте.
Orion9 писал(а): можно просто загружать ее командой OPENBAR
Именно так у меня и происходит.
Orion9 писал(а): Но тогда при выходе, главная панель будет оставаться одной и той же.
Именно это мне и нужно.
Собственно меня моя панель полностью устраивает. Отказываться от TCIMG я не собираюсь. У меня очень много на ней завязано.

Добавлено: Чт янв 16, 2025 10:22
Orion9
AkulaBig писал(а):И все это будет храниться в папке ТС и передаваться вместе со сборкой.
С чего вы решили? Просто поменяйте относительный путь на абсолютный, и все.

Мой последний пример остается в силе. Уберите третий элемент массива, замените относительный путь и добавьте em_команду. Можете сделать проверку существования вашего личного файла: если он не существует, ничего не переключать.

А пользователю вся эта склейка панелей (да еще и с выбором в каталоге) вряд ли нужна, уж поверьте.

Добавлено: Чт янв 16, 2025 11:31
AkulaBig
Orion9 писал(а): А пользователю вся эта склейка панелей (да еще и с выбором в каталоге) вряд ли нужна, уж поверьте.
Я вообще-то тоже пользователь и мне нужна именно такая панель и никакая другая. Мне не нужны две панели, между которыми я буду переключаться.

Добавлено: Чт янв 16, 2025 13:01
Orion9
AkulaBig писал(а):Мне не нужны две панели, между которыми я буду переключаться.
А сейчас вы что делаете, не переключаетесь, что ли? :lol:

[cut="P.S."]Мой пример все еще в силе. Пока я не понял, в чем заключается удобство вашего способа. Если вам действительно удобно как пользователю запускать каждый раз файл под курсором, чтобы загрузить его на панель, то дело-то ваше. А я, пожалуй, останусь при своем хоткее, и буду переключать панели по короткому кругу.[/cut]

Добавлено: Чт янв 16, 2025 13:19
AkulaBig
Orion9 писал(а): А сейчас вы что делаете, не переключаетесь, что ли? :lol:
Не переключаюсь. просто к основной панели добавляю ПП. При этом основная панель доступна.