Тема: AHK: ButtonBar eXtended помощь Total Commander-сообществу
Есть очень востребованная среди сборщиков Total Commander утилита:
ButtonBar eXtended
Утилита написана уже в далёком 2011 и имеет пару проблем с UAC:
1) Утилита не передаёт повышение прав программе которую запускает. То есть если ButtonBar eXtended запустить от Администратора, то программа которую запустит утилита не получает команду также запуститься от Администратора.
2) Утилита ищет Usercmd.ini в корневой папке Total Commander, но будучи запущенной с повышением прав, она его там не находит.
Обе эти проблемы решаются если запускать TC от имени администратора.
Просьба подправить исходный код утилиты:
; "ButtonBar eXtended" for Total Commander
; Version: 2.3
; Freeware by Samuel Plentz - www.SamuelPlentz.de.vu
; ### --------------------------------------------------------------------------
; ### get current keystates of Ctrl, Alt & Shift and read parameters
#NoTrayIcon
#SingleInstance off
SetBatchLines -1
AutoTrim,Off
Getkeystate,Keystate_Ctrl ,Ctrl
Getkeystate,Keystate_Alt ,Alt
Getkeystate,Keystate_Shift,Shift
Quote="
Parameter_1=%1%
Parameter_2E=%2%
Parameter_3E=%3%
StringLower,Parameter_1L,1
transform,Parameter_2,deref,%Parameter_2E%
transform,Parameter_3,deref,%Parameter_3E%
; ##############################################################################
; ### convert "ButtonBar" to "ButtonBar eXtended"
if(Parameter_1L=="-c" || Parameter_1L=="-d"){
; # check if Parameter_2 is valid and get NewFilename --------------------------
IniRead,ButtonCount,%Parameter_2%,Buttonbar,Buttoncount,0
if(!RegExMatch(Parameter_2,"i)\.bar$") || !FileExist(Parameter_2) || ButtonCount==0){
msgbox,16,Error: Wrong Parameters,A valid "ButtonBar" is needed to convert it to a "ButtonBar eXtended".`nParameter 1: "%Parameter_1%"`nParameter 2: "%Parameter_2E%"
return
}
SplitPath,Parameter_2,Parameter_2Name,tFilePath,,UserCmdSection
NewFilename=BBX_%Parameter_2Name%
if(tFilePath!=""){
NewFilename=%tFilePath%\%NewFilename%
}
NewFilenameCache=NewFilename
StringTrimRight,NewFilenameCache,NewFilenameCache,3
NewFilenameCache=%NewFilenameCache%br2
FileDelete,%NewFilename%
FileDelete,%NewFilenameCache%
; # delete all old user commands for this "ButtonBar eXtended" -----------------
StringReplace,UserCmdSection,UserCmdSection,%A_Space%,_,1
StringReplace,UserCmdSection,UserCmdSection,-,_,1
StringReplace,UserCmdSection,UserCmdSection,=,_,1
UserCmdSection=em_BBX_%UserCmdSection%>
UserCmdFile := LocationUserCmdFile()
WinCmdFile := LocationWinCmdFile()
FileRead,UserCmdContent,%UserCmdFile%
Loop,parse,UserCmdContent,`n,`r
{
if(1==InStr(A_LoopField,"[" . UserCmdSection) || (1==InStr(A_LoopField,"[em_BBX_") && 0==InStr(A_LoopField,">"))){
StringTrimLeft,currentSection,A_LoopField,1
StringTrimRight,currentSection,currentSection,1
IniDelete,%UserCmdFile%,%currentSection%
}
}
; # read all commands from the "ButtonBar" -------------------------------------
A_ScriptFullPathE=%A_ScriptFullPath%
A_ScriptDirE=%A_ScriptDir%
Loop,%ButtonCount%
{
ReadCommand(Parameter_2,A_Index)
Command := cmd%A_Index%
SplitPath,Command,tFilename
StringReplace,tFilename,tFilename,",,All
; change convert button to edit button
if(tFilename==A_ScriptName && InStr(param%A_Index%,Parameter_2Name) && (InStr(param%A_Index%,"-d") || InStr(param%A_Index%,"-c"))){
A_ScriptFullPathE := cmd%A_Index%
SplitPath,A_ScriptFullPathE,,A_ScriptDirE
A_ScriptDirE=%A_ScriptDirE%\
cmd%A_Index% := Parameter_2E
param%A_Index% := ""
path%A_Index% := ""
menu%A_Index% := "Edit this " . Quote . "ButtonBar eXtended" . Quote
}
}
; # convert all commands from the "ButtonBar" ----------------------------------
OutputButtonbarCount=0
OutputUserCmdCount=0
Mode=0
Loop,%ButtonCount%
{
nextIndex := A_Index+1
if(RegExMatch(menu%nextIndex%,"i)(^[2-5]?(c|a|s|ca|cs|as|cas)$|^[2-5]$|^m$)")){
; start of an "eXtended command"
if(Mode==0){
Mode=1
OutputButtonbarCount++
OutputUserCmdCount++
OutputUserCmdState=
OutputUserCmdStateCount=1
WriteNewCommand(NewFilename,"Buttonbar",OutputButtonbarCount,A_ScriptFullPathE,A_ScriptDirE,UserCmdSection . OutputUserCmdCount,button%A_Index%,0,menu%A_Index%)
menu%A_Index% := ""
WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "_" . OutputUserCmdState . "_" . OutputUserCmdStateCount,"")
continue
}
}else{
Mode=0
}
; "eXtended command" continues
if(RegExMatch(menu%A_Index%,"i)(^[2-5]?(c|a|s|ca|cs|as|cas)$|^[2-5]$|^m$)")){
if(RegExMatch(menu%A_Index%,"i)^m$")){
OutputUserCmdStateCount++
menu%A_Index% := ""
}else{
StringLower,OutputUserCmdState,menu%A_Index%
if menu%A_Index% is not lower
menu%A_Index% := "w"
else
menu%A_Index% := ""
OutputUserCmdStateCount=1
}
WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "_" . OutputUserCmdState . "_" . OutputUserCmdStateCount,"")
continue
}
; ahk command
if(1==InStr(cmd%A_Index%,"ahk_")){
OutputButtonbarCount++
OutputUserCmdCount++
WriteNewCommand(NewFilename,"Buttonbar",OutputButtonbarCount,A_ScriptFullPathE,A_ScriptDirE,UserCmdSection . OutputUserCmdCount,button%A_Index%,0,menu%A_Index%)
menu%A_Index% := ""
WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "__1","")
continue
}
; simple command
OutputButtonbarCount++
WriteCommand(NewFilename,A_Index,"Buttonbar",OutputButtonbarCount)
}
IniWrite,%OutputButtonbarCount%,%NewFilename%,Buttonbar,Buttoncount
; make the "ButtonBar eXtended" the default if "-d" was used
if(Parameter_1L=="-d" && FileExist(WinCmdFile)){
IniWrite,%NewFilename%,%WinCmdFile%,Buttonbar,Buttonbar
}
OutputUserCmdCount++
if(Parameter_3!=""){
WriteNewCommand(UserCmdFile,UserCmdSection . OutputUserCmdCount,"","OPENBAR","",Parameter_3,"",0,"")
}else{
WriteNewCommand(UserCmdFile,UserCmdSection . OutputUserCmdCount,"","OPENBAR","",NewFilename,"",0,"")
}
Command=%UserCmdSection%%OutputUserCmdCount%
EM_Command(Command)
ExitApp
}
; ##############################################################################
; ### execute a command in the "ButtonBar eXtended"
if(Parameter_1!=""){
UserCmdFile := LocationUserCmdFile()
MouseState := GetMouseButton()
Mode_CAS=%MouseState%
if(Keystate_Ctrl=="D"){
Mode_CAS=%Mode_CAS%c
}
if(Keystate_Alt=="D"){
Mode_CAS=%Mode_CAS%a
}
if(Keystate_Shift=="D"){
Mode_CAS=%Mode_CAS%s
}
; use default command if current keyboard modifiers are not available
if(Mode_CAS!=""){
IniRead,value,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_1,cmd,%A_Space%
; when there is no action defined for middlemousebutton it reacts like Ctrl
if(value==""){
if(Mode_CAS=="3"){
Mode_CAS=c
}else{
Mode_CAS=%MouseState%
}
}else{
; wait for modifier releases if necessary
IniRead,value,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_1,menu,%A_Space%
if(value=="w"){
Loop{
Getkeystate,Keystate_Ctrl ,Ctrl
Getkeystate,Keystate_Alt ,Alt
Getkeystate,Keystate_Shift,Shift
if(Keystate_Ctrl!="D" && Keystate_Alt!="D" && Keystate_Shift!="D"){
break
}
}
}
}
}
; execute all according commands
Loop
{
IniRead,Command,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_%A_Index%,cmd,%A_Space%
if(Command==""){
break
}
; run custom ahk commands
StringLower,Command,Command
if(1==InStr(Command,"ahk_")){
IniRead,Parameter_ahk,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_%A_Index%,param,%A_Space%
if(Command=="ahk_sleep"){
Sleep,%Parameter_ahk%
continue
}
if(Command=="ahk_sendinput"){
SendInput,%Parameter_ahk%
continue
}
continue
}
; run normal em_commands
Command=%Parameter_1%_%Mode_CAS%_%A_Index%
EM_Command(Command)
}
ExitApp
}
ExitApp
; ##############################################################################
; ##############################################################################
; ##############################################################################
; ### --------------------------------------------------------------------------
; ### get location of "usercmd.ini" (use CustomUsercmd if set in ini)
LocationUserCmdFile()
{
IniRead,tFileName,ButtonBar eXtended.ini,ButtonBar eXtended,CustomUsercmd,-
if(tFileName!="-"){
transform,tFileName,deref,%tFileName%
return tFileName
}
EnvGet,LocationWinCmdFile,COMMANDER_INI
SplitPath,LocationWinCmdFile,,tFilePath
tFilename=usercmd.ini
if(tFilePath!=""){
tFilename=%tFilePath%\%tFilename%
}
return tFilename
}
LocationWinCmdFile()
{
EnvGet,LocationWinCmdFile,COMMANDER_INI
return LocationWinCmdFile
}
; ### --------------------------------------------------------------------------
; ### read command into an array
ReadCommand(Filename,ArrayNr)
{
global
IniRead,cmd%ArrayNr% ,%Filename%,Buttonbar,cmd%ArrayNr% ,%A_Space%
cmd%ArrayNr% := RegExReplace(cmd%ArrayNr% ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
IniRead,path%ArrayNr% ,%Filename%,Buttonbar,path%ArrayNr% ,%A_Space%
path%ArrayNr% := RegExReplace(path%ArrayNr% ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
IniRead,param%ArrayNr% ,%Filename%,Buttonbar,param%ArrayNr% ,%A_Space%
param%ArrayNr% := RegExReplace(param%ArrayNr% ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
IniRead,button%ArrayNr%,%Filename%,Buttonbar,button%ArrayNr%,%A_Space%
button%ArrayNr% := RegExReplace(button%ArrayNr%,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
IniRead,iconic%ArrayNr%,%Filename%,Buttonbar,iconic%ArrayNr%,%A_Space%
iconic%ArrayNr% := RegExReplace(iconic%ArrayNr%,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
IniRead,menu%ArrayNr% ,%Filename%,Buttonbar,menu%ArrayNr% ,%A_Space%
menu%ArrayNr% := RegExReplace(menu%ArrayNr% ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
}
; ### --------------------------------------------------------------------------
; ### write command in a file
WriteCommand(Filename,ArrayNr,FileSection,FileNr)
{
global
value := cmd%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,cmd%FileNr%
value := path%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,path%FileNr%
value := param%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,param%FileNr%
value := button%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,button%FileNr%
value := iconic%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,iconic%FileNr%
value := menu%ArrayNr%
IniWrite,%value%,%Filename%,%FileSection%,menu%FileNr%
}
; ### --------------------------------------------------------------------------
; ### create new command in a file
WriteNewCommand(Filename,FileSection,FileNr,v1,v2,v3,v4,v5,v6)
{
global
cmd0=%v1%
path0=%v2%
param0=%v3%
button0=%v4%
iconic0=%v5%
menu0=%v6%
WriteCommand(Filename,0,FileSection,FileNr)
}
; ### --------------------------------------------------------------------------
; ### execute em_commands
EM_Command(ByRef emCommand)
{
Critical
VarSetCapacity(CopyDataStruct, A_PtrSize * 3)
VarSetCapacity(emCommandAnsi, StrPut(emCommand, "cp0"))
Loop, % StrLen(emCommand)
{
NumPut(Asc(SubStr(emCommand, A_Index, 1)), emCommandAnsi, A_Index - 1, "Char")
}
NumPut(Asc("E") + 256 * Asc("M"), CopyDataStruct)
NumPut(StrLen(emCommand) + 1, CopyDataStruct, A_PtrSize)
NumPut(&emCommandAnsi, CopyDataStruct, A_PtrSize * 2)
SendMessage, 0x4A,, &CopyDataStruct,, ahk_class TTOTAL_CMD
}
; ### --------------------------------------------------------------------------
; ### works together with MouseTool to detect which mouse button was pressed
GetMouseButton()
{
MouseButton=
Loop,5
{
if(A_Index!=1){
Mutex := DllCall("CreateMutex","uint","0","int","1","str","BBX_" . A_Index)
LastError := DllCall("GetLastError")
DllCall("CloseHandle","uint",Mutex)
if(LastError!=0){
MouseButton=%A_Index%
break
}
}
}
return MouseButton
}