Autorun
Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер
AkulaBig
Я это всё видел и знаю. Для полной поддержки многоязычности надо капитально переделывать интерфейс TC. Не наблюдаю ни энтузиазма со стороны автора, ни массовой поддержки этой идеи со стороны участников форумов. Тем более, что список отнюдь не исчерпывается пользовательскими меню. Как минимум, есть, например, заголовки вкладок. ИМХО, не будет он с этим связываться.
Я это всё видел и знаю. Для полной поддержки многоязычности надо капитально переделывать интерфейс TC. Не наблюдаю ни энтузиазма со стороны автора, ни массовой поддержки этой идеи со стороны участников форумов. Тем более, что список отнюдь не исчерпывается пользовательскими меню. Как минимум, есть, например, заголовки вкладок. ИМХО, не будет он с этим связываться.
Даже самая богатая фантазия
Не представит себе наши безобразия.
Не представит себе наши безобразия.
Не знаю на счет остального интерфейса (я не сильно в этой теме), но что касается секций [user] и [DirMenu], то не вижу здесь больших препятствий. Что мешает, например, создать еще один языковой файл, скажем WCMD_ENG.CFG [WCMD_RUS.CFG, WCMD_CHN.CFG, ...] и хранить в нем все, что было упущено, включая эти секции? И логики никакой менять не надо: если пользователь самостоятельно не создаст этот файл и не укажет в нем своих секций, они по-прежнему будут браться из wincmd.ini. Но как только пользователь создает этот файл, предподчение должно сразу отдаваться именно ему (этому файлу) и все изменения должны сораняться именно туда, а не в wincmd.ini или его редирект.Avada писал(а):ИМХО, не будет он с этим связываться.
AkulaBig
Ну вот, использовал ваш скрипт для переключения внутренних ассоциаций в Autorun
Говорил же: добавьте названия секций в параметры и сделайте небольшую документацию в шапке - получится отличный универсальный скрипт для обмена секциями в ini.
[cut="ChangeAssoc.vbs"][/cut]
[cut="autorun.cfg"][/cut]
[cut][/cut]
Все четко и гладко работает, но, блин... кажется, нашел баг в ТС (если это баг, конечно).
Жалею теперь, что потратил полчаса, пытаясь понять, где я накосячил, а оказывается в TCASwitcher.exe всё то же самое было.
Если при запуске ТС внутренние ассоциации включены, то никаких проблем нет - все работает как часы. Но если при запуске ассоциации выключены, то переключение не работает. Вернее оно работает с багом: значок переключается, а ассоциации нет. Только перезагрузка помогает. Как я понял, причина здесь в команде cm_ReloadFileIcons, которая не перечитывает значки (хотя должна), если при старте ТС секция ассоциаций была пустая. Но если секция была наполнена, то все работает.
Avada, вам вопрос (или, может быть, еще кто-то ответит, кто знает): как ТС определяет, что включены или выключены внутренние ассоциации? И баг ли это с cm_ReloadFileIcons, а то может Гислеру надо сообщить?
Ну вот, использовал ваш скрипт для переключения внутренних ассоциаций в Autorun
[cut="ChangeAssoc.vbs"]
Код: Выделить всё
Dim objArgs
Dim objShell
Dim arrLang
arrLang = Array("[+Associations]", "[-Associations]")
Set objShell = WScript.CreateObject("WScript.Shell")
INI = objShell.ExpandEnvironmentStrings("%COMMANDER_PATH%\Ini\Associations.ini")
Text = CreateObject("Scripting.FileSystemObject").OpenTextFile(INI, 1).ReadAll
for i = 0 to UBound(arrLang)
If InStr(1, Text, arrLang(i), 1) = 0 Then
Text = Replace(Text, "[Associations]", arrLang(i), 1, 1, 1)
exit for
End If
next
Set objArgs = WScript.Arguments
If InStr(1, Text, objArgs(0), 1) Then
Text = Replace(Text, objArgs(0), "[Associations]", 1, 1, 1)
With CreateObject("Scripting.FileSystemObject")
.OpenTextFile(INI, 2).Write Text
.OpenTextFile(INI, 1).Close
End With
End If
With CreateObject("Scripting.FileSystemObject")
.OpenTextFile(INI, 2).Write Text
.OpenTextFile(INI, 1).Close
End With
Set objShell = Nothing
WScript.Quit[cut="autorun.cfg"]
Код: Выделить всё
RegisterCommand 61003 "SwitchAssocState"
# первое выполнение при запуске
AssocState()
Func AssocState()
Local f1, res
IniRead /R f1 %COMMANDER_INI% "Associations" "Filter1" ""
# если в секции что-то есть, значит она включена
If f1 <> "" Then
SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\2.ico"
res = true
Else
SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\6.ico"
res = false
Endif
Return res
EndFunc
Func SwitchAssocState(lParam)
Local script = %COMMANDER_PATH% & "\Scripts\Vbs\ChangeAssoc.vbs", sect
If AssocState() Then
# отключение секции
sect = '[-Associations]'
Else
# включение секции
sect = '[+Associations]'
Endif
ShellExec /SW_HIDE /WAIT:3000 '%windir%\system32\cscript.exe' '"%script%" "%sect%"'
AssocState()
SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
CommandExec cm_ReloadFileIcons
CommandExec cm_ReloadBarIcons
sleep(10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(1)
EndFunc
[cut]
Код: Выделить всё
TOTALCMD#BAR#DATA
61003
%TEST_ICON%
Внутренние ассоциации
1
-1
Все четко и гладко работает, но, блин... кажется, нашел баг в ТС (если это баг, конечно).
Жалею теперь, что потратил полчаса, пытаясь понять, где я накосячил, а оказывается в TCASwitcher.exe всё то же самое было.
Если при запуске ТС внутренние ассоциации включены, то никаких проблем нет - все работает как часы. Но если при запуске ассоциации выключены, то переключение не работает. Вернее оно работает с багом: значок переключается, а ассоциации нет. Только перезагрузка помогает. Как я понял, причина здесь в команде cm_ReloadFileIcons, которая не перечитывает значки (хотя должна), если при старте ТС секция ассоциаций была пустая. Но если секция была наполнена, то все работает.
Avada, вам вопрос (или, может быть, еще кто-то ответит, кто знает): как ТС определяет, что включены или выключены внутренние ассоциации? И баг ли это с cm_ReloadFileIcons, а то может Гислеру надо сообщить?
Orion9
Тотал определяет наличие внутренних ассоциаций по содержимому секции [Associations]. На чём и основана работа TCASwitcher. Но команда cm_ReloadFileIcons о трюке с подменой секций не имеет никакого понятия. Если у вас сторонним образом (потому что другого нет) выключены внутренние ассоциации, т.е. секция с ними снабжена таким заголовком, по которому Тотал не обращается, а секция с правильным именем пустая, то их значки для перечитывании этой команде взять неоткуда. Это не баг, а вполне естественное и предсказуемое поведение.
Тотал определяет наличие внутренних ассоциаций по содержимому секции [Associations]. На чём и основана работа TCASwitcher. Но команда cm_ReloadFileIcons о трюке с подменой секций не имеет никакого понятия. Если у вас сторонним образом (потому что другого нет) выключены внутренние ассоциации, т.е. секция с ними снабжена таким заголовком, по которому Тотал не обращается, а секция с правильным именем пустая, то их значки для перечитывании этой команде взять неоткуда. Это не баг, а вполне естественное и предсказуемое поведение.
Даже самая богатая фантазия
Не представит себе наши безобразия.
Не представит себе наши безобразия.
Дак мне переключение ассоциаций не надо, поэтому я и не делалOrion9 писал(а):AkulaBig
Ну вот, использовал ваш скрипт для переключения внутренних ассоциаций в Autorun
Для переключения ассоциаций есть готовые скрипты, программа. Вроде достаточно инструментов. А мой скрипт все-же для другого. Он заточен чтобы более двух названий переключать. И причем определяет, какой язык используется.
Avada, Спасибо за ответ. В чём-то могу согласиться, но все-таки это больше похоже на недоработку. Возможно, Гислеру об этом не говорили, но команда cm_ReloadFileIcons должна перечитывать секцию прежде, чем перечитывать иконки, тогда она будет работать правильно. Вообще, давно заметил, что Тоталу не хватает команды, которая будет сохранять и перечитывать всю кофигурацию, как это происходит при начальной загрузке, это бы во многом облегчило жизнь. А что касается внутренних ассоциаций, то теперь остается только одно - вызывать окно командой cm_InternalAssociate и "прожимать" ОК, как это и было сделано в старых версиях TCASwitcher. Окно, конечно, мелькает, но зато работает все как надо.
В принципе, я так и сделал, но немного оптимизировал алгоритм: если при запуске ассоциации включены (секция наполнена), то cm_InternalAssociate не посылается, и все работает сверх-гладко, просто глаз радуется. Если же секция была пустой (ассоциации были отключены), то сначала вызывается окно внутренних ассоциаций, нажимается ОК, и только потом обновляется значок на панели. Окно при этом мелькает, но это мелочи.
[cut="autorun.cfg"][/cut]

В принципе, я так и сделал, но немного оптимизировал алгоритм: если при запуске ассоциации включены (секция наполнена), то cm_InternalAssociate не посылается, и все работает сверх-гладко, просто глаз радуется. Если же секция была пустой (ассоциации были отключены), то сначала вызывается окно внутренних ассоциаций, нажимается ОК, и только потом обновляется значок на панели. Окно при этом мелькает, но это мелочи.
[cut="autorun.cfg"]
Код: Выделить всё
Global IniAssocState
# первое выполнение при запуске
IniAssocState = AssocState()
Func AssocState()
Local f1, res
IniRead /R f1 %COMMANDER_INI% "Associations" "Filter1" ""
# если в секции что-то есть, значит она включена
If f1 <> "" Then
SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\2.ico"
res = true
Else
SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\6.ico"
res = false
Endif
Return res
EndFunc
Func SwitchAssocState(lParam)
Local script = %COMMANDER_PATH% & "\Scripts\Vbs\ChangeAssoc.vbs", sect
If AssocState() Then
# отключение секции
sect = '[-Associations]'
Else
# включение секции
sect = '[+Associations]'
Endif
ShellExec /SW_HIDE /WAIT:3000 '%windir%\system32\cscript.exe' '"%script%" "%sect%"'
AssocState()
If IniAssocState Then
AssocUpdateWin(true)
Else
RunThread AssocWinSynс
EndIf
EndFunc
Func AssocWinSynс()
Local h = 0, i
PostMessage(AUTORUN_TCHANDLE, 0x433, 519)
# ожидание появления окна
For i = 1 To 75
h = WinFind(0, "TDlgCustomColors")
If h > 0 Then Break
Sleep(25)
#OutputDebugString(h)
Next
If h > 0 Then
b = WinFind(h, "TButton", 3)
SendMessage(b, 0xF5, 0, 0)
Else
ShowHint("Окно не найдено")
Return
Endif
AssocUpdateWin(false)
EndFunc
Func AssocUpdateWin(lReload)
SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
If lReload Then SendCommand cm_ReloadFileIcons
SendCommand cm_ReloadBarIcons
sleep(10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(1)
EndFunc
Так ведь дело не только в ассоциациях: ваш скрипт к чему угодно можно применить, вы только добавьте ему универсальности, чтобы можно было управлять именем файла и секциями через параметры, а не созданием повторных экземпляров. Вам же самому пригодится, если будете делать [DirMenu] по тому же принципу.AkulaBig писал(а):Дак мне переключение ассоциаций не надо, поэтому я и не делал
Это да. Но на Autorun-то еще не было, да еще и в таком коллабеAkulaBig писал(а):Для переключения ассоциаций есть готовые скрипты, программа. Вроде достаточно инструментов.
Ну вы представляете, сколько параметров придется передавать. ТС поддерживает вроде 18 языков. Плюс внутренний. Плюс название устанавливаемого языка. Получается 20 параметров. А сейчас один параметр и понятный массив внутри с названиями языков. Ну а уж размер скрипта крошечный, можно и 100 копий сделать.Orion9 писал(а):чтобы можно было управлять именем файла и секциями через параметры, а не созданием повторных экземпляров.
Добавлено спустя 1 час 30 минут:
Кстати, немного увеличить универсальность можно за счет изменения обозначения массива языков. Ведь по сути набор языков - это константа, которая будет в любой операции. Но тогда надо будет передавать наименование файла. Тоже не очень приятно, но осуществимо.
AkulaBig
Согласен. Для вашей задачи такое вряд ли подойдет. Но как я писал выше, универсальность вашего скрипта хорошо может проявиться на ограниченном числе параметров, что и нужно большенству пользователей, имхо.
Да и вашей задаче большое число параметров не помеха
Попробуйте, например, кнопку:
Args.vbs
Скрипт Autorun перечисляет все файлы в папке Language (которых по умолчанию 53) и передает их в качестве параметров vbs-скрипту. Скрипт принимает все параметры, перечисляет и возвращает результат в Autorun.
Но все-равно я думаю, вам не стоит таким заморачиваться. А если и нужен универсальный скрипт для смены языковых секций [user] и [DirMnu], то, наверно, лучше другой алгоритм для этого использовать.
Согласен. Для вашей задачи такое вряд ли подойдет. Но как я писал выше, универсальность вашего скрипта хорошо может проявиться на ограниченном числе параметров, что и нужно большенству пользователей, имхо.
Да и вашей задаче большое число параметров не помеха
Попробуйте, например, кнопку:
Код: Выделить всё
RegisterCommand 63001 "TestVbsArgs"
Func TestVbsArgs(lParam)
Local txt, pipe
Local VbsPath = %COMMANDER_PATH% & "\Scripts\Vbs\"
Local LangPath = %COMMANDER_PATH% & "\LANGUAGE\"
ProcessExecGetOutput pipe %COMSPEC% "/c dir /b *.*" %LangPath%
pipe = StrReplace(pipe, auCRLF, " ")
ProcessExecGetOutput txt "cscript.exe" "/nologo Args.vbs %pipe%" %VbsPath%
ShowHint(txt)
EndFunc Код: Выделить всё
Set objArgs = Wscript.Arguments
WScript.Echo objArgs.Count
For i = 0 to objArgs.Count -1
Wscript.Echo "Arg" & i & " = " & objArgs.Item(i)
NextКод: Выделить всё
TOTALCMD#BAR#DATA
63001
%COMMANDER_EXE%
Тест параметров Vbs
1
-1
Но все-равно я думаю, вам не стоит таким заморачиваться. А если и нужен универсальный скрипт для смены языковых секций [user] и [DirMnu], то, наверно, лучше другой алгоритм для этого использовать.
А вы с какой-то целью cscript.exe прописываете? Просто я попробовал, прекрасно без этого работает.Orion9 писал(а):Код: Выделить всё
ProcessExecGetOutput txt "cscript.exe" "/nologo Args.vbs %pipe%" %VbsPath%
Добавлено спустя 1 час 8 минут:
Дак мой скрипт и не сможет обработать все языки. В моем скрипте очень важно, чтобы в файле User.ini были прописаны все секции, которые упоминаются в массиве. И берется первая, где не прописан язык. Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.Orion9 писал(а): Скрипт Autorun перечисляет все файлы в папке Language (которых по умолчанию 53) и передает их в качестве параметров vbs-скрипту. Скрипт принимает все параметры, перечисляет и возвращает результат в Autorun.
Но все-равно я думаю, вам не стоит таким заморачиваться.
Как это работает?AkulaBig писал(а):А вы с какой-то целью cscript.exe прописываете? Просто я попробовал, прекрасно без этого работает.
Может быть, вы путаете с ShellExec? Там такой вызов вполне допустим:
Код: Выделить всё
ShellExec "Args.vbs" %params% %VbsPath%Но тогда скрипт Args.vbs не сможет вернуть в Autorun данные через stdout.
А ведь Тотал, похоже, в окне для смены языка просто считывает *.lng из каталога LANGUAGE и предлагает их пользователю для переключения. Если изменить команду на %COMSPEC% "/c dir /b *.lng" %LangPath%, то скрипт получит все 18 языков в качестве своих параметров (или другое количество из каталога), которые будут соответствовать макросу AUTORUN_TCLANGFILE - другие языки пользователь просто не может выбрать через интерфейс. Может быть, из этого что-то и получилось бы, но мне кажется:AkulaBig писал(а):Дак мой скрипт и не сможет обработать все языки.
Вам, вероятно, нужен другой алгоритм, который будет запоминать с какого языка на какой происходило переключение и менять секции местами.AkulaBig писал(а):Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.
По-моему, тут всё дело в добавлении паузы sleep(10) после cm_ReloadBarIcons (2945) и WinRedraw(1).Orion9 писал(а):Блин, я офигел, как гладко работает!
Переделал подобным же образом обновление панели инструментов при изменении количества строк в ней:
Код: Выделить всё
SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
SendCommand 2901
SendCommand 2901
sleep(10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(1)Ну да, у меня через него сделано.Orion9 писал(а): Может быть, вы путаете с ShellExec?
Мне это и не надо, но вы немного по другому хотите сделать.Orion9 писал(а): Но тогда скрипт Args.vbs не сможет вернуть в Autorun данные через stdout.
И как вы потом определите:Orion9 писал(а): скрипт получит все 18 языков в качестве своих параметров
У меня это решается просто. Все необходимые секции должны быть прописаны. И с помощью массива я узнаю, какой язык используется в настоящее время. Поэтому я не могу читать весь список языков. Тогда только нейросеть может определить текущий языкAkulaBig писал(а):Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.
Пытаюсь сейчас сделать скрипт несколько универсальнее. Когда у меня было прописано конкретно название секции InStr нормально отрабатывал.А сейчас склеенные данные не понимает. Сравнивает не по полному соответствию. Похоже вместо [User_lng] надо писать [lng_User]. Так как [User] считается подстрокой.
Похоже, да. Иначе команда разрешения перерисовки окна выполняется раньше, чем панель перерисовывается. Но, видимо, это сейчас и самое слабое место, т.к. на разных машинах, особенно слабых, эта цифра наверняка будет разной, и sleep(10) может попросту не хватить. Но работает не хуже чем в TCFS2, хотя в справке написано, что функция WinRedraw находится в тестовой стадии и перерисовка методом RedrawWindow отключена по умолчанию, хотя только именно этот метод почему-то и работает.sa писал(а):По-моему, тут всё дело в добавлении паузы sleep(10) после cm_ReloadBarIcons (2945) и WinRedraw(1).
Не берите в голову, это просто были творческие изыскания: интересно же посмотреть на что способен Autorun и как он гоняет параметры туда-сюда через stdoutAkulaBig писал(а):И как вы потом определите:
Вот, вроде и получился универсальный скрипт. Даже комменты написал 
[cut="ChangeLang.vbs"]
[/cut]
[cut="ChangeLang.vbs"]
Код: Выделить всё
' Смена текущей секции ini-файлов в зависимости от выбранного языка
Dim objShell
Dim arrLang
Dim ini, sect, lng
' Поддерживаемые языки. В ini-файле должны быть секции, название которых
' создано по шаблону [sect_lng]. Количество секций должно соответствовать
' количеству поддерживаемых языков
arrLang = Array("eng", "rus")
Set objShell = WScript.CreateObject("WScript.Shell")
' Имя ini-файла, в котором необходимо менять названия секций, в зависимости
' от выбранного языка
ini = objShell.ExpandEnvironmentStrings(WScript.Arguments(0))
' Название оригинальной секции, которая используется программой
sect = WScript.Arguments(1)
' Язык, который будет использоваться текущим. Оригинальная секция будет без
' дополнения названия языка и соответствовать шаблону [sect_lng]. Все остальные
' секции будут соответствовать шаблону [sect_lng]
lng = WScript.Arguments(2)
Text = CreateObject("Scripting.FileSystemObject").OpenTextFile(ini, 1).ReadAll
' Переименовываем все секции по шаблону [sect_lng]
for i = 0 to UBound(arrLang)
If InStr(1, Text, "[" & sect & "_" & arrLang(i) & "]", 1) = 0 Then
Text = Replace(Text, "[" & sect & "]", "[" & sect & "_" & arrLang(i) & "]", 1, 1, 1)
exit for
End If
next
' Переименовываем оригинальную секции по шаблону [sect]
If InStr(1, Text, "[" & sect & "_" & lng & "]", 1) Then
Text = Replace(Text, "[" & sect & "_" & lng & "]", "[" & sect & "]", 1, 1, 1)
End If
With CreateObject("Scripting.FileSystemObject")
.OpenTextFile(ini, 2).Write Text
.OpenTextFile(ini, 1).Close
End With
Set objShell = Nothing
WScript.Quit