| View previous topic :: View next topic |
| Author |
Message |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Tue Sep 22, 2026 22:31 Post subject: |
|
|
| Orion9 wrote: | | Вы бы гифку записали, а то не понятно о чем речь. |
Я разобрался, но там все достаточно печально и кажется корректно не решаемо. Вот такой код я прописал где требуется обновление ПИ:
| Code: | # Обновляем текущую панель инструментов для смены иконки
# Updating current toolbar to change the icon
SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
SendCommand cm_ReloadBarIcons
# Sleep(auX64 ? 0 : 10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(1) |
Но теперь надо и пользовательские команды ТС через Авторан переделывать. Так как любая команда cm_ReloadBarIcons вызывает дерганье на ТС32 Вин11.
Дак вот, почему я в унынии. Видите у меня закомментирована команда Слип? А без нее в ТС32 все равно есть небольшое подергивание. А с ней подергивания ПИ нет совсем, как в ТС64, но дергается иконка в трее То-есть избавится полностью от подергивания не получится.
Поэтому вроде и ни к чему возиться с гифкой. Тем более увидеть подергивание очень просто. Выполните команду cm_ReloadBarIcons в обоих разрядностях через командную строку ТС. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Wed Sep 23, 2026 13:40 Post subject: |
|
|
AkulaBig
Продолжил общаться с болваном. Можно еще через PostMessage сделать, о чем сразу не подумал
 Hidden text Для отправки комбинации Ctrl + Shift + Левый клик мыши в конкретное фоновое окно через PostMessage не нужно отправлять нажатия клавиш Ctrl и Shift по отдельности.
В Win32 API клики мыши обрабатывают модификаторы гораздо проще: в сообщение WM_LBUTTONDOWN передается специальная битовая маска, которая сообщает окну, что в момент клика клавиатурные клавиши Ctrl и Shift уже были зажаты.
Вот готовый и чистый код на AutoHotkey v2:
| Code: | #Requires AutoHotkey v2.0
; Пример: по нажатию F2 отправляем Ctrl+Shift+Клик в окно Блокнота по координатам X:300, Y:200
F2::DllPostCtrlShiftClick(WinExist("ahk_exe notepad.exe"), 300, 200)
/**
* Симулирует комбинацию Ctrl + Shift + Левый клик мыши в фоновом окне
* @param {Integer} hwnd - Дескриптор (HWND) целевого окна
* @param {Integer} x - Координата X внутри окна (в пикселях)
* @param {Integer} y - Координата Y внутри окна (в пикселях)
*/
DllPostCtrlShiftClick(hwnd, x, y) {
if (!hwnd)
return
; Константы сообщений мыши
static WM_LBUTTONDOWN := 0x0201
static WM_LBUTTONUP := 0x0202
; Битовые маски модификаторов для wParam
static MK_LBUTTON := 0x0001
static MK_CONTROL := 0x0008
static MK_SHIFT := 0x0004
; Объединяем флаги для нажатия (ЛКМ + Ctrl + Shift)
wParamDown := MK_LBUTTON | MK_CONTROL | MK_SHIFT
; Объединяем флаги для отжатия (только Ctrl + Shift, так как ЛКМ уже отпущена)
wParamUp := MK_CONTROL | MK_SHIFT
; Упаковываем координаты X и Y в один 32-битный параметр lParam
; Y уходит в старшие 16 бит (сдвиг << 16), X остается в младших 16 битах
lParam := (y << 16) | (x & 0xFFFF)
; 1. Посылаем нажатие ЛКМ с зажатыми Ctrl и Shift
DllCall("user32\PostMessage", "Ptr", hwnd, "UInt", WM_LBUTTONDOWN, "Ptr", wParamDown, "Ptr", lParam)
Sleep(30) ; Короткая пауза, чтобы окно успело зафиксировать клик
; 2. Посылаем отжатие ЛКМ
DllCall("user32\PostMessage", "Ptr", hwnd, "UInt", WM_LBUTTONUP, "Ptr", wParamUp, "Ptr", lParam)
}
|
## Как это работает:
1. Флаги wParam: Вместо того чтобы «заставлять» операционную систему думать, что пользователь нажал физические клавиши, мы напрямую передаем окну готовый статус: MK_CONTROL | MK_SHIFT. Окно считывает этот параметр и сразу обрабатывает событие как комплексную комбинацию.
2. Координаты lParam: Важно помнить, что при использовании PostMessage координаты X и Y отсчитываются от левого верхнего угла клиентской области самого окна, а не от экрана. То есть 0, 0 — это самый крайний левый верхний пиксель внутри выбранной программы.
Но из-за того, что lParam в сообщении указывает координаты клиентской области, реализация на Autorun немного громоздкая и, возможно, не везде будет уместна. Т.е. вместо
| Code: | SendLCtrlViaDll()
Sleep(10)
MouseClick()
Sleep(10)
SendLCtrlViaDll("up") |
в моем случае будет
| Code: | Local x, y
MouseGetPos("x","y")
Local hWnd = WinFromPoint(x,y)
Static buf = Buffer(8) # POINT
buf.Zero()
buf.SetNum(0, "long", x, "long", y)
DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
x = buf.GetNum(0)
y = buf.GetNum(4)
Local MousePos = MakeInt(x,y)
PostMessage(hWnd, 0x0201, 0x0008, MousePos)
PostMessage(hWnd, 0x0202, 0x0008, MousePos) |
Но зато слип не нужен (у меня и так работает), да и сама возможность интересная, может кому пригодится.
Ну я понял теперь о чем вы говорите. Это старая проблема. Лечится она (по крайне мере у меня) через WinRedraw(2). Полная версия примерно такая. Не знаю поможет вам или нет, но других вариантов по сути нет. Иконка на панели задач будет исчезать и появляться.
| Code: | SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
SendCommand(2901, 0, 1) #cm_VisButtonBar
SendCommand(2901, 0, 1) #cm_VisButtonBar
Sleep(10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(2) |
|
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Wed Sep 23, 2026 19:30 Post subject: |
|
|
| Orion9 wrote: | | Ну я понял теперь о чем вы говорите. Это старая проблема. |
Это проблема ТС. Так что до конца нерешаемая. Сейчас более-менее приемлемый вариант. В коде на Авторан я везде так прописал. Но и в командах пользователя ТС, которые никак не связаны с Авторан, работает также с подергиванием. Получается их надо переписывать с использованием Авторан. Чет желания нет. Как и писать Гислеру.
| Orion9 wrote: | | в моем случае будет |
Я уже запутался. Это замена ControlSetMouseAction /L /K:C /K:S 0 "CompareToolShowMenu"? К чему этот код? |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Thu Sep 24, 2026 13:45 Post subject: |
|
|
AkulaBig
Работает хук, проверил сейчас. Перехватывает клавишу CTRL глобально.
 Hidden text | Code: | Global WH_KEYBOARD_LL = 13
Global MyKeyboard = Callback("LowLevelKeyboardProc", "int;wparam;lparam")
RunThread("KeyboardHook")
Func KeyboardHook()
Local hHook
hHook = DllCall("SetWindowsHookEx", _
"Int", WH_KEYBOARD_LL, _
"Ptr", MyKeyboard.Ptr, "Ptr", 0, "UInt", 0, "Ptr")
Local buf = Buffer(auX64 ? 56 : 28)
While 1
DllCall("GetMessage", "ptr", buf.ptr, "hwnd", -1, "uint", 0, "uint", 0)
DllCall("TranslateMessage", "ptr", buf.ptr)
DllCall("DispatchMessage", "ptr", buf.ptr)
Wend
Free(buf)
EndFunc
Func LowLevelKeyboardProc(nCode, wParam, lParam)
Static c = 0, up = 0, T2
Static LLKHF_INJECTED = 0x00000010, HC_ACTION = 0
Static WM_KEYDOWN = 0x0100, WM_KEYUP = 0x0101, VK_LCONTROL = 0xA2
# Передача сообщения следующему хуку
If nCode <> 0 Then
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "Ptr", lParam, "Ptr")
EndIf
Local obj = Buffer(24, lParam)
# Извлечение из структуры MSLLHOOKSTRUCT
vkCode = obj.GetNum(0, "UInt")
uFlags = obj.GetNum(8, "UInt")
# Перехват только если окно ТС активно
If (vkCode = VK_LCONTROL) And WinGetState(4) Then
If wParam = WM_KEYDOWN Then
c += 1
# Отключение CTRL для ТСх64 через 10 повторов
If auX64 And c > 8 Then
Global gHintCaps = false
Return 1
EndIf
ElseIf wParam = WM_KEYUP Then
c = 0
up += 1
If up = 1 Then T2 = GetUptime()
If auX64 Then Global gHintCaps = true
If up > 1 Then
up = 0
If Round(GetUptime() - T2, 0) < 400 Then
SendCommand cm_About
EndIf
EndIf
EndIf
# Return 1 # Заблокировать для системы
EndIf
# Передача управления следующему хуку в цепочке
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "lParam", lParam, "Ptr")
EndFunc |
Возможности открылись неплохие. В частности удалось обойти абсолютно дурацкий косяк ТСх64 с модификаторами при вызове подсказки на панели, когда нажатие CTRL скрывает подсказку или не дает ей появиться. Чтобы заставить ее работать, CTRL отключается через 10 повторов и меняет флаг подсказки gHintCaps на false, который отвечает за MediaInfo Inform. Это костыль, конечно, но работает.
Второй бонус - двойное нажатие CTRL. Сейчас просто вызывается окно About, но можно сделать что-то и поинтереснее (уже, кстати, есть идея).
| AkulaBig wrote: | | Я уже запутался. Это замена ControlSetMouseAction /L /K:C /K:S 0 "CompareToolShowMenu"? К чему этот код? |
Вы хотели, чтобы назначенная через ControlSetMouseAction функция пропускала свою комбинацию. PostMessage позволяет это сделать. Но я вчера толком не проверил, по факту там не нужны модификаторы - и без них работает.
 Hidden text | Code: | Func PostMouseClick()
Local x, y
# Константы сообщений мыши
Static WM_LBUTTONDOWN = 0x0201, _
WM_LBUTTONUP = 0x0202, _
WM_LBUTTONDBLCLK = 0x0203, _
WM_RBUTTONDOWN = 0x0204, _
WM_RBUTTONUP = 0x0205, _
WM_RBUTTONDBLCLK = 0x0206, _
WM_MBUTTONDOWN = 0x0207, _
WM_MBUTTONUP = 0x0208, _
WM_MBUTTONDBLCLK = 0x0209
# Битовые маски модификаторов для wParam
Static MK_LBUTTON = 0x0001, _
MK_MBUTTON = 0x0010, _
MK_RBUTTON = 0x0002, _
MK_CONTROL = 0x0008, _
MK_SHIFT = 0x0004
# Дескриптор окна под курсором
MouseGetPos("x","y")
Local hWnd = WinFromPoint(x,y)
# Буфер для структуры POINT
Static buf = Buffer(8)
buf.Zero()
# Координаты мыши в клиентской области hWnd
buf.SetNum(0, "long", x, "long", y)
DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
x = buf.GetNum(0)
y = buf.GetNum(4)
# Упаковка координат в 32-битный параметр lParam
Local lParam = MakeInt(x,y)
# Упаковка координат в 32-битный параметр lParam
#Local wParam = BitOR(MK_CONTROL, MK_SHIFT)
wParam = 0
PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam)
Sleep(25)
PostMessage(hWnd, WM_LBUTTONUP, wParam, lParam)
EndFunc
|
Т.е. wParam может быть 0.
В функцию CompareToolShowMenu можно добавить переключатель для выполнения кода (показа меню) или пропуска комбинации вызовом PostMouseClick(). |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Thu Sep 24, 2026 14:38 Post subject: |
|
|
| Orion9 wrote: | | пропуска комбинации вызовом PostMouseClick() |
Добавил код из PostMouseClick. Поставил wParam=12. Кнопка вкл/выкл хоткея перестала переключаться. То-есть нажимаю, чтобы отключить хоткей, а кнопка возвращается в предыдущее состояние. То-есть хоткей остается включенным. И отключение вызова меню не работает. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Fri Sep 25, 2026 13:16 Post subject: |
|
|
И еще один хук на Autorun, в этот раз WH_MSGFILTER. Вы спросите на кой? Не знаю. Но пока я их все не сделаю, не успокоюсь
 Hidden text | Code: | RunThread("MsgFilterHook")
Func MsgFilterHook()
Local hHook
Local WH_MSGFILTER = 6
Local MsgFilter = Callback("MessageProc", "int;wparam;lparam")
Local hTotal = DllCall("GetModuleHandleW", "Ptr", 0, "handle")
Local uThreadId = DllCall("GetCurrentThreadId", "UInt") #AUTORUN_THREADID
Local hAutoWdx = DllCall("GetModuleHandleW", "Wstr", ("Autorun.wdx" & (auX64 ? "64" : "")), "handle")
hHook = DllCall("SetWindowsHookExW", _
"Int", WH_MSGFILTER, _
"Ptr", MsgFilter.Ptr, "Ptr", hAutoWdx, "UInt", 0, "Ptr")
OutputDebugString("WH_MSGFILTER: " & SYSERROR & " " & SYSERRORTEXT)
Local buf = Buffer(auX64 ? 56 : 28)
While 1
DllCall("GetMessage", "ptr", buf.ptr, "hwnd", -1, "uint", 0, "uint", 0)
DllCall("TranslateMessage", "ptr", buf.ptr)
DllCall("DispatchMessage", "ptr", buf.ptr)
Wend
Free(buf)
EndFunc
Func MessageProc(nCode, wParam, lParam)
If nCode < 0 Then
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "Ptr", lParam, "Ptr")
EndIf
Local obj = Buffer(auX64 ? 56 : 28, lParam)
# Извлечение из MSG
Local hWnd = obj.GetNum(0, "hwnd")
Local uMsg = obj.GetNum(auX64 ? 8 : 4, "UInt")
Local wParam1 = obj.GetNum(auX64 ? 16 : 8, "Ptr")
Local lParam1 = obj.GetNum(auX64 ? 24 : 12, "Ptr")
Static cls = Buffer(512)
cls.Zero()
# Получение имени класса
DllCall("GetClassName", "Ptr", hWnd, "Ptr", cls.Ptr, "Int", 256)
OutputDebugString("Class: " & cls.GetStr() & " uMsg: " & uMsg & " wParam: " & wParam1 & " lParam: " & lParam1)
# Передача следующему хуку
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "Ptr", lParam, "Ptr")
EndFunc |
| AkulaBig wrote: | | Добавил код из PostMouseClick. Поставил wParam=12. |
Зачем? Я же написал выше, что работает без модификаторов, поэтому и оставил 0 для wParam. И там, кстати, евклидова математика в действии: 12 не равно 0x12
Все работает. Один раз кликаю - появляется вертикальное меню, второй раз кликаю - выделяется группа файлов на панели (если клик, конечно, был по панели). Все как положено.
| Code: | ControlSetMouseAction /L /K:C /K:S 0 "CompareToolShowMenu"
Func CompareToolShowMenu()
static mode = 1, bar = COMMANDER_PATH & "\Vertical.bar"
mode = mode = 1 ? 2 : 1
If mode = 2 Then
ShowPopupMenu /D %bar%
Else
PostMouseClick()
EndIf
EndFunc
|
|
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Fri Sep 25, 2026 14:44 Post subject: |
|
|
| Orion9 wrote: | | Вы спросите на кой? |
Вы на меня не обращайте внимания. фонтанируйте, фонтанируйте. Щас не надо, а через 3 месяца будет надо.
| Orion9 wrote: | | оставил 0 для wParam |
Да с этим значением я сразу попробовал. А потом попробовал поэкспериментировать.
| Orion9 wrote: | | Все работает. |
Сейчас стало структурированно, может и у меня заработает.
Еще Флешера на оф. форуме загрузил этим. Может что получится общими усилиями.
Добавлено спустя 42 минуты:
Не. Код PostMouseClick() просто не дает переключить кнопку на отключение меню. То-есть есть кнопка на ПИ ТС. Когда у ней состояние 1, меню показывается. При 0 меню не должно показываться. Ваш код не дает кнопке переключиться. Нажимаю на 1, мелькает 0 и снова показывает 1. На оф. форуме я код выложил. Можете там посмотреть, если мою сборку качать не охота. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Sat Sep 26, 2026 10:01 Post subject: |
|
|
| AkulaBig wrote: | | фонтанируйте, фонтанируйте |
Дв я не против, в целом. Но сначала пусть Гислер флягу баварского отгрузит для поддержания фонтана идей. Хотя чтобы сдалать ТС снова великим одной фляжкой ему не обойтись.
| AkulaBig wrote: | | Ваш код не дает кнопке переключиться |
А причем здесь кнопка? Это ведь другой вопрос. Главное чтобы фуцнкия работала, а кнопку можно сдалать по разному. Нвпример
| Code: | gCompareToolMenu = 0
ControlSetMouseAction /L /K:C /K:S 0 "CompareToolShowMenu"
Func CompareToolShowMenu()
Static bar = COMMANDER_PATH & "\Vertical.bar"
If gCompareToolMenu Then
ShowPopupMenu /D %bar%
Else
PostMouseClick()
EndIf
EndFunc
RegisterCommand 60065 "CompareToolMenu"
Func CompareToolMenu()
gCompareToolMenu = not gCompareToolMenu
EndFunc
|
| Code: | TOTALCMD#BAR#DATA
60065
%COMMANDER_EXE%
CompareToolMenu
1
-1
|
|
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Sat Sep 26, 2026 10:22 Post subject: |
|
|
По такому алгоритму у меня и сделано. PostMouseClick() не дает переключить кнопку. То-есть я щелкаю по кнопке, она на мгновенье переключается по PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam), а по PostMessage(hWnd, WM_LBUTTONUP, wParam, lParam) возвращается назад. Я в своих плагинах обычно только на отжатие действие вешаю. На нажатие и отжатие очень редко. Оставил у вас только отжатие, кнопка переключается, но меню не отключается. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Sat Sep 26, 2026 13:14 Post subject: |
|
|
И еще один хук на Autorun, в этот раз WH_KEYBOARD, тот, что выше WH_KEYBOARD_LL и работает с очередью потока. Я же говорю, пока все их не сделаю, не успокоюсь
Ладно, шучу. Это был последний хук. Или может быть предпоследний.
 Hidden text | Code: | Func KeyboardHook()
Local hHook
Local WH_KEYBOARD = 2
Local gKeyboard = Callback("KeyboardProc", "int;wparam;lparam")
Local processID = 0
Local mainThreadID = DllCall("user32\GetWindowThreadProcessId", "Ptr", AUTORUN_TCHANDLE, "UInt*", @processID, "UInt")
Local hAutoWdx = DllCall("GetModuleHandleW", "Wstr", ("Autorun.wdx" & (auX64 ? "64" : "")), "handle")
hHook = DllCall("SetWindowsHookEx", _
"Int", WH_KEYBOARD, _
"Ptr", gKeyboard.Ptr, "Ptr", hAutoWdx, "UInt", mainThreadID, "Ptr")
OutputDebugString("WH_KEYBOARD: " & SYSERROR & " " & SYSERRORTEXT)
Local buf = Buffer(auX64 ? 56 : 28)
While 1
DllCall("GetMessage", "ptr", buf.ptr, "hwnd", -1, "uint", 0, "uint", 0)
DllCall("TranslateMessage", "ptr", buf.ptr)
DllCall("DispatchMessage", "ptr", buf.ptr)
Wend
Free(buf)
EndFunc
Func KeyboardProc(nCode, wParam, lParam)
Static c = 0, up = 0, T2
Static HC_ACTION = 0
# Передача сообщения следующему хуку
If nCode < 0 Then
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "Ptr", lParam, "Ptr")
EndIf
OutputDebugString("nCode: " & nCode & " wParam: " & wParam & " lParam: " & lParam)
Local bUp, bRpt
If auX64 Then
bUp = lParam > 2147483647 ? 1 : 0
Else
bUp = BitAND(BitShift(lParam,31), 1)
EndIf
#bUp = BitAND(BitShift(lParam,16), 0x8000) = 0x8000 ? 1 : 0
#bRpt = BitAND(BitShift(lParam,16), 0x4000) = 0x4000 ? 1 : 0
# Перехват CTRL
If wParam = 0x11 Then
OutputDebugString("Repeat : " & BitAND(lParam, 0xffff) & " bRpt: " & bRpt & " bUp: " & bUp)
If Not bUp Then
c += 1
# Отключение CTRL для ТСх64 через 10 повторов
If auX64 And c > 8 Then
Global gHintCaps = false
Return 1
EndIf
Else
c = 0
up += 1
If up = 1 Then T2 = GetUptime()
If auX64 Then Global gHintCaps = true
If up > 1 Then
up = 0
If Round(GetUptime() - T2, 0) < 600 Then
#SendCommand cm_About
Local sPath = GetCurrentPath(ItemAtCursor("panel"))
Local sName = sPath & ItemAtCursor("name")
MsgBox("Файл под курсором: " & sName)
EndIf
EndIf
EndIf
EndIf
# Передача управления следующему хуку в цепочке
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "lParam", lParam, "Ptr")
EndFunc
|
Здесь хук привязывается к главному потоку ТС, поэтому нет необходимости проверять авктивно ли окно приложения, события вне этого потока все-равно не будут обрабатываться.
В остальном логика поторяется, но есть замечание по 64-битной версии. Сдвиг битов в этой версии не работает. То ли это проблема самого Autorun, то ли я чего-то не понял, но в общем не стал я с этим разбирать и сделал проверку последнего бита по числу. Но в ТСх32 эти строки все же работают
| Code: | bUp = BitAND(BitShift(lParam,16), 0x8000) = 0x8000 ? 1 : 0
bRpt = BitAND(BitShift(lParam,16), 0x4000) = 0x4000 ? 1 : 0 |
Самое главное отличие в процедуре обработчика - двойной CTRL вызывает не окно About, а полное имя файла под курсором. Это можно использовать по полной программе, когда нужно получить дополнительную или расширенную информацию о файле, помимо стандартной подсказки ТС. Курсор висит над файлом, отображается обычная подсказка, двойное нажатие Ctrl в этот момент отобразит другую подсказку, или все что угодно.
| AkulaBig wrote: | | Оставил у вас только отжатие, кнопка переключается, но меню не отключается. |
Я не знаю, что у вас не работает. У меня код выше работает как и ожидается, т.е. при старте ТС файлы при клике по панели с зажатым Ctrl+Shift выделяются. После нажатия на кнопку для переключения меню, отображается меню из вертикальной панели. Повторные нажатия пследовательно переключают этот функционал.
У вас моя кнопка работает? |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Sat Sep 26, 2026 13:38 Post subject: |
|
|
| Orion9 wrote: | | У вас моя кнопка работает? |
Проверил вашу кнопку в полном наборе. Вроде работает. Буду разбираться. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Sat Sep 26, 2026 17:12 Post subject: |
|
|
Orion9
Проблема понятна. PostMouseClick() не дает переключить кнопку. Все-же прошу вас посмотреть, почему при ЛКМ безо всяких модификаторов PostMouseClick() срабатывает? |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1259
|
(Separately) Posted: Sat Sep 26, 2026 20:43 Post subject: |
|
|
В общем, вот так оно должно где-то выглядеть, а точнее как в лучших домах России и Швейцарии.
 Hidden text
Но это только прототип, который нужно дорабатыват. Пока двойной Ctrl не всегда срабатывает и удержание иногда проскальзывает, но уже прикольненько.
Ниже полный код хука и подсказки, но для работы подсказки нужны дополнительные функции из модуля MediaInfo.aucfg.
 Hidden text | Code: | RunThread("KeyboardHook")
Func KeyboardHook()
Local hHook
Local WH_KEYBOARD = 2
Local gKeyboard = Callback("KeyboardProc", "int;wparam;lparam")
Local processID = 0
Local mainThreadID = DllCall("user32\GetWindowThreadProcessId", "Ptr", AUTORUN_TCHANDLE, "UInt*", @processID, "UInt")
Local hAutoWdx = DllCall("GetModuleHandleW", "Wstr", ("Autorun.wdx" & (auX64 ? "64" : "")), "handle")
hHook = DllCall("SetWindowsHookEx", _
"Int", WH_KEYBOARD, _
"Ptr", gKeyboard.Ptr, "Ptr", hAutoWdx, "UInt", mainThreadID, "Ptr")
OutputDebugString("WH_KEYBOARD: " & SYSERROR & " " & SYSERRORTEXT)
Local buf = Buffer(auX64 ? 56 : 28)
While 1
DllCall("GetMessage", "ptr", buf.ptr, "hwnd", -1, "uint", 0, "uint", 0)
DllCall("TranslateMessage", "ptr", buf.ptr)
DllCall("DispatchMessage", "ptr", buf.ptr)
Wend
Free(buf)
EndFunc
Func KeyboardProc(nCode, wParam, lParam)
Static c = 0, up = 0, T2, T1
Static HC_ACTION = 0
# Передача сообщения следующему хуку
If nCode < 0 Then
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "Ptr", lParam, "Ptr")
EndIf
#OutputDebugString("nCode: " & nCode & " wParam: " & wParam & " lParam: " & lParam)
Local bUp, bRpt
If auX64 Then
bUp = lParam > 2147483647 ? 1 : 0
Else
bUp = BitAND(BitShift(lParam,31), 1)
EndIf
#bUp = BitAND(BitShift(lParam,16), 0x8000) = 0x8000 ? 1 : 0
#bRpt = BitAND(BitShift(lParam,16), 0x4000) = 0x4000 ? 1 : 0
# Перехват CTRL
If wParam = 0x11 Then
#OutputDebugString("Repeat : " & BitAND(lParam, 0xffff) & " bRpt: " & bRpt & " bUp: " & bUp)
If Not bUp Then
c += 1
# Отключение CTRL для ТСх64 через 10 повторов
If auX64 And c > 8 Then
Global gHintCaps = false
Return 1
EndIf
Else
c = 0
up += 1
#OutputDebugString("c : " & c & " up: " & up)
If up <= 1 Then T2 = GetUptime()
If auX64 Then Global gHintCaps = true
T1 = Round(GetUptime() - T2, 0)
If up > 1 Then
up = 0
#T1 = Round(GetUptime() - T2, 0)
If T1 < 1000 Then
Local sPath = GetCurrentPath(ItemAtCursor("panel"))
Local sName = sPath & ItemAtCursor("name")
RunThread("MediaInfoHint", sName)
#MsgBox("Файл под курсором: " & sName)
EndIf
EndIf
EndIf
#OutputDebugString("c : " & c & " up: " & up & " T2: " & T2 & " T1: " & T1)
EndIf
# Передача управления следующему хуку в цепочке
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "wParam", wParam, "lParam", lParam, "Ptr")
EndFunc
Func MediaInfoHint(Filename)
Local hWin = MediaInfoTip(Filename)
# удаление подсказки тотала
Local hTip = WinFind(0, "TToolTip")
If hTip > 0 Then SendMessage(hTip, 0x0010, 0, 0)
Local buf = Buffer(auX64 ? 56 : 28)
While 1
DllCall("GetMessage", "ptr", buf.ptr, "hwnd", hWin, "uint", 0, "uint", 0)
DllCall("TranslateMessage", "ptr", buf.ptr)
DllCall("DispatchMessage", "ptr", buf.ptr)
Wend
Free(buf)
EndFunc
Func MediaInfoTip(sFile)
If Not FileExist(sFile) Then
ShowHint("Файл не существует " & sFile)
Return
Endif
If StrPos(FileGetAttr(sFile), "D") Then
ShowHint("Каталог " & sFile)
Return
Endif
Static sLib = auX64 ? gMediaInfoX64 : gMediaInfoX32
Static hLib = DllCall("LoadLibrary", "wstr", sLib, "ptr")
If hLib = 0 Then
ShowHint("Error LoadLibrary " & sLib)
Return
EndIf
Static sPath = FileGetDir(sLib)
Static sLang ="file://" & sPath & "\ru.csv"
Static pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
Static pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
Static pGet = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Get", "Ptr")
Static pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
Static pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
Static pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")
Local hMI = DllCall(pNew, "Ptr")
If hMI = 0 Then
ShowHint("MediaInfo.dll couldn't create new object")
Return
Endif
If DllCall(pOpen, 'ptr', hMI, "wstr", sFile, "uint") <> 1 Then
DllCall(pDel, "Ptr", hMI)
Return ShowHint("MediaInfo.dll couldn't open file " & sFile)
EndIf
Local sMI
DllCall(pOpt, "Ptr", hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")
DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", sLang, "Wstr")
DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", "Inform", "Wstr")
Local lst = List()
lst.Text = DllCall(pInfo, "Ptr", hMI, "Uint", 0, "Wstr")
For line in lst
sMI &= FixSpaces(line) & auCRLF
Next
Free(lst)
DllCall(pDel, "Ptr", hMI)
If gDurationBaloon Then
gBTip = CreateBaloonTip("MediaInfo", 1, 300)
If gBTip = 0 Then Return MsgBox("Не удалось создать окно подсказки BaloonTip")
EndIf
If StrTrim(sMI) = "" Then sMI = "нет данных"
ShowMediaHint(sMI)
Return gBTip
EndFunc
|
| AkulaBig wrote: | | Все-же прошу вас посмотреть |
Что и где посмотреть то? Вы же видите - все работает. Значит у вас код усложнен, раз где-то перестает работать.
| AkulaBig wrote: | | почему при ЛКМ безо всяких модификаторов PostMouseClick() срабатывает? |
Не знаю, но оно туда вообще не должно заходить, только с модификаторами, указанными в ControlSetMouseAction (и то если переменная gCompareToolMenu = false). |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 607
|
(Separately) Posted: Sat Sep 26, 2026 22:25 Post subject: |
|
|
| Orion9 wrote: | | Значит у вас код усложнен |
Ну понятно, что у меня код не такой простейший и никакой gCompareToolMenu и быть не может. Надо-же где-то хранить ее состояние. Но все равно алгоритм тот-же, просто с большей информативности.
| Orion9 wrote: | | Не знаю, но оно туда вообще не должно заходить |
Не должно, но почему-то перехватывает ЛКМ по кнопке.
Вот это гифку я сейчас записал!
Обратите внимание - я смог переключить состояние! Если в какую-то определенную область нажать, состояние меняется! Похоже какие-то проблемы с определением координат.
Но дальше - хуже. Состояние кнопки переключилось, но меню все равно показывается! И вот теперь у меня возникает подозрение, что bar-меню отключается, а динамическое меню, которое использую я, не отключается. Сейчас буду проверять.
Добавлено спустя 34 минуты:
Использование bar-меню ничего не изменило  |
|
| 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
|