Orion9

|
Posted: Tue Oct 28, 2025 13:51 Post subject: |
|
|
| Loopback wrote: | Ну да, с Ctrl вряд ли удастся случайно что-то утянуть  |
Ну а Гислеру что мешает сделать то же самое?
Кто не в курсе о чем речь, напоминаю ответ маэстро в этой теме.
Ну да, я торопился и забыл написать про CTRL, но что это меняет? Можно и на Shift заменить, результат будет тем же:
| Code: | Switch uMsg
Case WM_LBUTTONDOWN
If BitAND(wParam, 0x0004) Then |
Т.ч. мой вопрос остаётся в силе: ну и где здесь "случайное" перетаскивание кнопок? Что-то я его не наблюдаю.
Более того, можно было и без модификаторов обойтись, но у Гислера своя оконная процедура висит и мешает. В частности это приводит к тому, что при претаскивании кнопки на саму себя происходит ее запуск. Побороть может и получится, но будет сложно, поскольку простой выход из процедуры без вызова оригинальной приводит к другим проблемам.
| Code: | Case WM_LBUTTONDOWN
If BitAND(wParam, 0x0004) Then
MouseGetPos("x","y")
IsDrag = 0
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
Return 1
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
WinSetStyle(0x80000, 5, hWnd)
IsDrag = 0
Return 1
EndIf |
Кстати, вы заметили, что я использовал MakeInt? Руки так и чесались
В общем, хотел я по быстрому сделать модуль, ведь основная функция была уже готова, оставалось только ее разбить на блоки и внести небольшие изменения, но поскольку времени было совсем мало, процесс затянулся.
Однако удалось добиться состояния промежуточной готовности:
 Bars.aucfg | Code: | Pragma IncludeOnce
# наведение на главную панель
ControlSetHint /F /D:50 28 "HBarShowHint"
Global gDragIndex, gDropIndex
Global gHBarButtons = 0, gHBarDivs = 0
Global gHBarUpdSec = 2, gHBarVerb
Global gHBarName, gHBarFile, gHBarMap = List(), gHBarTxt, gHBarWincmd
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
Static drag_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32646), _
stop_system = DllCall("LoadCursor", "Ptr", 0, "Ptr", 32648), _
drag_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 22), _
stop_cursor = DllCall("LoadCursor", "Ptr", hTotal, "Ptr", 21)
Switch uMsg
Case WM_LBUTTONDOWN
If BitAND(wParam, MK_CONTROL) Then
MouseGetPos("x","y")
IsDrag = 0
If DllCall("DragDetect", "hwnd", hWnd, "int64", MakeInt(y, x, 2)) Then
IsDrag = 1
WinSetStyle(0x80000, 3, hWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hWnd, "ptr", 0, "byte", 128, "dword", 2)
gDragIndex = HBarGetIdx()
#Return 1
EndIf
EndIf
Case WM_LBUTTONUP
If IsDrag = 1 Then
gDropIndex = HBarGetIdx()
WinSetStyle(0x80000, 5, hWnd)
SetHintParam("ShowHint", "Font", 17, "Arial")
SetHintParam("ShowHint", "BackColor", 0xFF0000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
If WinFromPoint() = hWnd Then
ShowHint("Button Index: " & gDragIndex & " To Index: " & gDropIndex, "", "", 3000, 1)
Else
#ShowHint("Drag operation aborted, "", "", 3000, 1)
EndIf
Sleep(50)
SetHintParam("ShowHint", "Reload")
IsDrag = 0
#Return 1
EndIf
Case WM_MOUSEMOVE
If IsDrag = 1 And BitAND(wParam, MK_LBUTTON) Then
If WinFromPoint() = hWnd Then
DllCall("SetCursor", "Ptr", drag_cursor)
Else
DllCall("SetCursor", "Ptr", stop_cursor)
EndIf
EndIf
EndSwitch
Return DllCall("CallWindowProcW", _
"ptr", gHBarWndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func HBarShowHint()
# состояние Ctrl
Local bMap = IsPressed(0x11)
# состояние CapsLock и Shift
If Not bMap Then
If BitAND(DllCall("GetKeyState", "int", 0x14, "short"), 1) = 0 Then
If Not IsPressed(0x10) Then Return
EndIf
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
gHBarFile = HBarGetFile()
If Not FileExist(gHBarFile) Then Return "Файл панели не найден " & gHBarFile
# загрузка панели
HBarLoad()
EndIf
# индекс кнопки под курсором
gDragIndex = HBarGetIdx()
If Not gDragIndex Then Return "Не удалось определить индекс кнопки"
Return HBarGetHint(bMap)
EndFunc
Func HBarGetFile()
Local bar, txt
# информация о файле панели в wincmd.ini
IniRead 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 = COMMANDER_PATH & "\" & txt
EndIf
Return bar
EndFunc
Func HBarLoad()
# загрузка файла в массив
Local aBar = List()
aBar.LoadFromFile(gHBarFile)
# количество кнопок в файле
Local nCount = 0
IniRead nCount %gHBarFile% "Buttonbar" "Buttoncount" 0
# обнуление счетчиков
gHBarDivs = 0
gHBarButtons = 0
# локальные переменные
Local j, key, val, found, oButton = Map(), oCmd = Map()
# поиск кнопок и команд
For j = 0 To aBar.Count - 1
found = 0
If StrLeft(aBar[j], 6) = "button" Then
found = 1
ElseIf StrLeft(aBar[j], 3) = "cmd" Then
found = 2
EndIf
If found > 0 Then
key = StrLower(StrPart(aBar[j], "=", 1))
val = StrLen(StrPart(aBar[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
gHBarMap.Add(0)
EndIf
Next
Free(aBar, oButton, oCmd)
# карта панели
gHBarTxt = auCRLF & auCRLF & "Loaded: " & gHBarFile & 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()
# дескриптор монитора окна ТС
Local hMon = DllCall("MonitorFromWindow", "hwnd", AUTORUN_TCHANDLE, "dword", 2)
# информация о масштабировании экрана
Local nScale = 0, bRes
bRes = DllCall("Shcore.dll\GetScaleFactorForMonitor", "hwnd", hMon, "dword*", @nScale)
# буфер для структуры 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 x, y, w, h, mx, my, idx, row, rows, rowh, bar, txt, b, extra
# координаты и размеры окна панели
WinGetPos("x", "y", "w", "h", hBarWnd)
# координаты указателя мыши
MouseGetPos("mx", "my")
# чтение информации о высоте кнопок
IniRead b %COMMANDER_INI% "Buttonbar" "Buttonheight"
# масштабирование экрана
If nScale > 0 Then b = Round(b*nScale/100,0)
# количество рядов кнопок на панели
rows = Floor(h/b)
# If rows = 0 Then Return "Error number of rows = 0"
# количество дополнительных пикселей
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
# индекс кнопки в ряду
If gHBarDivs = 0 Then
idx = (Floor((mx - x)/b) + 1) + (row-1)*(Floor(w/b))
Else
j = 1
idx = 0
For i = 0 To gHBarMap.Count - 1
cx += (gHBarMap[i] = 0 ? div : b)
ex = j*w - cx
If i + 1 <= gHBarMap.Count - 1 Then
If ex < (gHBarMap[i+1] = 0 ? div : b) Then
cx += ex
j += 1
EndIf
Else
cx += ex
EndIf
If cx >= tx Then
idx = i + 1
Break
EndIf
Next
EndIf
# дополнительная информация
gHBarVerb = "mouse=" & mx & ", " & my & auCRLF & _
"bar=" & x & ", " & y & ", " & w & ", " & h & auCRLF & _
"map=" & tx & ", " & cx & auCRLF & _
"row=" & row & " of " & rows & auCRLF & _
"height=" & rowh & " (" & extra & ")" & auCRLF & _
"buttons=" & gHBarButtons & " + " & gHBarDivs & " divs" & auCRLF & _
"width=" & b & ", " & div & auCRLF & _
"mon=" & HMon & " scale=" & nScale & "%"
Return idx
EndFunc
Func HBarGetHint(bMap)
# чтение информации о кнопке из .bar фйла
Local sMenu, sButton, sCmd, sParam, sPath, sIcon
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, "TToolTip")
If hTip > 0 Then DllCall("DestroyWindow", "handle", hTip)
# возврат текста
Return gHBarVerb & auCRLF & _
"" & auCRLF & _
"index=" & gDragIndex & " of " & gHBarButtons+gHBarDivs & auCRLF & _
"menu=" & sMenu & auCRLF & _
"button=" & sButton & auCRLF & _
"cmd=" & sCmd & auCRLF & _
"param=" & sParam & auCRLF & _
"path=" & sPath & auCRLF & _
"iconic=" & sIcon & (bMap ? gHBarTxt : "")
EndFunc |
Сейчас подсказка вызывается по Ctrl, Shift и CapsLock. Ctrl добавляет карту панели и имеет возможность перетаскивания кнопок. Пока при перетаскивании показываются только индексы опрации. Пересобрать панель будет делом техники, но сначала нужно добавить дополнительные проверки и провести больше тестов. Например усовершенствовать блок с масштабированием экрана и оптимизировать количество вызовов. Также нужно что-то придумать, как обрабатывать временно загруженную панель, файл которой не находится в корне ТС или подкаталоге \Bars. Сейчас такая панель работать не будет.
| Loopback wrote: | | Думаю, можно и полностью исправить, но тогда придется отказаться от создания диалога с помощью DialogBox и полностью создать свое окно с нуля. |
А откуда уверенность, что это поможет?
| Loopback wrote: | | Что-то может быть, конечно, но проблема с потоком маловероятно что связана с ним. |
Согласен. Я больше имел в виду дурацкие приколы с загрузкой графического объекта.
| Loopback wrote: | | Из плагинов статистики нет, слишком много затрат для реализации. |
То, что некоторые вещи реализовать сложно, это понятно. Но какие сложности с SetHotkeyAction? Разве во время парсинга вы не можете собрать статистику, что привязано к этому вызову? У меня много модулей, и в каждом что-то висит на SetHotkeyAction. Со временем забываешь, что именно. Можно конечно простым поиском по всем файлам найти, но ведь лень же да и не удобно это. Куда лучше было бы вызвать GetState("SetHotkeyAction") и всё увидеть. |
|