| View previous topic :: View next topic |
| Author |
Message |
sa
Joined: 29 Apr 2009 Posts: 2745
|
(Separately) Posted: Fri Jul 10, 2026 15:03 Post subject: |
|
|
| Orion9 wrote: | | сделал сохранение |
По-моему, файл не перезаписывается (не меняет дату и время модификации), если имя остаётся прежним. Это немного настораживает… |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1193
|
(Separately) Posted: Sat Jul 11, 2026 00:39 Post subject: |
|
|
| sa wrote: | | Это немного настораживает… |
Согласен. Сделал сообщение, что нельзя в тот же файл сохранить.
С удалением, конечно, надо подумать, но это дело второе. Меня больше интересовал перенос значка, и вроде получилось. Кода совсем немного, но приложу весь модуль, поскольку было много мелких правок, включая WinRedraw(0), который помогает лучше перерисовывать, чем скрытие панели.
Перенос значка - копирование + сброс с удержанием перемещения
 beta | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
# правый клик с удержанием Ctrl
ControlSetMouseAction /R /K:C 28 "HBarShowMenu"
Global gDragIndex, gDropIndex, gSmartIndex
Global gHBarButtons = 0, gHBarDivs = 0, gHBarSmart = 1
Global gHBarName, gHBarFile, gHBarFileTs
Global gHBarTxt, gHBarCP = "ANSI", gHBarWincmd = 0, gHBarDbg = 0
Global gHBarHint = 0, gHBarVerb, gHBarCancel, gHBarCancelLoad, gHBarLoadError = 0
Global gHBarList = List(), gHBarMap = List(), gHBarUndo, gHBarUndoTs, gHBarUndoLoad
Global gHBarWndProc, hBarWnd = 0
Global gHBarWP = Callback("HBarWndProc", "hwnd;uint;wparam;lparam")
Func HBarWndProc(hWnd, uMsg, wParam, lParam)
Static IsDrag = 0, _
hTotal = DllCall("GetModuleHandleW", "Ptr", 0, "handle"), _
MK_SHIFT = 0x0004, _
MK_CONTROL = 0x0008, _
MK_LBUTTON = 0x0001, _
WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
MoveButton = MK_CONTROL, _
CopyButton = MK_SHIFT
Static drag_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32646), _
stop_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32648), _
icon_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 13), _
kick_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 26), _
copy_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 25), _
drag_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 22), _
stop_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 21)
Static SM_CXDRAG = 68, SM_CYDRAG = 69, _
dragX = GetSystemMetrics(SM_CXDRAG), dragY = GetSystemMetrics(SM_CYDRAG), _
startX, startY
Local x, y, pos
If gHBarLoadError Then
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndIf
Switch uMsg
Case WM_LBUTTONDOWN
If IsDrag = 0 And (BitAND(wParam, MoveButton) Or BitAND(wParam, CopyButton)) Then
Static buf = Buffer(8) # POINT
buf.Zero()
x = BitAND(lParam, 0xFFFF)
y = BitAND(BitShift(lParam,16), 0xFFFF)
startX = x
startY = y
buf.SetNum(0, "int", x, "int", y)
DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
pos = buf.GetNum(0, "int64")
#x = buf.GetNum(0)
#y = buf.GetNum(4)
#If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
If DllCall("DragDetect", "hwnd", hWnd, "int64", pos) Then
If FileGetTime(gHBarFile) <> gHBarFileTs Then
ShowDragHint("Операция невозможна. Файл панели изменился.")
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
Endif
If BitAND(wParam, MoveButton) And BitAND(wParam, CopyButton) Then
IsDrag = MoveButton
Else
IsDrag = wParam
EndIf
WinSetStyle(0x80000, 3, hWnd)
If BitAND(wParam, MoveButton) Then
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
Else
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 216, "dword", 2)
EndIf
x = buf.GetNum(0)
y = buf.GetNum(4)
gDragIndex = HBarGetIdx(1, x, y)
Else
IsDrag = 0
DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", WM_LBUTTONUP, "wparam", wParam, "lparam", lParam)
Return 0
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag > 1 Then
Local nDragMode = IsDrag
DllCall("ReleaseCapture")
IsDrag = 0
If WinFromPoint() = hWnd Then
MouseGetPos("x","y")
gSmartIndex = 0
gDropIndex = HBarGetIdx(2, x, y)
If gDragIndex <> gDropIndex Then
If gHBarHint Then ShowDragHint("Index " & gDragIndex & " To Index: " & gDropIndex)
If BitAND(nDragMode, MoveButton) Then
HBarDragnDrop(gDragIndex, gDropIndex)
Else
If BitAND(wParam, MoveButton) Then
HBarDragIcon(gDragIndex, gDropIndex)
Else
HBarDragnCopy(gDragIndex, gDropIndex)
EndIf
EndIf
EndIf
EndIf
WinSetStyle(0x80000, 5, hWnd)
#Return 0
#lParam = MakeInt(y, x + 200, 2)
lParam = -1000
EndIf
Case WM_MOUSEMOVE
If IsDrag > 1 And BitAND(wParam, MK_LBUTTON) Then
If WinFromPoint() = hWnd Then
If BitAND(IsDrag, CopyButton) Then
DllCall("SetCursor", "Ptr", BitAND(wParam, MoveButton) ? icon_cursor : copy_cursor)
Else
DllCall("SetCursor", "Ptr", drag_cursor)
EndIf
#DllCall("SetCursor", "Ptr", BitAND(IsDrag, MoveButton) ? drag_cursor : copy_cursor)
Else
y = BitAND(BitShift(lParam,16), 0xFFFF)
#WinSetText(lParam & " y=" & y)
If BitAND(wParam, MoveButton) And lParam > 0 And y > 200 Then
DllCall("SetCursor", "Ptr", kick_cursor)
Else
DllCall("SetCursor", "Ptr", stop_cursor)
EndIf
EndIf
EndIf
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func HBarShowHint()
# панель в режиме drag'n'drop
If WinHasStyle(0x80000, 1, hBarWnd) Then Return
# состояние CapsLock и Shift
If BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1) = 0 Then
If Not IsPressed(0x10) Then Return
EndIf
# дескриптор горизонтальной панели
Local hWnd = RequestInfo(28)
If hWnd = 0 Then
Return "Окно панели не найдено " & hWnd
EndIf
# глобальные переменные дескриптора и оконной процедуры
If hBarWnd <> hWnd Then
hBarWnd = hWnd
gHBarWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", hBarWnd, "int", -4, "long_ptr", gHBarWP.Ptr, "ptr")
EndIf
# поиск файла панели
If gHBarName <> WinGetText(hBarWnd) Then
gHBarUndo = false
gHBarUndoLoad = ""
gHBarCancel = false
gHBarCancelLoad = ""
gHBarFile = HBarGetFile()
If Not FileExist(gHBarFile) Then
gHBarName = ""
Return "Файл панели не найден " & gHBarFile
EndIf
# метка времени
gHBarFileTs = FileGetTime(gHBarFile)
# загрузка панели
HBarLoad()
If gHBarLoadError Then Return HBarGetHint()
ElseIf FileGetTime(gHBarFile) <> gHBarFileTs Then
gHBarUndo = false
gHBarUndoLoad = ""
If Not FileExist(gHBarFile) Then
gHBarName = ""
Return "Файл панели не найден " & gHBarFile
EndIf
gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
If gHBarLoadError Then Return HBarGetHint()
EndIf
# индекс кнопки под курсором
gDragIndex = HBarGetIdx()
If Not gDragIndex And Not gHBarDbg Then Return "Не удалось определить индекс кнопки"
Return HBarGetHint()
EndFunc
Func HBarGetFile()
Local bar, txt
# информация о файле панели в wincmd.ini
IniRead /R bar %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"
# раскрытие переменной окружения
bar = Set(bar)
# в конфигурации указано только имя файла
If FileGetDir(bar) = "" Then bar = COMMANDER_PATH & "\" & bar
gHBarWincmd = bar
# чтение текста окна панели
txt = WinGetText(hBarWnd)
gHBarName = txt
# на панель загружен временный .bar файл
If Not StrPos(bar, txt) Then
bar = COMMANDER_PATH & "\Bars\" & txt
EndIf
If Not FileExist(bar) Then
bar = GetCurrentPath() & "\" & txt
EndIf
# проверка существования файла панели
If Not FileExist(bar) Then
bar = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
gHBarLoadError = 0
Local bar = FileRead(gHBarFile, 128, "RAW")
Local bom = "FFFE"
Local utf = "5B0042007500740074006F006E006200610072005D000D000A00"
If ERROR = 1 Then
gHBarLoadError = 1
gHBarCP = "Unknown"
Return
EndIf
If StrLeft(bar, 4) = "FFFE" Then
gHBarCP = "UTF-16 BOM"
Else
IF StrPos(bar, utf) Then
gHBarCP = "UTF-16 без BOM"
Else
gHBarCP = "ANSI"
EndIf
EndIf
# загрузка файла в массив
gHBarList.Count = 0
gHBarList.LoadFromFile(gHBarFile, gHBarCP)
# количество кнопок в файле
Local nCount = 0
IniRead /R nCount %gHBarFile% "Buttonbar" "Buttoncount" 0
# обнуление счетчиков
gHBarDivs = 0
gHBarButtons = 0
# локальные переменные
Local j, key, val, found, oButton = Map(), oCmd = Map()
# поиск кнопок и команд
For j = 0 To gHBarList.Count - 1
found = 0
If StrLeft(gHBarList[j], 6) = "button" Then
found = 1
ElseIf StrLeft(gHBarList[j], 3) = "cmd" Then
found = 2
EndIf
If found > 0 Then
key = StrLower(StrPart(gHBarList[j], "=", 1))
val = StrLen(StrPart(gHBarList[j], "=", 2))
If found = 1 Then
oButton.Set(key, val)
Else
oCmd.Set(key, val)
EndIf
EndIf
Next
gHBarMap.Count = 0
# подсчет кнопок и разделителей
For j = 1 To nCount
key = "button" & j
val = oButton.Get(key, 0)
If val > 0 Then
# количество кнопок
gHBarButtons += 1
gHBarMap.Add(1)
Else
# количество разделителей
gHBarDivs += 1
If oCmd.Get("cmd" & j, 0) = 2 Then
gHBarMap.Add(-2)
Else
gHBarMap.Add(0)
EndIf
EndIf
Next
Free(oButton, oCmd)
If gHBarButtons = 0 Then gHBarLoadError = 1
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded" & ": " & gHBarFile & " > " & gHBarCP & " "
If gHBarLoadError Then gHBarTxt &= " -- ERROR LOADING"
gHBarTxt &= auCRLF
For j = 0 To gHBarMap.Count - 1
gHBarTxt &= gHBarMap[j] & " "
If j > 0 and Mod(j, 50) = 0 Then gHBarTxt &= auCRLF
Next
gHBarTxt &= auCRLF & "Wincmd.ini: " & gHBarWincmd
EndFunc
Func HBarGetIdx(MousePos = false, PosX = 0, PosY = 0)
# дескриптор монитора окна ТС
Local hMon = DllCall("MonitorFromWindow", "hwnd", AUTORUN_TCHANDLE, "dword", 2)
# буфер для структуры MONITORINFOEX
Local buf = Buffer(104)
buf.Zero()
buf.SetNum(0, "dword", 104)
DllCall("GetMonitorInfoW", "ptr", hMon, "ptr", buf.ptr)
# имя монитора
Local sMon = buf.GetStr(40)
# информация о масштабировании экрана
Local DC = DllCall("GetDC", "int", 0)
Local nDPI = DllCall("GetDeviceCaps", "handle", DC, "int", 88) # LOGPIXELSX
Local nScale = DllCall("MulDiv", "int", 100, "int", nDPI, "int", 96)
DllCall("ReleaseDC", "int", 0, "handle", DC)
# локальные переменные
Local x, y, w, h, mx, my, idx, row, rows, rowh, dpi, b, extra
# координаты и размеры окна панели
WinGetPos("x", "y", "w", "h", hBarWnd)
# координаты указателя мыши
If MousePos Then
mx = PosX
my = PosY
Else
MouseGetPos("mx", "my")
EndIf
# чтение информации о высоте кнопок
IniRead /R b %COMMANDER_INI% "Buttonbar" "Buttonheight"
IniRead /R dpi %COMMANDER_INI% "Buttonbar" "DefaultDpi" %'nDPI'
Local b_ini = b, b_calc
# масштабирование экрана
If dpi <> nDPI Then
IniRead /R d %COMMANDER_INI% "Buttonbar" %'"Buttonheight" & nDPI' 0
If d <> 0 Then
b = d
Else
b = Round(b / (dpi / nDPI), 0)
b_calc = "*"
EndIf
EndIf
# количество рядов кнопок на панели
rows = Floor(h/b)
If rows = 0 Then Return ShowDragHint("Error number of rows can't be zero")
# количество дополнительных пикселей
extra = Mod(h,b)
# ширина разделителя
Local div = Floor(b/3)
# высота одного ряда
rowh = b + 3
# номер ряда под указателем
row = Ceil((my - y)/rowh)
# абстрактные координаты по оси х
Local tx = (mx - x + 1) + ((row - 1) * w), cx = 0, ex = 0, idx_padding = 0
# индекс кнопки в ряду
If gHBarDivs = 0 Then
idx = (Floor((mx - x)/b) + 1) + (row-1)*(Floor(w/b))
If idx > gHBarButtons Then idx = gHBarButtons
Else
j = 1
idx = 0
For i = 0 To gHBarMap.Count - 1
idx_padding = 0
If gHBarMap[i] = -2 Then
If i = 0 Then cx += w # первая кнопка разрыв
j += 1
cx += ex
If i > 0 And gHBarMap[i-1] = -2 Then
cx += w - ex
EndIf
If i = gHBarMap.Count - 1 Then cx += w # последняя кнопка разрыв
If cx >= tx Then
idx = i + 1
Break
EndIf
Continue
EndIf
cx += (gHBarMap[i] = 0 ? div : b)
ex = j*w - cx
If i + 1 <= gHBarMap.Count - 1 Then
next_button = gHBarMap[i+1]
next_width = (next_button = -2 ? 0 : (next_button = 0 ? div : b))
If ex < next_width Then
cx += ex
idx_padding += ex
j += 1
EndIf
Else
cx += ex
idx_padding = ex
EndIf
If cx >= tx Then
idx = i + 1
Break
EndIf
Next
EndIf
idx_button = gHBarMap[idx-1]
idx_width = (idx_button = -2 ? 0 : (idx_button = 0 ? div : b))
idx_pixel = tx - (cx - idx_padding - idx_width)
idx_float = idx_width > 0 ? idx_pixel / idx_width : 0
# дробный индекс
gSmartIndex = idx + Round(idx_float, 3)
If Floor(gSmartIndex) > idx Then gSmartIndex = idx + 0.999
# дополнительная информация
gHBarVerb = "mouse=" & mx & ", " & my & auCRLF & _
"bar=" & x & ", " & y & ", " & w & ", " & h & auCRLF & _
"map=" & tx & ", " & cx & auCRLF & _
"row=" & row & " of " & rows & auCRLF & _
"height=" & rowh & " (" & extra & ")" & " b=" & b & b_calc & " (" & b_ini & ")" & auCRLF & _
"buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _
"width=" & b & ", " & div & auCRLF & _
"mon=" & HMon & " dpi=" & nDPI & " scale=" & nScale & "%" & auCRLF & auCRLF & _
"smart=" & gSmartIndex & auCRLF & _
"button=" & idx_button & " width=" & idx_width & " pixel=" & idx_pixel
Local bSysDbg = false
If bSysDbg Then
OutputDebugString("" & auCRLF & (Not MousePos ? "Hint" : "Proc " & MousePos) & auCRLF & gHBarVerb & auCRLF & "idx=" & idx)
EndIf
If MousePos <> 2 Then gSmartIndex = 0
Return idx
EndFunc
Func HBarGetHint()
# чтение информации о кнопке из .bar фйла
Local sMenu, sButton, sCmd, sParam, sPath, sIcon, text
IniRead sMenu %gHBarFile% "Buttonbar" %'"menu" & gDragIndex' ""
IniRead sButton %gHBarFile% "Buttonbar" %'"button" & gDragIndex' ""
IniRead sCmd %gHBarFile% "Buttonbar" %'"cmd" & gDragIndex' ""
IniRead sParam %gHBarFile% "Buttonbar" %'"param" & gDragIndex' ""
IniRead sPath %gHBarFile% "Buttonbar" %'"path" & gDragIndex' ""
IniRead sIcon %gHBarFile% "Buttonbar" %'"iconic" & gDragIndex' ""
# удаление подсказки тотала
Local hTip = WinFind(0, auX64 ? "HintWindow" : "TToolTip")
If hTip > 0 Then DllCall("DestroyWindow", "handle", hTip)
# возврат текста
text = "index=" & gDragIndex & " of " & gHBarButtons+gHBarDivs & auCRLF & _
"menu=" & sMenu & auCRLF & _
"button=" & sButton & auCRLF & _
"cmd=" & sCmd & auCRLF & _
"param=" & sParam & auCRLF & _
"path=" & sPath & auCRLF & _
"iconic=" & sIcon & (gHBarDbg ? auCRLF & auCRLF & gHBarVerb & gHBarTxt : "")
Return text
EndFunc
Func HBarDragnDrop(DragIdx, DropIdx)
Static aItems = List("button","cmd","param","path","menu","iconic")
Local T1, T2, bTL = 0
If bTL Then T1 = GetUptime()
Local i, j, k, txt, key, new
txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# временная замена индекса
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx & "="
new = aItems[j] & 9999 & "="
txt = StrReplace(txt, key, new)
Next
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 1: " & StrFormat("%.3f", T2) & " sec")
OutputDebugString("Drag & Drop: " & DragIdx & " -> " & DropIdx)
EndIf
# умный сброс по границам кнопки
If gHBarSmart Then
If gSmartIndex > DropIdx + 0.499 Then
If DragIdx >= DropIdx Then
DropIdx += 1
EndIf
Else
If DragIdx < DropIdx Then
DropIdx -= 1
EndIf
EndIf
EndIf
If DragIdx < DropIdx Then
If gHBarMap[DropIdx-1] = -2 Then DropIdx -= 1
For i = DragIdx + 1 To DropIdx
For k = 0 To aItems.Count - 1
key = aItems[k] & i & "="
new = aItems[k] & i - 1 & "="
txt = StrReplace(txt, key, new)
#If bTL Then OutputDebugString("DragIdx < " & key & " -> " & new)
Next
Next
Else
For i = DragIdx - 1 TO DropIdx Step -1
For k = 0 To aItems.Count - 1
key = aItems[k] & i & "="
new = aItems[k] & i + 1 & "="
txt = StrReplace(txt, key, new)
#If bTL Then OutputDebugString("DragIdx > " & key & " -> " & new)
Next
Next
EndIf
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 2: " & StrFormat("%.3f", T2) & " sec")
EndIf
For j = 0 To aItems.Count - 1
key = aItems[j] & 9999 & "="
new = aItems[j] & DropIdx & "="
txt = StrReplace(txt, key, new)
Next
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 3: " & StrFormat("%.3f", T2) & " sec")
EndIf
SendCommand(2945) # cm_ReloadBarIcons
EndFunc
Func HBarReadIndex(Index)
Local key, val, txt
Static aItems = List("button","cmd","param","path","menu","iconic")
# сохранение индекса
For j = 0 To aItems.Count - 1
key = aItems[j] & Index
val = IniRead(gHBarFile, "Buttonbar", key)
If val <> '' Then
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
txt &= key & '=' & val & auCRLF
EndIf
Next
Return StrTrim(txt)
EndFunc
Func HBarDragnCopy(DragIdx, DropIdx)
Local key, val, ini, new
Static aItems = List("button","cmd","param","path","menu","iconic")
# сохранение кнопки
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx
val = IniRead(gHBarFile, "Buttonbar", key)
If val <> '' Then
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
ini &= key & '=' & val & auCRLF
EndIf
Next
ini = StrTrim(ini)
If ini = '' Then Return ShowDragHint("Нет данных о кнопке " & DragIdx)
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# умный сброс по границам кнопки
If gHBarSmart Then
If gSmartIndex > DropIdx + 0.499 Then
DropIdx += 1
EndIf
EndIf
If DropIdx <= gHBarMap.Count Then
# замена ключей со сдвигом +1
For i = gHBarMap.Count To DropIdx Step -1
For j = 0 To aItems.Count - 1
key = aItems[j] & i & "="
new = aItems[j] & i + 1 & "="
txt = StrReplace(txt, key, new)
Next
Next
EndIf
# добавление сохраненной кнопки
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx & "="
new = aItems[j] & DropIdx & "="
ini = StrReplace(ini, key, new)
Next
txt &= auCRLF & ini
# обновление панели
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", gHBarMap.Count+1)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
EndFunc
Func ShowDragHint(DragHint)
Local dark = IniRead(COMMANDER_INI, "Configuration", "DarkMode", 0)
SetHintParam("ShowHint", "Font", 13, "Tahoma")
SetHintParam("ShowHint", "BackColor", 0x0F0F0F)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
SetHintParam("ShowHint", "DarkText", 0xFFFFFF)
ShowHint(auCRLF & " " & DragHint & " " & auCRLF, 0, 0, 1000, 1)
WinAlign(LAST_HINT_WINDOW)
If Not dark Then
WinSetStyle(0x80000, 3, LAST_HINT_WINDOW)
DllCall("SetLayeredWindowAttributes", _
"hwnd", LAST_HINT_WINDOW, "ptr", 0, "byte", 192, "dword", 2)
EndIf
Sleep(100)
SetHintParam("ShowHint", "Reload")
EndFunc
Func HBarShowMenu()
Local hWnd = RequestInfo(28)
If hWnd = 0 Then
ShowDragHint("Окно панели не найдено")
Return
EndIf
If gHBarName <> WinGetText(hWnd) Then
ShowDragHint("Нет сведений о файле панели" & auCRLF & " " & _
"Используйте Shift + наведение для активации")
Return
EndIf
ShowPopupMenu /D /F /I:0 "HBarMenu"
EndFunc
Func HBarMenu()
Local txt
Local bak1 = FileChangeExt(gHBarFile, "bak1")
Local bak2 = FileChangeExt(gHBarFile, "bak2")
txt &= 'MENUITEM "' & gHBarName & '", em_aucmd /D' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Загружена как ANSI", em_aucmd /D ' & (gHBarCP = "ANSI" ? "/C" : "") & ' -1' & auCRLF
txt &= 'MENUITEM "Загружена как UTF-16", em_aucmd /D ' & (StrPos(gHBarCP, "UTF-16") ? "/C" : "") & ' -1' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Smart Drag&&Drop", em_aucmd ' & (gHBarSmart ? "/C" : "") & ' -1 HBarSmart' & auCRLF
txt &= 'MENUITEM "Отладочная информация", em_aucmd ' & (gHBarDbg ? "/C" : "") & ' -1 HBarDebugInfo' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Сохранить...", em_aucmd -1 HBarSaveAs' & auCRLF
txt &= 'POPUP "Загрузить панель"' & auCRLF
txt &= HBarAddBarMenu() & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'POPUP "Удалить кнопки за разрывом"' & auCRLF
txt &= HBarBreakMenu() & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Отменить действие", em_aucmd ' & (gHBarUndo ? "" : "/D") & ' -1 HBarUndo' & auCRLF
txt &= 'MENUITEM "Отменить последние действия", em_aucmd ' & (gHBarCancel ? "" : "/D") & ' -1 HBarCancel' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Резервная копия 1", em_aucmd ' & (FileExist(bak1) ? "" : "/D") & ' -1 HBarLoadBak 1' & auCRLF
txt &= 'MENUITEM "Резервная копия 2", em_aucmd ' & (FileExist(bak2) ? "" : "/D") & ' -1 HBarLoadBak 2' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Сделать резервную копию 1", em_aucmd -1 HBarSaveBak 1' & auCRLF
txt &= 'MENUITEM "Сделать резервную копию 2", em_aucmd -1 HBarSaveBak 2' & auCRLF
Return txt
EndFunc
Func HBarDebugInfo()
gHBarDbg = Not gHBarDbg
If gHBarDbg Then
ShowDragHint("Отладочная информация включена")
Else
ShowDragHint("Отладочная информация отключена")
EndIf
EndFunc
Func HBarSmart()
gHBarSmart = Not gHBarSmart
If gHBarSmart Then
ShowDragHint("Smart Drag&Drop включен")
Else
ShowDragHint("Smart Drag&Drop отключен")
EndIf
EndFunc
Func HBarSetCodePage(nCodePage)
Local sCP = (nCodePage = 1 ? "ANSI" : "UTF-16")
Local bLoadQ = gHBarCP <> sCP
gHBarCP = sCP
If bLoadQ Then
MsgBox("Открыть панель в кодировке " & gHBarCP & "?", "Autorun", 3+64+0)
If EXTENDED = 6 Then
HBarLoad()
ShowDragHint("Панель открыта как " & gHBarCP)
SendCommand(2945)
EndIf
EndIf
EndFunc
Func HBarSaveBak(nBak)
Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
If FileExist(bak) Then
MsgBox("Файл существует" & auCRLF & auCRLF & _
bak & auCRLF & auCRLF & "Перезаписать?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
EndIf
FileCopy(gHBarFile, bak, 1)
ShowDragHint("Файл сохранен " & bak)
EndFunc
Func HBarLoadBak(nBak)
Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
If Not FileExist(bak) Then
MsgBox("Файл не существует " & bak, "Autorun")
Return
EndIf
If Not FileExist(gHBarFile) Then
MsgBox("Файл не существует " & gHBarFile, "Autorun")
Return
EndIf
MsgBox("Файл " & gHBarFile & " будет перезаписан файлом " & _
bak & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
FileCopy(bak, gHBarFile, 1)
HBarLoad()
ShowDragHint("Файл загружен " & bak)
SendCommand(2945)
WinRedraw(0)
#WinRedraw(2)
EndFunc
Func HBarUndo()
If Not gHBarUndo Then Return
If FileGetTime(gHBarFile) <> gHBarUndoTs Then
MsgBox("Файл " & gHBarFile & " изменился на диске" & auCRLF & auCRLF & _
"Отмена действия невозможна", "Autorun", 64)
Return
EndIf
FileWrite(gHBarFile, gHBarUndoLoad, gHBarCP)
If ERROR = 1 Then
MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
Else
gHBarUndo = false
gHBarUndoLoad = ""
#gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
ShowDragHint("Действие отменено")
SendCommand(2945)
WinRedraw(0)
EndIf
EndFunc
Func HBarCancel()
If Not gHBarCancel Then Return
If gHBarCancelLoad = "" Then Return MsgBox("Пустое значение CancelLoad")
MsgBox("Файл будет перезаписан" & auCRLF & auCRLF & _
gHBarFile & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
FileWrite(gHBarFile, gHBarCancelLoad, gHBarCP)
If ERROR = 1 Then
MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
Else
gHBarCancel = false
gHBarCancelLoad = ""
#gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
ShowDragHint("Первоначальная панель загружена")
SendCommand(2945)
WinRedraw(0)
EndIf
EndFunc
gHBarBars = list()
Func HBarAddBarMenu()
Local sBars = FileFind(COMMANDER_PATH, "*.bar", -1, 1)
#sBars = StrTrim(sBars)
Local text
gHBarBars.Count = 0
gHBarBars.Text = sBars
For i = 0 To gHBarBars.Count - 1
text = text & 'MENUITEM "' & gHBarBars[i] & '", em_aucmd -1 HBarMergeOne ' & i & auCRLF
Next
Return text
EndFunc
Func HBarMergeOne(FileIndex)
Local bar = gHBarBars[FileIndex]
c = IniRead(bar, "Buttonbar", "Buttoncount", 0)
If c = 0 Then
MsgBox("Файл не содержит данных о кнопках" & auCRLF & auCRLF & bar, "Autorun", 0+48)
Return
EndIf
If FileGetTime(gHBarFile) <> gHBarFileTs Then
MsgBox("Операция невозможна. Файл главной панели изменился.")
Return
Endif
Local text = FileRead(bar), count = gHBarMap.Count + 1
Local rext = 'button' & count & '=' & auCRLF & _
'cmd' & count & '=-2' & auCRLF & 'iconic' & count & '=0' & auCRLF
Local i = 0
Local rex = RegExp('(?i)(button|cmd|param|path|menu|iconic)(\d+?)=(.*?)\R', text)
If rex.Exec() Then
Do
#If StrLower(rex.Match[2]) = 'button' Then i += 1
rext &= rex.Match[1] & rex.Match[2]+count & '=' & rex.Match[3] & auCRLF
Until not rex.ExecNext()
EndIf
Free(rex)
#If i < 1 Then Return MsgBox("Error: the number of buttons can't be zero")
#rext = StrTrim(rext)
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
txt &= auCRLF & rext
# обновление панели
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", count+c)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
#SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
#SendCommand(2901, 0, 1)
#SendCommand(2901, 0, 1) # cm_VisButtonBar
#Sleep(10)
#SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(0)
#WinRedraw(2)
EndFunc
Func HBarBreakMenu()
Local text
For i = 0 To gHBarMap.Count - 1
If gHBarMap[i] = -2 Then
text = text & 'MENUITEM "Индекс разрыва: ' & i+1 & '", em_aucmd -1 HBarBreakErase ' & i+1 & auCRLF
EndIf
Next
If text = "" Then text = 'MENUITEM "Нет разрывов", em_aucmd /D -1'
Return text
EndFunc
Func HBarBreakErase(BreakIndex)
If FileGetTime(gHBarFile) <> gHBarFileTs Then
MsgBox("Операция невозможна. Файл главной панели изменился.")
Return
Endif
If BreakIndex < 1 Then
MsgBox("Индекс разрыва не может быть меньше 2")
Return
Endif
Local text = gHBarList.Text, rext = ""
Local rex = RegExp('(?i)(button|cmd|param|path|menu|iconic)(\d+?)=(.*?)\R', text)
If rex.Exec() Then
Do
If rex.Match[2] < BreakIndex Then
rext &= rex.Match[1] & rex.Match[2] & '=' & rex.Match[3] & auCRLF
EndIf
Until not rex.ExecNext()
EndIf
Free(rex)
If rext = "" Then Return MsgBox("Ошибка удаления. Buttoncount=0, BreakIndex=" & BreakIndex)
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# обновление панели
gHBarList.Text = "[Buttonbar]" & auCRLF & "Buttoncount=" & BreakIndex-1 & auCRLF & rext
gHBarList.SaveToFile(gHBarFile, gHBarCP)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
#SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
#SendCommand(2901, 0, 1)
#SendCommand(2901, 0, 1)
#Sleep(10)
#SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
SendCommand(2945) # cm_ReloadBarIcons
WinRedraw(0)
#WinRedraw(2)
EndFunc
#{
поиск индекса по ключу и значению:
bar = COMMANDER_PATH & "\Bars\Main.bar"
idx = FindButtonIdx(bar, "cmd", "61007")
idx = FindButtonIdx(bar, "menu", "Auto_bars")
idx = FindButtonIdx(bar, "button", "WCMICONS.dll,72")
MsgBox(FindButtonIdx(bar, "param", '/ef "tcm(60011,1)"'))
#}
Func FindButtonIdx(ButtonBar, ButtonKey, ButtonVal)
Local txt, pos, len, sub, idx = 0
If Not FileExist(ButtonBar) Then
ShowDragHint("Панель не найдена " & ButtonBar)
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)
If sub = ButtonKey Then
idx = StrMid(txt, pos-i, i)
If IsInt(idx) Then Break
Endif
Next
# перепроверка индекса
If idx > 0 Then
IniRead txt %ButtonBar% "Buttonbar" %"ButtonKey & idx"
If StrPos(txt, ButtonVal) > 0 Then Return idx
EndIf
Return 0
EndFunc
Func HBarSaveAs()
# буфер для имени файла
Local file = Buffer(1024)
file.Zero()
file.SetStr(gHBarFile)
# буфер для фильтра расширений
Local fstr = "Bar files (*.bar)" & Chr(0) & "*.bar" & Chr(0) & Chr(0)
Local flen = StrLen(fstr) * 2
Local filt = Buffer(flen)
filt.Zero()
filt.SetStr(fstr)
# буфер для структуры OPENFILENAMEW
Local ofn = Buffer(auX64 ? 152 : 76)
ofn.Zero()
ofn.SetNum(0, "UInt", ofn.size) # lStructSize
If auX64 Then
ofn.SetNum(8, "Ptr", AUTORUN_TCHANDLE) # hwndOwner
ofn.SetNum(24, "Ptr", filt.ptr) # lpstrFilter
ofn.SetNum(48, "Ptr", file.ptr) # lpstrFile
ofn.SetNum(56, "Dword", file.size) # nMaxFile
ofn.SetNum(96, "Dword", 0x00000802) # 0x00000002 | 0x00000800
Else
ofn.SetNum(4, "Ptr", AUTORUN_TCHANDLE) # hwndOwner
ofn.SetNum(12, "Ptr", filt.ptr) # lpstrFilter
ofn.SetNum(28, "Ptr", file.ptr) # lpstrFile
ofn.SetNum(32, "Dword", file.size) # nMaxFile
ofn.SetNum(52, "Dword", 0x00000802) # 0x00000002 | 0x00000800
EndIf
If DllCall("comdlg32\GetSaveFileNameW", "Ptr", ofn.ptr) Then
Local new = file.GetStr()
If new <> gHBarFile Then
gHBarList.SaveToFile(new, gHBarCP)
Else
MsgBox("Файл не может быть сохранен сам в себя","Autorun", 48)
EndIf
EndIf
Free(file, filt, ofn)
EndFunc
Func HBarDragIcon(DragIdx, DropIdx)
# сохранение значка
Local val = IniRead(gHBarFile, "Buttonbar", "button" & DragIdx)
If val = '' Then
Return ShowDragHint("Нет данных о значке button" & DragIdx)
Else
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
EndIf
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# обновление панели
IniWrite(gHBarFile, "Buttonbar", "button" & DropIdx, val)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
EndFunc |
 Hidden text |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1193
|
(Separately) Posted: Sat Jul 11, 2026 14:04 Post subject: |
|
|
sa
Да, я немного ступил, когда вы говорили об удалении. Думал, речь идет о выделении дипазона, но увы, в Autorun нет возможности делать поля ввода, за исключением самой простой формы, да и то через VBScript.
Что касается удаления одной кнопки, сделать его было несложно (самая последняя функция в модуле). Пока сделал так: вынос кнопки на 200 пикселей за панель (от начала панели) + удержание кнопки переноса удаляет ее. При этом появляется соответствующий значок. DPI не учитывается, что может быть проблемой при большом масштабировании, но это пока только для теста. Все можно изменить. Может быть, у вас появятся какие-то идеи, если не понравится. Я сам пока не понял: вроде бы нормально, но...
Относительно диапазона, сделал в меню удаления за разрывом дополнительные пункты для удаления кнопок между разрывов. Немного потестировал — вроде работает. Но косяки, конечно, могут быть. Пока не буду на первой странице делать обновления, поскольку модуль еще в режиме тестирования.
 Hidden text | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
# правый клик с удержанием Ctrl
ControlSetMouseAction /R /K:C 28 "HBarShowMenu"
# Win + Backspace
# отмена последнего действия
SetHotkeyAction /K:W /H:BS /DM /S "HBarUndo"
Global gDragIndex, gDropIndex, gSmartIndex
Global gHBarButtons = 0, gHBarDivs = 0, gHBarSmart = 1
Global gHBarName, gHBarFile, gHBarFileTs
Global gHBarTxt, gHBarCP = "ANSI", gHBarWincmd = 0, gHBarDbg = 0
Global gHBarHint = 0, gHBarVerb, gHBarCancel, gHBarCancelLoad, gHBarLoadError = 0
Global gHBarList = List(), gHBarMap = List(), gHBarUndo, gHBarUndoTs, gHBarUndoLoad
Global gHBarWndProc, hBarWnd = 0
Global gHBarWP = Callback("HBarWndProc", "hwnd;uint;wparam;lparam")
Func HBarWndProc(hWnd, uMsg, wParam, lParam)
Static IsDrag = 0, _
hTotal = DllCall("GetModuleHandleW", "Ptr", 0, "handle"), _
MK_SHIFT = 0x0004, _
MK_CONTROL = 0x0008, _
MK_LBUTTON = 0x0001, _
WM_MOUSEMOVE = 0x0200, _
WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
MoveButton = MK_CONTROL, _
CopyButton = MK_SHIFT
Static drag_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32646), _
stop_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32648), _
icon_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 13), _
kick_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 26), _
copy_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 25), _
drag_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 22), _
stop_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 21)
Static SM_CXDRAG = 68, SM_CYDRAG = 69, _
dragX = GetSystemMetrics(SM_CXDRAG), dragY = GetSystemMetrics(SM_CYDRAG), _
startX, startY
Local x, y, pos
If gHBarLoadError Then
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndIf
Switch uMsg
Case WM_LBUTTONDOWN
If IsDrag = 0 And (BitAND(wParam, MoveButton) Or BitAND(wParam, CopyButton)) Then
Static buf = Buffer(8) # POINT
buf.Zero()
x = BitAND(lParam, 0xFFFF)
y = BitAND(BitShift(lParam,16), 0xFFFF)
startX = x
startY = y
buf.SetNum(0, "int", x, "int", y)
DllCall("ClientToScreen", "hwnd", hWnd, "ptr", buf.ptr)
pos = buf.GetNum(0, "int64")
#x = buf.GetNum(0)
#y = buf.GetNum(4)
#If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
If DllCall("DragDetect", "hwnd", hWnd, "int64", pos) Then
If FileGetTime(gHBarFile) <> gHBarFileTs Then
ShowDragHint("Операция невозможна. Файл панели изменился.")
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
Endif
If BitAND(wParam, MoveButton) And BitAND(wParam, CopyButton) Then
IsDrag = MoveButton
Else
IsDrag = wParam
EndIf
WinSetStyle(0x80000, 3, hWnd)
If BitAND(wParam, MoveButton) Then
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
Else
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 216, "dword", 2)
EndIf
x = buf.GetNum(0)
y = buf.GetNum(4)
gDragIndex = HBarGetIdx(1, x, y)
Else
IsDrag = 0
DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", WM_LBUTTONUP, "wparam", wParam, "lparam", lParam)
Return 0
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag > 1 Then
Local nDragMode = IsDrag
DllCall("ReleaseCapture")
IsDrag = 0
If WinFromPoint() = hWnd Then
MouseGetPos("x","y")
gSmartIndex = 0
gDropIndex = HBarGetIdx(2, x, y)
If gDragIndex <> gDropIndex Then
If gHBarHint Then ShowDragHint("Index " & gDragIndex & " To Index: " & gDropIndex)
If BitAND(nDragMode, MoveButton) Then
HBarDragnDrop(gDragIndex, gDropIndex)
Else
If BitAND(wParam, MoveButton) Then
HBarDragIcon(gDragIndex, gDropIndex)
Else
HBarDragnCopy(gDragIndex, gDropIndex)
EndIf
EndIf
EndIf
Else
y = BitAND(BitShift(lParam,16), 0xFFFF)
If BitAND(wParam, MoveButton) And lParam > 0 And y > 200 Then HBarDragDelete(gDragIndex)
EndIf
WinSetStyle(0x80000, 5, hWnd)
#Return 0
#lParam = MakeInt(y, x + 200, 2)
lParam = -1000
EndIf
Case WM_MOUSEMOVE
If IsDrag > 1 And BitAND(wParam, MK_LBUTTON) Then
If WinFromPoint() = hWnd Then
If BitAND(IsDrag, CopyButton) Then
DllCall("SetCursor", "Ptr", BitAND(wParam, MoveButton) ? icon_cursor : copy_cursor)
Else
DllCall("SetCursor", "Ptr", drag_cursor)
EndIf
#DllCall("SetCursor", "Ptr", BitAND(IsDrag, MoveButton) ? drag_cursor : copy_cursor)
Else
y = BitAND(BitShift(lParam,16), 0xFFFF)
#WinSetText(lParam & " y=" & y)
If BitAND(wParam, MoveButton) And lParam > 0 And y > 200 Then
DllCall("SetCursor", "Ptr", kick_cursor)
Else
DllCall("SetCursor", "Ptr", stop_cursor)
EndIf
EndIf
EndIf
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func HBarShowHint()
# панель в режиме drag'n'drop
If WinHasStyle(0x80000, 1, hBarWnd) Then Return
# состояние CapsLock и Shift
If BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1) = 0 Then
If Not IsPressed(0x10) Then Return
EndIf
# дескриптор горизонтальной панели
Local hWnd = RequestInfo(28)
If hWnd = 0 Then
Return "Окно панели не найдено " & hWnd
EndIf
# глобальные переменные дескриптора и оконной процедуры
If hBarWnd <> hWnd Then
hBarWnd = hWnd
gHBarWndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", hBarWnd, "int", -4, "long_ptr", gHBarWP.Ptr, "ptr")
EndIf
# поиск файла панели
If gHBarName <> WinGetText(hBarWnd) Then
gHBarUndo = false
gHBarUndoLoad = ""
gHBarCancel = false
gHBarCancelLoad = ""
gHBarFile = HBarGetFile()
If Not FileExist(gHBarFile) Then
gHBarName = ""
Return "Файл панели не найден " & gHBarFile
EndIf
# метка времени
gHBarFileTs = FileGetTime(gHBarFile)
# загрузка панели
HBarLoad()
If gHBarLoadError Then Return HBarGetHint()
ElseIf FileGetTime(gHBarFile) <> gHBarFileTs Then
gHBarUndo = false
gHBarUndoLoad = ""
If Not FileExist(gHBarFile) Then
gHBarName = ""
Return "Файл панели не найден " & gHBarFile
EndIf
gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
If gHBarLoadError Then Return HBarGetHint()
EndIf
# индекс кнопки под курсором
gDragIndex = HBarGetIdx()
If Not gDragIndex And Not gHBarDbg Then Return "Не удалось определить индекс кнопки"
Return HBarGetHint()
EndFunc
Func HBarGetFile()
Local bar, txt
# информация о файле панели в wincmd.ini
IniRead /R bar %COMMANDER_INI% "Buttonbar" "Buttonbar" "%COMMANDER_PATH%\DEFAULT.BAR"
# раскрытие переменной окружения
bar = Set(bar)
# в конфигурации указано только имя файла
If FileGetDir(bar) = "" Then bar = COMMANDER_PATH & "\" & bar
gHBarWincmd = bar
# чтение текста окна панели
txt = WinGetText(hBarWnd)
gHBarName = txt
# на панель загружен временный .bar файл
If Not StrPos(bar, txt) Then
bar = COMMANDER_PATH & "\Bars\" & txt
EndIf
If Not FileExist(bar) Then
bar = GetCurrentPath() & "\" & txt
EndIf
# проверка существования файла панели
If Not FileExist(bar) Then
bar = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
gHBarLoadError = 0
Local bar = FileRead(gHBarFile, 128, "RAW")
Local bom = "FFFE"
Local utf = "5B0042007500740074006F006E006200610072005D000D000A00"
If ERROR = 1 Then
gHBarLoadError = 1
gHBarCP = "Unknown"
Return
EndIf
If StrLeft(bar, 4) = "FFFE" Then
gHBarCP = "UTF-16 BOM"
Else
IF StrPos(bar, utf) Then
gHBarCP = "UTF-16 без BOM"
Else
gHBarCP = "ANSI"
EndIf
EndIf
# загрузка файла в массив
gHBarList.Count = 0
gHBarList.LoadFromFile(gHBarFile, gHBarCP)
# количество кнопок в файле
Local nCount = 0
IniRead /R nCount %gHBarFile% "Buttonbar" "Buttoncount" 0
# обнуление счетчиков
gHBarDivs = 0
gHBarButtons = 0
# локальные переменные
Local j, key, val, found, oButton = Map(), oCmd = Map()
# поиск кнопок и команд
For j = 0 To gHBarList.Count - 1
found = 0
If StrLeft(gHBarList[j], 6) = "button" Then
found = 1
ElseIf StrLeft(gHBarList[j], 3) = "cmd" Then
found = 2
EndIf
If found > 0 Then
key = StrLower(StrPart(gHBarList[j], "=", 1))
val = StrLen(StrPart(gHBarList[j], "=", 2))
If found = 1 Then
oButton.Set(key, val)
Else
oCmd.Set(key, val)
EndIf
EndIf
Next
gHBarMap.Count = 0
# подсчет кнопок и разделителей
For j = 1 To nCount
key = "button" & j
val = oButton.Get(key, 0)
If val > 0 Then
# количество кнопок
gHBarButtons += 1
gHBarMap.Add(1)
Else
# количество разделителей
gHBarDivs += 1
If oCmd.Get("cmd" & j, 0) = 2 Then
gHBarMap.Add(-2)
Else
gHBarMap.Add(0)
EndIf
EndIf
Next
Free(oButton, oCmd)
If gHBarButtons = 0 Then gHBarLoadError = 1
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded" & ": " & gHBarFile & " > " & gHBarCP & " "
If gHBarLoadError Then gHBarTxt &= " -- ERROR LOADING"
gHBarTxt &= auCRLF
For j = 0 To gHBarMap.Count - 1
gHBarTxt &= gHBarMap[j] & " "
If j > 0 and Mod(j, 50) = 0 Then gHBarTxt &= auCRLF
Next
gHBarTxt &= auCRLF & "Wincmd.ini: " & gHBarWincmd
EndFunc
Func HBarGetIdx(MousePos = false, PosX = 0, PosY = 0)
# дескриптор монитора окна ТС
Local hMon = DllCall("MonitorFromWindow", "hwnd", AUTORUN_TCHANDLE, "dword", 2)
# буфер для структуры MONITORINFOEX
Local buf = Buffer(104)
buf.Zero()
buf.SetNum(0, "dword", 104)
DllCall("GetMonitorInfoW", "ptr", hMon, "ptr", buf.ptr)
# имя монитора
Local sMon = buf.GetStr(40)
# информация о масштабировании экрана
Local DC = DllCall("GetDC", "int", 0)
Local nDPI = DllCall("GetDeviceCaps", "handle", DC, "int", 88) # LOGPIXELSX
Local nScale = DllCall("MulDiv", "int", 100, "int", nDPI, "int", 96)
DllCall("ReleaseDC", "int", 0, "handle", DC)
# локальные переменные
Local x, y, w, h, mx, my, idx, row, rows, rowh, dpi, b, extra
# координаты и размеры окна панели
WinGetPos("x", "y", "w", "h", hBarWnd)
# координаты указателя мыши
If MousePos Then
mx = PosX
my = PosY
Else
MouseGetPos("mx", "my")
EndIf
# чтение информации о высоте кнопок
IniRead /R b %COMMANDER_INI% "Buttonbar" "Buttonheight"
IniRead /R dpi %COMMANDER_INI% "Buttonbar" "DefaultDpi" %'nDPI'
Local b_ini = b, b_calc
# масштабирование экрана
If dpi <> nDPI Then
IniRead /R d %COMMANDER_INI% "Buttonbar" %'"Buttonheight" & nDPI' 0
If d <> 0 Then
b = d
Else
b = Round(b / (dpi / nDPI), 0)
b_calc = "*"
EndIf
EndIf
# количество рядов кнопок на панели
rows = Floor(h/b)
If rows = 0 Then Return ShowDragHint("Error number of rows can't be zero")
# количество дополнительных пикселей
extra = Mod(h,b)
# ширина разделителя
Local div = Floor(b/3)
# высота одного ряда
rowh = b + 3
# номер ряда под указателем
row = Ceil((my - y)/rowh)
# абстрактные координаты по оси х
Local tx = (mx - x + 1) + ((row - 1) * w), cx = 0, ex = 0, idx_padding = 0
# индекс кнопки в ряду
If gHBarDivs = 0 Then
idx = (Floor((mx - x)/b) + 1) + (row-1)*(Floor(w/b))
If idx > gHBarButtons Then idx = gHBarButtons
Else
j = 1
idx = 0
For i = 0 To gHBarMap.Count - 1
idx_padding = 0
If gHBarMap[i] = -2 Then
If i = 0 Then cx += w # первая кнопка разрыв
j += 1
cx += ex
If i > 0 And gHBarMap[i-1] = -2 Then
cx += w - ex
EndIf
If i = gHBarMap.Count - 1 Then cx += w # последняя кнопка разрыв
If cx >= tx Then
idx = i + 1
Break
EndIf
Continue
EndIf
cx += (gHBarMap[i] = 0 ? div : b)
ex = j*w - cx
If i + 1 <= gHBarMap.Count - 1 Then
next_button = gHBarMap[i+1]
next_width = (next_button = -2 ? 0 : (next_button = 0 ? div : b))
If ex < next_width Then
cx += ex
idx_padding += ex
j += 1
EndIf
Else
cx += ex
idx_padding = ex
EndIf
If cx >= tx Then
idx = i + 1
Break
EndIf
Next
EndIf
idx_button = gHBarMap[idx-1]
idx_width = (idx_button = -2 ? 0 : (idx_button = 0 ? div : b))
idx_pixel = tx - (cx - idx_padding - idx_width)
idx_float = idx_width > 0 ? idx_pixel / idx_width : 0
# дробный индекс
gSmartIndex = idx + Round(idx_float, 3)
If Floor(gSmartIndex) > idx Then gSmartIndex = idx + 0.999
# дополнительная информация
gHBarVerb = "mouse=" & mx & ", " & my & auCRLF & _
"bar=" & x & ", " & y & ", " & w & ", " & h & auCRLF & _
"map=" & tx & ", " & cx & auCRLF & _
"row=" & row & " of " & rows & auCRLF & _
"height=" & rowh & " (" & extra & ")" & " b=" & b & b_calc & " (" & b_ini & ")" & auCRLF & _
"buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _
"width=" & b & ", " & div & auCRLF & _
"mon=" & HMon & " dpi=" & nDPI & " scale=" & nScale & "%" & auCRLF & auCRLF & _
"smart=" & gSmartIndex & auCRLF & _
"button=" & idx_button & " width=" & idx_width & " pixel=" & idx_pixel
Local bSysDbg = false
If bSysDbg Then
OutputDebugString("" & auCRLF & (Not MousePos ? "Hint" : "Proc " & MousePos) & auCRLF & gHBarVerb & auCRLF & "idx=" & idx)
EndIf
If MousePos <> 2 Then gSmartIndex = 0
Return idx
EndFunc
Func HBarGetHint()
# чтение информации о кнопке из .bar фйла
Local sMenu, sButton, sCmd, sParam, sPath, sIcon, text
IniRead sMenu %gHBarFile% "Buttonbar" %'"menu" & gDragIndex' ""
IniRead sButton %gHBarFile% "Buttonbar" %'"button" & gDragIndex' ""
IniRead sCmd %gHBarFile% "Buttonbar" %'"cmd" & gDragIndex' ""
IniRead sParam %gHBarFile% "Buttonbar" %'"param" & gDragIndex' ""
IniRead sPath %gHBarFile% "Buttonbar" %'"path" & gDragIndex' ""
IniRead sIcon %gHBarFile% "Buttonbar" %'"iconic" & gDragIndex' ""
# удаление подсказки тотала
Local hTip = WinFind(0, auX64 ? "HintWindow" : "TToolTip")
If hTip > 0 Then DllCall("DestroyWindow", "handle", hTip)
# возврат текста
text = "index=" & gDragIndex & " of " & gHBarButtons+gHBarDivs & auCRLF & _
"menu=" & sMenu & auCRLF & _
"button=" & sButton & auCRLF & _
"cmd=" & sCmd & auCRLF & _
"param=" & sParam & auCRLF & _
"path=" & sPath & auCRLF & _
"iconic=" & sIcon & (gHBarDbg ? auCRLF & auCRLF & gHBarVerb & gHBarTxt : "")
Return text
EndFunc
Func HBarDragnDrop(DragIdx, DropIdx)
Static aItems = List("button","cmd","param","path","menu","iconic")
Local T1, T2, bTL = 0
If bTL Then T1 = GetUptime()
Local i, j, k, txt, key, new
txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# временная замена индекса
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx & "="
new = aItems[j] & 9999 & "="
txt = StrReplace(txt, key, new)
Next
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 1: " & StrFormat("%.3f", T2) & " sec")
OutputDebugString("Drag & Drop: " & DragIdx & " -> " & DropIdx)
EndIf
# умный сброс по границам кнопки
If gHBarSmart Then
If gSmartIndex > DropIdx + 0.499 Then
If DragIdx >= DropIdx Then
DropIdx += 1
EndIf
Else
If DragIdx < DropIdx Then
DropIdx -= 1
EndIf
EndIf
EndIf
If DragIdx < DropIdx Then
If gHBarMap[DropIdx-1] = -2 Then DropIdx -= 1
For i = DragIdx + 1 To DropIdx
For k = 0 To aItems.Count - 1
key = aItems[k] & i & "="
new = aItems[k] & i - 1 & "="
txt = StrReplace(txt, key, new)
#If bTL Then OutputDebugString("DragIdx < " & key & " -> " & new)
Next
Next
Else
For i = DragIdx - 1 TO DropIdx Step -1
For k = 0 To aItems.Count - 1
key = aItems[k] & i & "="
new = aItems[k] & i + 1 & "="
txt = StrReplace(txt, key, new)
#If bTL Then OutputDebugString("DragIdx > " & key & " -> " & new)
Next
Next
EndIf
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 2: " & StrFormat("%.3f", T2) & " sec")
EndIf
For j = 0 To aItems.Count - 1
key = aItems[j] & 9999 & "="
new = aItems[j] & DropIdx & "="
txt = StrReplace(txt, key, new)
Next
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
If bTL Then
T2 = Round(GetUptime() - T1, 0) / 1000
OutputDebugString("Время операции 3: " & StrFormat("%.3f", T2) & " sec")
EndIf
SendCommand(2945) # cm_ReloadBarIcons
EndFunc
Func HBarReadIndex(Index)
Local key, val, txt
Static aItems = List("button","cmd","param","path","menu","iconic")
# сохранение индекса
For j = 0 To aItems.Count - 1
key = aItems[j] & Index
val = IniRead(gHBarFile, "Buttonbar", key)
If val <> '' Then
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
txt &= key & '=' & val & auCRLF
EndIf
Next
Return StrTrim(txt)
EndFunc
Func HBarDragnCopy(DragIdx, DropIdx)
Local key, val, ini, new
Static aItems = List("button","cmd","param","path","menu","iconic")
# сохранение кнопки
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx
val = IniRead(gHBarFile, "Buttonbar", key)
If val <> '' Then
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
ini &= key & '=' & val & auCRLF
EndIf
Next
ini = StrTrim(ini)
If ini = '' Then Return ShowDragHint("Нет данных о кнопке " & DragIdx)
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# умный сброс по границам кнопки
If gHBarSmart Then
If gSmartIndex > DropIdx + 0.499 Then
DropIdx += 1
EndIf
EndIf
If DropIdx <= gHBarMap.Count Then
# замена ключей со сдвигом +1
For i = gHBarMap.Count To DropIdx Step -1
For j = 0 To aItems.Count - 1
key = aItems[j] & i & "="
new = aItems[j] & i + 1 & "="
txt = StrReplace(txt, key, new)
Next
Next
EndIf
# добавление сохраненной кнопки
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx & "="
new = aItems[j] & DropIdx & "="
ini = StrReplace(ini, key, new)
Next
txt &= auCRLF & ini
# обновление панели
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", gHBarMap.Count+1)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
EndFunc
Func ShowDragHint(DragHint)
Local dark = IniRead(COMMANDER_INI, "Configuration", "DarkMode", 0)
SetHintParam("ShowHint", "Font", 13, "Tahoma")
SetHintParam("ShowHint", "BackColor", 0x0F0F0F)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
SetHintParam("ShowHint", "DarkBackColor", 0xFF0000)
SetHintParam("ShowHint", "DarkText", 0xFFFFFF)
ShowHint(auCRLF & " " & DragHint & " " & auCRLF, 0, 0, 1000, 1)
WinAlign(LAST_HINT_WINDOW)
If Not dark Then
WinSetStyle(0x80000, 3, LAST_HINT_WINDOW)
DllCall("SetLayeredWindowAttributes", _
"hwnd", LAST_HINT_WINDOW, "ptr", 0, "byte", 192, "dword", 2)
EndIf
Sleep(100)
SetHintParam("ShowHint", "Reload")
EndFunc
Func HBarShowMenu()
Local hWnd = RequestInfo(28)
If hWnd = 0 Then
ShowDragHint("Окно панели не найдено")
Return
EndIf
If gHBarName <> WinGetText(hWnd) Then
ShowDragHint("Нет сведений о файле панели" & auCRLF & " " & _
"Используйте Shift + наведение для активации")
Return
EndIf
ShowPopupMenu /D /F /I:0 "HBarMenu"
EndFunc
Func HBarMenu()
Local txt
Local bak1 = FileChangeExt(gHBarFile, "bak1")
Local bak2 = FileChangeExt(gHBarFile, "bak2")
txt &= 'MENUITEM "' & gHBarName & '", em_aucmd /D' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Загружена как ANSI", em_aucmd /D ' & (gHBarCP = "ANSI" ? "/C" : "") & ' -1' & auCRLF
txt &= 'MENUITEM "Загружена как UTF-16", em_aucmd /D ' & (StrPos(gHBarCP, "UTF-16") ? "/C" : "") & ' -1' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Smart Drag&&Drop", em_aucmd ' & (gHBarSmart ? "/C" : "") & ' -1 HBarSmart' & auCRLF
txt &= 'MENUITEM "Отладочная информация", em_aucmd ' & (gHBarDbg ? "/C" : "") & ' -1 HBarDebugInfo' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Сохранить...", em_aucmd -1 HBarSaveAs' & auCRLF
txt &= 'POPUP "Загрузить панель"' & auCRLF
txt &= HBarAddBarMenu() & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'POPUP "Удалить кнопки за разрывом"' & auCRLF
txt &= HBarBreakMenu() & auCRLF
txt &= 'END_POPUP' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Отменить действие", em_aucmd ' & (gHBarUndo ? "" : "/D") & ' -1 HBarUndo' & auCRLF
txt &= 'MENUITEM "Отменить последние действия", em_aucmd ' & (gHBarCancel ? "" : "/D") & ' -1 HBarCancel' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Резервная копия 1", em_aucmd ' & (FileExist(bak1) ? "" : "/D") & ' -1 HBarLoadBak 1' & auCRLF
txt &= 'MENUITEM "Резервная копия 2", em_aucmd ' & (FileExist(bak2) ? "" : "/D") & ' -1 HBarLoadBak 2' & auCRLF
txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Сделать резервную копию 1", em_aucmd -1 HBarSaveBak 1' & auCRLF
txt &= 'MENUITEM "Сделать резервную копию 2", em_aucmd -1 HBarSaveBak 2' & auCRLF
Return txt
EndFunc
Func HBarDebugInfo()
gHBarDbg = Not gHBarDbg
If gHBarDbg Then
ShowDragHint("Отладочная информация включена")
Else
ShowDragHint("Отладочная информация отключена")
EndIf
EndFunc
Func HBarSmart()
gHBarSmart = Not gHBarSmart
If gHBarSmart Then
ShowDragHint("Smart Drag&Drop включен")
Else
ShowDragHint("Smart Drag&Drop отключен")
EndIf
EndFunc
Func HBarSetCodePage(nCodePage)
Local sCP = (nCodePage = 1 ? "ANSI" : "UTF-16")
Local bLoadQ = gHBarCP <> sCP
gHBarCP = sCP
If bLoadQ Then
MsgBox("Открыть панель в кодировке " & gHBarCP & "?", "Autorun", 3+64+0)
If EXTENDED = 6 Then
HBarLoad()
ShowDragHint("Панель открыта как " & gHBarCP)
SendCommand(2945)
EndIf
EndIf
EndFunc
Func HBarSaveBak(nBak)
Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
If FileExist(bak) Then
MsgBox("Файл существует" & auCRLF & auCRLF & _
bak & auCRLF & auCRLF & "Перезаписать?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
EndIf
FileCopy(gHBarFile, bak, 1)
ShowDragHint("Файл сохранен " & bak)
EndFunc
Func HBarLoadBak(nBak)
Local bak = FileChangeExt(gHBarFile, "bak" & nBak)
If Not FileExist(bak) Then
MsgBox("Файл не существует " & bak, "Autorun")
Return
EndIf
If Not FileExist(gHBarFile) Then
MsgBox("Файл не существует " & gHBarFile, "Autorun")
Return
EndIf
MsgBox("Файл " & gHBarFile & " будет перезаписан файлом " & _
bak & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
FileCopy(bak, gHBarFile, 1)
HBarLoad()
ShowDragHint("Файл загружен " & bak)
SendCommand(2945)
WinRedraw(0)
#WinRedraw(2)
EndFunc
Func HBarUndo()
If Not gHBarUndo Then Return
If FileGetTime(gHBarFile) <> gHBarUndoTs Then
MsgBox("Файл " & gHBarFile & " изменился на диске" & auCRLF & auCRLF & _
"Отмена действия невозможна", "Autorun", 64)
Return
EndIf
FileWrite(gHBarFile, gHBarUndoLoad, gHBarCP)
If ERROR = 1 Then
MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
Else
gHBarUndo = false
gHBarUndoLoad = ""
#gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
ShowDragHint("Действие отменено")
SendCommand(2945)
WinRedraw(0)
EndIf
EndFunc
Func HBarCancel()
If Not gHBarCancel Then Return
If gHBarCancelLoad = "" Then Return MsgBox("Пустое значение CancelLoad")
MsgBox("Файл будет перезаписан" & auCRLF & auCRLF & _
gHBarFile & auCRLF & auCRLF & "Продолжить?", "Autorun", 3+32+0)
If EXTENDED <> 6 Then Return
FileWrite(gHBarFile, gHBarCancelLoad, gHBarCP)
If ERROR = 1 Then
MsgBox("Ошибка записи " & gHBarFile, "Autorun", 64)
Else
gHBarCancel = false
gHBarCancelLoad = ""
#gHBarFileTs = FileGetTime(gHBarFile)
HBarLoad()
ShowDragHint("Первоначальная панель загружена")
SendCommand(2945)
WinRedraw(0)
EndIf
EndFunc
gHBarBars = list()
Func HBarAddBarMenu()
Local sBars = FileFind(COMMANDER_PATH, "*.bar", -1, 1)
#sBars = StrTrim(sBars)
Local text
gHBarBars.Count = 0
gHBarBars.Text = sBars
For i = 0 To gHBarBars.Count - 1
text = text & 'MENUITEM "' & gHBarBars[i] & '", em_aucmd -1 HBarMergeOne ' & i & auCRLF
Next
Return text
EndFunc
Func HBarMergeOne(FileIndex)
Local bar = gHBarBars[FileIndex]
c = IniRead(bar, "Buttonbar", "Buttoncount", 0)
If c = 0 Then
MsgBox("Файл не содержит данных о кнопках" & auCRLF & auCRLF & bar, "Autorun", 0+48)
Return
EndIf
If FileGetTime(gHBarFile) <> gHBarFileTs Then
MsgBox("Операция невозможна. Файл главной панели изменился.")
Return
Endif
Local text = FileRead(bar), count = gHBarMap.Count + 1
Local rext = 'button' & count & '=' & auCRLF & _
'cmd' & count & '=-2' & auCRLF & 'iconic' & count & '=0' & auCRLF
Local i = 0
Local rex = RegExp('(?i)(button|cmd|param|path|menu|iconic)(\d+?)=(.*?)\R', text)
If rex.Exec() Then
Do
#If StrLower(rex.Match[2]) = 'button' Then i += 1
rext &= rex.Match[1] & rex.Match[2]+count & '=' & rex.Match[3] & auCRLF
Until not rex.ExecNext()
EndIf
Free(rex)
#If i < 1 Then Return MsgBox("Error: the number of buttons can't be zero")
#rext = StrTrim(rext)
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
txt &= auCRLF & rext
# обновление панели
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", count+c)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
WinRedraw(0)
EndFunc
Func HBarBreakMenu()
Local text, br = List()
For i = 0 To gHBarMap.Count - 1
If gHBarMap[i] = -2 Then
br.Add(i+1)
text &= 'MENUITEM "Индекс разрыва: ' & i+1 & '", em_aucmd -1 HBarBreakErase ' & i+1 & ' ' & i+1 & auCRLF
EndIf
Next
If text = "" Then Return 'MENUITEM "Нет разрывов", em_aucmd /D -1'
If br.Count > 1 Then
Local r1 = br[0], r2 = 0
text &= 'MENUITEM SEPARATOR' & auCRLF
For i = 1 To br.Count - 1
r2 = br[i]
If r2 > 0 Then
text &= 'MENUITEM "Удалить кнопки между ' & r1 & ' - ' & r2 & '", em_aucmd -1 HBarBreakErase ' & r1 & ' ' & r2 & auCRLF
EndIf
r1 = r2
r2 = 0
Next
EndIf
Return text
EndFunc
Func HBarBreakErase(BreakIndex, StopIndex)
Local Count = 0, Range = StopIndex-BreakIndex+1
If FileGetTime(gHBarFile) <> gHBarFileTs Then
MsgBox("Операция невозможна. Файл главной панели изменился.")
Return
Endif
If BreakIndex < 1 Then
MsgBox("Индекс разрыва не может быть меньше 2")
Return
Endif
Local text = gHBarList.Text, rext = ""
Local rex = RegExp('(?i)(button|cmd|param|path|menu|iconic)(\d+?)=(.*?)\R', text)
If rex.Exec() Then
Do
If BreakIndex = StopIndex Then
If rex.Match[2] < BreakIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2] & '=' & rex.Match[3] & auCRLF
EndIf
Else
If rex.Match[2] < BreakIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2] & '=' & rex.Match[3] & auCRLF
ElseIf rex.Match[2] > StopIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2]-Range & '=' & rex.Match[3] & auCRLF
EndIf
EndIf
Until not rex.ExecNext()
EndIf
Free(rex)
If rext = "" Then Return MsgBox("Ошибка удаления. Buttoncount=0, BreakIndex=" & BreakIndex)
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# обновление панели
Local NewCount = 0
If BreakIndex = StopIndex Then
NewCount = BreakIndex - 1
Else
NewCount = StopIndex - BreakIndex
NewCount = gHBarMap.Count - NewCount - 1
EndIf
gHBarList.Text = "[Buttonbar]" & auCRLF & "Buttoncount=" & NewCount & auCRLF & rext
gHBarList.SaveToFile(gHBarFile, gHBarCP)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
WinRedraw(0)
EndFunc
#{
поиск индекса по ключу и значению:
bar = COMMANDER_PATH & "\Bars\Main.bar"
idx = FindButtonIdx(bar, "cmd", "61007")
idx = FindButtonIdx(bar, "menu", "Auto_bars")
idx = FindButtonIdx(bar, "button", "WCMICONS.dll,72")
MsgBox(FindButtonIdx(bar, "param", '/ef "tcm(60011,1)"'))
#}
Func FindButtonIdx(ButtonBar, ButtonKey, ButtonVal)
Local txt, pos, len, sub, idx = 0
If Not FileExist(ButtonBar) Then
ShowDragHint("Панель не найдена " & ButtonBar)
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)
If sub = ButtonKey Then
idx = StrMid(txt, pos-i, i)
If IsInt(idx) Then Break
Endif
Next
# перепроверка индекса
If idx > 0 Then
IniRead txt %ButtonBar% "Buttonbar" %"ButtonKey & idx"
If StrPos(txt, ButtonVal) > 0 Then Return idx
EndIf
Return 0
EndFunc
Func HBarSaveAs()
# буфер для имени файла
Local file = Buffer(1024)
file.Zero()
file.SetStr(gHBarFile)
# буфер для фильтра расширений
Local fstr = "Bar files (*.bar)" & Chr(0) & "*.bar" & Chr(0) & Chr(0)
Local flen = StrLen(fstr) * 2
Local filt = Buffer(flen)
filt.Zero()
filt.SetStr(fstr)
# буфер для структуры OPENFILENAMEW
Local ofn = Buffer(auX64 ? 152 : 76)
ofn.Zero()
ofn.SetNum(0, "UInt", ofn.size) # lStructSize
If auX64 Then
ofn.SetNum(8, "Ptr", AUTORUN_TCHANDLE) # hwndOwner
ofn.SetNum(24, "Ptr", filt.ptr) # lpstrFilter
ofn.SetNum(48, "Ptr", file.ptr) # lpstrFile
ofn.SetNum(56, "Dword", file.size) # nMaxFile
ofn.SetNum(96, "Dword", 0x00000802) # 0x00000002 | 0x00000800
Else
ofn.SetNum(4, "Ptr", AUTORUN_TCHANDLE) # hwndOwner
ofn.SetNum(12, "Ptr", filt.ptr) # lpstrFilter
ofn.SetNum(28, "Ptr", file.ptr) # lpstrFile
ofn.SetNum(32, "Dword", file.size) # nMaxFile
ofn.SetNum(52, "Dword", 0x00000802) # 0x00000002 | 0x00000800
EndIf
If DllCall("comdlg32\GetSaveFileNameW", "Ptr", ofn.ptr) Then
Local new = file.GetStr()
If new <> gHBarFile Then
gHBarList.SaveToFile(new, gHBarCP)
Else
MsgBox("Файл не может быть сохранен сам в себя","Autorun", 48)
EndIf
EndIf
Free(file, filt, ofn)
EndFunc
Func HBarDragIcon(DragIdx, DropIdx)
# сохранение значка
Local val = IniRead(gHBarFile, "Buttonbar", "button" & DragIdx)
If val = '' Then
Return ShowDragHint("Нет данных о значке button" & DragIdx)
Else
If StrLeft(val, 1) ='"' And StrRight(val, 1) ='"' Then val = '"' & val & '"'
EndIf
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# обновление панели
IniWrite(gHBarFile, "Buttonbar", "button" & DropIdx, val)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
EndFunc
Func HBarDragDelete(DragIdx)
Static aItems = List("button","cmd","param","path","menu","iconic")
# сохранение панели для откатов
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# замена индекса удаляемой кнопки
Local key, new
For j = 0 To aItems.Count - 1
key = aItems[j] & DragIdx & "="
new = aItems[j] & 8888 & "="
txt = StrReplace(txt, key, new)
Next
# замена ключей со сдвигом -1
For i = DragIdx + 1 To gHBarMap.Count
For k = 0 To aItems.Count - 1
key = aItems[k] & i & "="
new = aItems[k] & i - 1 & "="
txt = StrReplace(txt, key, new)
Next
Next
# обновление панели
gHBarList.Text = txt
gHBarList.SaveToFile(gHBarFile, gHBarCP)
# удаление ключей кнопки из файла
For j = 0 To aItems.Count - 1
key = aItems[j] & 8888
IniDelete(gHBarFile, "Buttonbar", key)
Next
# обновление общего количества кнопок
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", gHBarMap.Count-1)
# запоминание времени последнего изменения
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
# загрузка обновленного айла панели
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
EndFunc |
P.S. Я добавил горячую клавишу в заголовок для отмены последнего действия Win+Backspace, можно изменить. |
|
| Back to top |
|
 |
sa
Joined: 29 Apr 2009 Posts: 2745
|
(Separately) Posted: Sun Jul 12, 2026 10:28 Post subject: |
|
|
| Orion9 wrote: | | Перенос значка | Работает. Лучше, наверное, запретить перенос значка на разделители, по крайней мере на разрывы – это, к тому же чревато ошибками в работе скрипта. См. ранее: | Quote: | | в результате разрыв строки проверяется не по значению "-2", а по размеру 2. Но поскольку вероятность команды с двумя символами очень мала, пока оставил так, но нужно будет переделать. |
| Orion9 wrote: | | Что касается удаления одной кнопки, сделать его было несложно | Работает. С учётом возможности отмены действия, в отличие от удаления средствами TC, наверное, это полезная функция.
| Orion9 wrote: | | дополнительные пункты для удаления кнопок между разрывов | Возможно, удобнее один из двух разрывов оставлять, но не факт...
А так всё наглядно получилось, тем более, что копировать разрывы для выделения диапазона несложно. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1193
|
(Separately) Posted: Sun Jul 12, 2026 12:23 Post subject: |
|
|
| sa wrote: | | Лучше, наверное, запретить перенос значка на разделители, по крайней мере на разрывы – это, к тому же чревато ошибками в работе скрипта |
Да, я посмотрю, что там. Пока не успел основательно все протестировать, но постараюсь сделать это в ближайшее время.
| sa wrote: | | С учётом возможности отмены действия, в отличие от удаления средствами TC, наверное, это полезная функция. |
Вроде бы. Но само движение вниз для вас оказалось удобным? Я сначала делал, чтобы при касании верхней границы экрана кнопку можно было удалять, но доделав до смены значка, понял, что при расрытом на весь экран ТС это неудобно - расстояние слишком мальнькое. Вообще, вариантов как-то мало, наверное, пусть пока так останется, а там посмотрим.
| sa wrote: | | Возможно, удобнее один из двух разрывов оставлять, но не факт... |
Да нет, тут я промахнулся. Конечно же лучше оставлять! Исправлю. А также сделаю в меню пункты для добавления разрыва и разделителя, чтобы при их отсутствии не нужно было залезать в диалог изменения панели. А копировать разрывы и разделители действительно удобно, не говоря уж о кнопках, спасибо за идею  |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1193
|
(Separately) Posted: Sun Jul 12, 2026 19:21 Post subject: |
|
|
| sa wrote: | | Лучше, наверное, запретить перенос значка на разделители, по крайней мере на разрывы – это, к тому же чревато ошибками в работе скрипта. |
Да, это приводит к серьезным ошибкам! Там вообще на ниточке все держится. Если в файле панели будет мальшее отклонение от нормы, то проблемы будут обязательно. Видимо, придется пересматривать считывание панели с учетом разных нюансов, ведь сейчас кнопки просто определяются по наличию ключа button=, а разделители по cmd= с учетом, что ключ button= пустой.
Fix:
| Code: | Func HBarDragIcon(DragIdx, DropIdx)
# проверка индекса получателя
If gHBarMap[DropIdx-1] <> 1 Then Return ShowDragHint("Получатель не может быть разделителем")
# сохранение значка
Local val = IniRead(gHBarFile, "Buttonbar", "button" & DragIdx) |
| sa wrote: | | Возможно, удобнее один из двух разрывов оставлять |
Обновленная функция
 Hidden text | Code: | Func HBarBreakErase(BreakIndex, StopIndex)
Local Count = 0, Range = StopIndex-BreakIndex
If FileGetTime(gHBarFile) <> gHBarFileTs Then
MsgBox("Операция невозможна. Файл главной панели изменился.")
Return
Endif
If BreakIndex < 1 Then
MsgBox("Индекс разрыва не может быть меньше 2")
Return
Endif
Local text = gHBarList.Text, rext = ""
Local rex = RegExp('(?i)(button|cmd|param|path|menu|iconic)(\d+?)=(.*?)(\R|\Z)', text)
If rex.Exec() Then
Do
If BreakIndex = StopIndex Then
If rex.Match[2] < BreakIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2] & '=' & rex.Match[3] & auCRLF
EndIf
Else
If rex.Match[2] < BreakIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2] & '=' & rex.Match[3] & auCRLF
ElseIf rex.Match[2] >= StopIndex Then
Count += 1
rext &= rex.Match[1] & rex.Match[2]-Range & '=' & rex.Match[3] & auCRLF
EndIf
EndIf
Until not rex.ExecNext()
EndIf
Free(rex)
If rext = "" Then Return MsgBox("Ошибка удаления. Buttoncount=0, BreakIndex=" & BreakIndex)
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# обновление панели
Local NewCount = 0
If BreakIndex = StopIndex Then
NewCount = BreakIndex - 1
Else
NewCount = gHBarMap.Count - Range
EndIf
gHBarList.Text = "[Buttonbar]" & auCRLF & "Buttoncount=" & NewCount & auCRLF & rext
gHBarList.SaveToFile(gHBarFile, gHBarCP)
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
WinRedraw(0)
EndFunc
|
Добавил к регулярному выражению \Z, иначе последний ключ терялся, если панель заканчивается eof, а не \r\n. В функции HBarMergeOne это тоже нужно подправить.
+Новые два пункта
| Code: | txt &= 'MENUITEM SEPARATOR' & auCRLF
txt &= 'MENUITEM "Добавить разрыв", em_aucmd -1 HBarAddButton -2' & auCRLF
txt &= 'MENUITEM "Добавить разделитель", em_aucmd -1 HBarAddButton 1' & auCRLF
txt &= 'POPUP "Удалить кнопки за разрывом"' & auCRLF
|
 Hidden text | Code: | Func HBarAddButton(IndexType)
# сохранение панели
Local txt = gHBarList.Text
gHBarUndoLoad = txt
If Not gHBarCancel Then
gHBarCancel = true
gHBarCancelLoad = txt
EndIf
# добавление новых ключей
IniWrite(gHBarFile, "Buttonbar", "button" & gHBarMap.Count+1)
IniWrite(gHBarFile, "Buttonbar", "iconic" & gHBarMap.Count+1, 0)
If IndexType = -2 Then
IniWrite(gHBarFile, "Buttonbar", "cmd" & gHBarMap.Count+1, -2)
EndIf
# обновление общего количества кнопок
IniWrite(gHBarFile, "Buttonbar", "Buttoncount", gHBarMap.Count+1)
# запоминание времени последнего изменения
gHBarUndoTs = FileGetTime(gHBarFile)
gHBarFileTs = FileGetTime(gHBarFile)
If gHBarUndoTs Then
gHBarUndo = true
Else
gHBarUndo = false
gHBarUndoLoad = ""
EndIf
HBarLoad()
SendCommand(2945) # cm_ReloadBarIcons
WinRedraw(0)
WinRedraw(2)
EndFunc |
Здесь все было просто. И последний фикс
| Code: | SetHotkeyAction /K:W /H:BS "HBarUndo" |
Иначе клавиша Win чудила с ключами /DM /S, скорее всего из-за последнего.
Ну вот, пока так. Остальные испытания чуть позже. Кстати, WinRedraw(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
|