Orion9

|
Posted: Thu Sep 17, 2026 12:31 Post subject: |
|
|
AkulaBig
Мда... C болваном можно долго играться, идей у него масса.
Зарисовка на тему однажды Гислер проснулся и включил Total Commander
 Hidden text
 И так в каждом меню Тролль завёлся под меню? Может это просто глю..? 
Код от болвана с небольшой правкой
 Hidden text | Code: | #Requires AutoHotkey v2.0
Persistent()
; 1. Путь к картинке (поддерживаются BMP, PNG, JPG)
IMAGE_PATH := "d:\Temp\Trollface.bmp"
; 2. Создаем кастомное GUI для оверлея
overlay := Gui("+AlwaysOnTop -Caption +ToolWindow +E0x08000000") ; E0x08000000 = WS_EX_NOACTIVATE (не забирает фокус)
overlay.MarginX := 0
overlay.MarginY := 0
; Добавляем картинку с вашими размерами
picCtrl := overlay.Add("Picture", "w222 h180", IMAGE_PATH)
; Привязываем действие к клику по картинке
picCtrl.OnEvent("Click", MyImageClicked)
; 3. Константы хуков
EVENT_SYSTEM_MENUPOPUPSTART := 0x0006
EVENT_SYSTEM_MENUPOPUPEND := 0x0007
WINEVENT_OUTOFCONTEXT := 0x0000
; Ставим хуки на ОТКРЫТИЕ и ЗАКРЫТИЕ меню по всей системе
callback := CallbackCreate(WinEventProc, "Fast", 7)
hHookStart := DllCall("SetWinEventHook", "UInt", EVENT_SYSTEM_MENUPOPUPSTART, "UInt", EVENT_SYSTEM_MENUPOPUPSTART, "Ptr", 0, "Ptr", callback, "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT)
hHookEnd := DllCall("SetWinEventHook", "UInt", EVENT_SYSTEM_MENUPOPUPEND, "UInt", EVENT_SYSTEM_MENUPOPUPEND, "Ptr", 0, "Ptr", callback, "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT)
WinEventProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
global overlay
if hwnd == 0
overlay.Hide()
if (WinGetClass(hwnd) == "#32768") {
if (event == EVENT_SYSTEM_MENUPOPUPSTART) {
Sleep(20) ; Ждем отрисовки оригинального меню
; Получаем координаты и размеры открывшегося чужого меню
WinGetPos(&menuX, &menuY, &menuW, &menuH, hwnd)
; --- РАСЧЕТ ПОЗИЦИИ ---
; Покажем оверлей, например, строго ПОД чужим меню
showX := menuX
showY := menuY + menuH
; Или ВНУТРИ меню вместо первых пунктов (потребуется сдвиг)
; showX := menuX + 5
; showY := menuY + 5
; Отображаем наше GUI поверх чужого процесса
overlay.Show("X" showX " Y" showY " NoActivate")
} else if (event == EVENT_SYSTEM_MENUPOPUPEND) {
; Как только чужое меню закрылось — прячем оверлей
overlay.Hide()
}
}
}
; 4. Функция, которая выполнится при клике на картинку поверх чужого меню
MyImageClicked(*) {
overlay.Hide() ; Скрываем оверлей
;WinClose("#32768") ; Принудительно закрываем чужое контекстное меню
MsgBox("Click")
}
; Снятие хуков при выходе
OnExit((*) => (
DllCall("UnhookWinEvent", "Ptr", hHookStart),
DllCall("UnhookWinEvent", "Ptr", hHookEnd),
CallbackFree(callback)
))
|
В общем, есть там варианты, но их долго проверять. Болван хорош схемами, готовый код не всегда от него работает. Более менее рабочий вариант вот этот, но его нужно дорабатывать.
 Hidden text | Code: | #Requires AutoHotkey v2.0
Persistent()
; 1. Константы Win32 API
EVENT_SYSTEM_MENUPOPUPSTART := 0x0006
EVENT_SYSTEM_MENUPOPUPEND := 0x0007
EVENT_OBJECT_FOCUS := 0x8005 ; Событие изменения фокуса (наведения мыши)
WINEVENT_OUTOFCONTEXT := 0x0000
MN_GETHMENU := 0x01E1
MY_CUSTOM_ID := 7777
; Глобальные переменные для сохранения состояния
global lastFocusedID := 0
global currentMenuHwnd := 0
global currentMenuHandle := 0
; 2. Устанавливаем один общий хук на все необходимые фазы жизни меню
callback := CallbackCreate(WinEventProc, "Fast", 7)
hHookStart := DllCall("SetWinEventHook", "UInt", EVENT_SYSTEM_MENUPOPUPSTART, "UInt", EVENT_SYSTEM_MENUPOPUPSTART, "Ptr", 0, "Ptr", callback, "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT)
hHookEnd := DllCall("SetWinEventHook", "UInt", EVENT_SYSTEM_MENUPOPUPEND, "UInt", EVENT_SYSTEM_MENUPOPUPEND, "Ptr", 0, "Ptr", callback, "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT)
hHookFocus := DllCall("SetWinEventHook", "UInt", EVENT_OBJECT_FOCUS, "UInt", EVENT_OBJECT_FOCUS, "Ptr", 0, "Ptr", callback, "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT)
WinEventProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
global currentMenuHwnd, currentMenuHandle, lastFocusedID, MY_CUSTOM_ID
; А) МЕНЮ ОТКРЫВАЕТСЯ
if (event == EVENT_SYSTEM_MENUPOPUPSTART && WinGetClass(hwnd) == "#32768") {
Sleep(15)
hMenu := DllCall("SendMessage", "Ptr", hwnd, "UInt", MN_GETHMENU, "Ptr", 0, "Ptr", 0, "Ptr")
if (!hMenu)
return
currentMenuHwnd := hwnd
currentMenuHandle := hMenu
lastFocusedID := 0 ; Сбрасываем старый фокус
; Внедряем наш кастомный пункт самым первым
DllCall("InsertMenuW", "Ptr", hMenu, "UInt", 0, "UInt", 0x0400 | 0x0000, "Ptr", MY_CUSTOM_ID, "Str", "⚡ Независимый пункт")
DllCall("DrawMenuBar", "Ptr", hwnd)
}
; Б) ПОЛЬЗОВАТЕЛЬ НАВЕЛ МЫШКУ НА ПУНКТ (ФОКУСИРОВКА СТРОКИ)
else if (event == EVENT_OBJECT_FOCUS && hwnd == currentMenuHwnd && currentMenuHandle != 0) {
; В событии EVENT_OBJECT_FOCUS параметр idChild содержит индекс (POSITION) элемента меню, на который навели мышь!
if (idChild > 0) {
menuIdx := idChild - 1 ; Переводим в zero-based индекс (0, 1, 2...)
; Получаем реальный ID элемента из хэндла меню
focusedID := DllCall("GetMenuItemID", "Ptr", currentMenuHandle, "Int", menuIdx, "UInt")
if (focusedID != 4294967295) { ; Игнорируем разделители
lastFocusedID := focusedID ; Запоминаем текущий ID в памяти
}
}
}
; В) МЕНЮ ЗАКРЫЛОСЬ (КЛИК СОВЕРШЕН)
else if (event == EVENT_SYSTEM_MENUPOPUPEND && hwnd == currentMenuHwnd) {
; Если в момент закрытия меню последним сфокусированным элементом был наш пункт:
if (lastFocusedID == MY_CUSTOM_ID) {
; Вызываем действие асинхронно через таймер, чтобы дать ОС корректно закрыть меню чужого процесса
SetTimer(MyCustomAction, -10)
}
; Полностью очищаем переменные
currentMenuHwnd := 0
currentMenuHandle := 0
lastFocusedID := 0
}
}
; Функция-обработчик успешного клика
MyCustomAction() {
MsgBox("Пункт меню нажат! Перехвачено через фокус до закрытия меню.")
}
; Снятие хуков при закрытии скрипта
OnExit((*) => (
DllCall("UnhookWinEvent", "Ptr", hHookStart),
DllCall("UnhookWinEvent", "Ptr", hHookEnd),
DllCall("UnhookWinEvent", "Ptr", hHookFocus),
CallbackFree(callback)
))
|
Болван часто выводит код на С++, но AHK v2 легче всего переводить в Autorun. Для теста не нужно никаких сред разработок, достаточно одного exe файла и скрипта, это еще один плюс получения кода в AHK.
| AkulaBig wrote: | | Конечно базу брал из вашей сборки |
Сборка это хорошо, но болван лучше! Ведь это был его код
| AkulaBig wrote: | | А можно без перезагрузки отключить назначенное действие на кнопки мыши? |
Можно попробовать ключ /S, я думаю. Через него пропускать.
| FallenAngel wrote: | | У LoadLibrary есть аналог ahk-го #Include *i? Т.е. не выдавать ошибку not found - а молча пропускать, если не нашел? |
Если нет других вариантов, то можно через DllCall
| Code: | Static hLib = DllCall("LoadLibrary", "Wstr", sLib, "Ptr") |
А перед этим просто проверить существование файла через FileExist |
|