1 (изменено: 1srafel, 2025-06-17 23:38:16)

Тема: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

Составил такой вариант v2-скрипта для блокировки клавиатуры и мыши, который запускаю из v1-скрипта с правами администратора.

— блокирует по "F1 + Пробел" (можно разблокировать по этой же клавише, но закомментировано);
— после блокировки создает файл "BlockKbrdMouse.FLG", чтобы после перезапуска компьютера блокировка восстановилась;
— разблокирует по горячей строке "102" (в гуи записано словами, для защиты от неумеющих читать детей);
— разблокировка удаляет файл "BlockKbrdMouse.FLG";
— если запущен PotPlayer — остается рабочей только клавиша "Пробел", для возможности остановки/старта воспроизведения;
— добавил дополнительно почти все клавиши с return, так как "BlockInput(true)" некоторые мои клавиши преодолевали.

Есть вопрос по коду v2. Как исправить поведение, когда горячая строка не откликается на "102", если много раз перед этим набирались случайные цифры?

Код для v1:

IfExist, %MY_DATA%\_Scripts\BlockKbrdMouse.FLG
   Gosub, BlockKbrdMouse

; Заблокировать клавиатуру и мышь
F1 & Space::
BlockKbrdMouse:
   ;Запуск программы С ПРАВАМИ Администратора

   Run *RunAs "C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe" "%MY_DATA%\_Scripts\BlockKbrdMouse_(+ADMIN+AHKv2).ahk"
Return

Код для v2:

#Requires AutoHotkey v2.0
#SingleInstance Force
#UseHook
;KeyHistory 0 ; Отключает историю нажатий клавиш для оптимизации и снижения использования памяти.



; Путь к файлу флага
BlockKbrdMouseFile := A_ScriptDir "\BlockKbrdMouse.FLG"

; Создание файла флага, если он не существует
if !FileExist(BlockKbrdMouseFile) {
    FileAppend("", BlockKbrdMouseFile)  ; Создаёт пустой файл
}

; Инициализация переменных
isLocked := true

; Создание GUI
; Внешнее окно с красным фоном (для каймы)
myGui := Gui()
myGui.BackColor := "Red"  ; Красный фон для имитации каймы
myGui.Opt("-Caption +AlwaysOnTop +ToolWindow +E0x80000") ; WS_EX_LAYERED, без +Border

; Внутреннее окно с жёлтым фоном и текстом
innerGui := Gui()
innerGui.BackColor := "Yellow"  ; Жёлтый фон
innerGui.Opt("-Caption +Parent" myGui.Hwnd) ; Внутреннее окно

; Включить обнаружение скрытых окон 
;!!DetectHiddenWindows(true)
;MsgBox WinExist("ahk_exe PotPlayerMini64.exe") ? "PotPlayer существует" : "PotPlayer не найден" ; Раскомментировать для отладки

; Проверка, существует ли процесс PotPlayer
if WinExist("ahk_exe PotPlayerMini64.exe") {
    innerGui.SetFont("s18 cRed", "Segoe UI")
    innerGui.Add("Text", "x10 y10 w120", "Сто два") ;Сто два
    innerGui.SetFont("s18 cBlack", "Segoe UI")
    innerGui.Add("Text", "x+20 y10 w580", " — разблокировать клавиатуру и мышь")
    innerGui.Show("x10 y10 w680 h60") ; Уменьшенное окно
    myGui.Show("w700 h80 y0") ; Внешнее окно по центру
    myGui.Title := "BlockKbrdMouse_Win"
} else {
    innerGui.SetFont("s20 cRed", "Segoe UI")
    innerGui.Add("Text", "x10 y10 w120", "Сто два") ;Сто два
    innerGui.SetFont("s20 cBlack", "Segoe UI")
    innerGui.Add("Text", "x+20 y10 w350", " — разблокировать клавиатуру и мышь")
    innerGui.SetFont("s12 cRed", "Segoe UI")
    innerGui.Add("Text", "x10 y100 w120", "F1+Пробел")
    innerGui.SetFont("s12 cBlack", "Segoe UI")
    innerGui.Add("Text", "x+20 y100 w140", " — заблокировать")
    innerGui.Show("x10 y10 w410 h140") ; Полное окно
    myGui.Show("w430 h160 Center") ; Внешнее окно по центру
    myGui.Title := "BlockKbrdMouse_Win"
}

; Проверка существования окна GrandGui
if WinExist("GrandGui")
{
    ; Установить прозрачность (100 — нечётко видимое)
    DllCall("SetLayeredWindowAttributes", "Ptr", myGui.Hwnd, "UInt", 0, "UChar", 90, "UInt", 0x2)
}
else
{
    ; Установить прозрачность (255 — чётко видимое)
    DllCall("SetLayeredWindowAttributes", "Ptr", myGui.Hwnd, "UInt", 0, "UChar", 255, "UInt", 0x2)
}

WinShow(myGui.Hwnd) ; Принудительно показать окно
WinRedraw(myGui.Hwnd) ; Перерисовать окно для гарантии отображения






; Включение блокировки при запуске скрипта
BlockInput(true)
SoundBeep(500, 200) ; Звуковой сигнал для подтверждения



; Исключения для клавиш
#InputLevel 1
; Исключение для пробела в окне PotPlayer: пробел не блокируется
$Space:: {
    ; Проверка, существует ли процесс PotPlayer
    if WinExist("ahk_exe PotPlayerMini64.exe") {
        WM_KEYDOWN := 0x0100
        WM_KEYUP := 0x0101
        VK_Space := 0x20
        potPlayerTitle := "ahk_exe PotPlayerMini64.exe"
        potPlayerID := WinGetID(potPlayerTitle)

        DetectHiddenWindows(false)
        BlockInput(false)

        if potPlayerID {
            persistentClass := getPersistentClass(potPlayerID)
            hwnd := findChildByClass(potPlayerID, persistentClass)

            if !hwnd {
                ToolTip("❌ Класс " persistentClass " не найден, пробую заново")
                persistentClass := getPersistentClass(potPlayerID)
                hwnd := findChildByClass(potPlayerID, persistentClass)
            }
            if hwnd {
                ; Временно активируем PotPlayer, чтобы пробел точно сработал
                WinActivate("ahk_id " potPlayerID)
                Sleep(40) ;100

                ; Отправляем пробел
                PostMessage(WM_KEYDOWN, VK_Space, 0, , hwnd)
                Sleep(15) ;30
                PostMessage(WM_KEYUP, VK_Space, 0, , hwnd)

                ToolTip("Пробел отправлен в HWND: " hwnd)

                ; Снова поднимаем GUI поверх PotPlayer
                WinSetAlwaysOnTop(true, "ahk_id " myGui.Hwnd)
                WinSetAlwaysOnTop(true, "ahk_id " innerGui.Hwnd)
                WinActivate("ahk_id " myGui.Hwnd) ; Только после отправки
            } else {
                ToolTip("❌ Не удалось найти нужное окно даже после повтора")
            }
        } else {
            Send("{Space}")
            ToolTip("PotPlayer не найден, пробел отправлен")
        }
        ToolTip()
        BlockInput(true)
        DetectHiddenWindows(true)
    }
}

getPersistentClass(potPlayerID) {
    persistentClass := ""
    foundHwnd := 0

    EnumChildProc(hwnd, _) {
        class := WinGetClass("ahk_id " hwnd)
        if class {
            foundHwnd := hwnd
            persistentClass := class
            return false
        }
        return true
    }
    cb := CallbackCreate(EnumChildProc, "Fast")
    DllCall("User32.dll\EnumChildWindows", "Ptr", potPlayerID, "Ptr", cb, "Ptr", 0)
    CallbackFree(cb)

    return (foundHwnd != 0) ? persistentClass : ""
}

findChildByClass(parentHwnd, className) {
    foundHwnd := 0

    EnumChildProc(hwnd) {
        class := WinGetClass("ahk_id " hwnd)
        if (class = className) {
            foundHwnd := hwnd
            return false
        }
        return true
    }
    cb := CallbackCreate(EnumChildProc, "Fast")
    DllCall("User32.dll\EnumChildWindows", "Ptr", parentHwnd, "Ptr", cb, "Ptr", 0)
    CallbackFree(cb)

    return foundHwnd
}

#InputLevel 0





/*
; удерживать F1 + F5 + Пробел одновременно, чтобы разблокировать
SetTimer(CheckUnlock, 50)
CheckUnlock() {
    global isLocked
    if (isLocked && GetKeyState("F1", "P") && GetKeyState("F5", "P") && GetKeyState("Space", "P")) {
        UnBlock()
    }
}
*/




; Горячая строка для разблокировки
; --- Автозамена в любом месте ввода ---
:?*:102::
{
    global isLocked
    if (!GetKeyState("F1", "P") && isLocked)
    {
        UnBlock()
    }
}



/*
; Горячая клавиша для блокировки (F1 + Пробел)
#HotIf GetKeyState("F1", "P") ; Проверяем, удерживается ли F1
Space::
{
    UnBlock()
}
#HotIf
*/

; Функция разблокировки
UnBlock() {
    global isLocked
    BlockInput(false) ; Отключаем блокировку
    isLocked := false
    if FileExist(BlockKbrdMouseFile) {
        FileDelete(BlockKbrdMouseFile) ; Удаляем файл флага
    }
    ;myGui.Destroy() ; Уничтожаем GUI после разблокировки
    ;SoundBeep(1000, 200) ; Звуковой сигнал для подтверждения
    ExitApp
}

; Перехват всех клавиш, кроме цифр, в состоянии блокировки
#HotIf isLocked
; Буквы
$a::return
$b::return
$c::return
$d::return
$e::return
$f::return
$g::return
$h::return
$i::return
$j::return
$k::return
$l::return
$m::return
$n::return
$o::return
$p::return
$q::return
$r::return
$s::return
$t::return
$u::return
$v::return
$w::return
$x::return
$y::return
$z::return

/*
; Цифровые клавиши
0::Return
1::Return
2::Return
3::Return
4::Return
5::Return
6::Return
7::Return
8::Return
9::Return
*/

; Функциональные клавиши
$F1::return
$F2::return
$F3::return
$F4::return
$F5::return
$F6::return
$F7::return
$F8::return
$F9::return
$F10::return
$F11::return
$F12::return

; Специальные клавиши
$AppsKey::Return   ; Меню (context menu key)
;$Space::return
$Enter::return
$Tab::return
$Backspace::return
$Delete::return
$Insert::return
$Home::return
$End::return
$PgUp::return
$PgDn::return
$Up::return
$Down::return
$Left::return
$Right::return
$Esc::return
$CapsLock::return
$ScrollLock::return
$NumLock::return
$PrintScreen::return
$Pause::return

; Модификаторы
$LShift::return
$RShift::return
$LCtrl::return
$RCtrl::return
$LAlt::return
$RAlt::return
$LWin::return
$RWin::return

/*
; Знаки препинания и символы
$`::return
$~::return
$!::return
$@::return
$#::return
$$::return
$%::return
$^::return
$&::return
$*::return
$(::return
$)::return
$_::return
$+::return
$[::return
$]::return
${::return
$}::return
$|::return
$\::return
$;::return
$Colon::return
$'::return
$"::return
$,::return
$.::return
$<::return
$>::return
$/::return
$?::return
*/

/*
; Математические символы
Multiply::Return ; Умножение (*)
Add::Return      ; Плюс (+)
Subtract::Return ; Минус (-)
Divide::Return   ; Деление (/)
Decimal::Return  ; Десятичная точка (.)
*/

; Клавиши цифрового блока (кроме цифр)
$NumpadDiv::return
$NumpadMult::return
$NumpadAdd::return
$NumpadSub::return
$NumpadEnter::return
$NumpadDot::return

; Мышь
$LButton::return
$RButton::return
$MButton::return
$XButton1::return
$XButton2::return
$WheelUp::return
$WheelDown::return

; Мультимедийные клавиши
Browser_Back::return
Browser_Forward::return
Browser_Refresh::return
Browser_Stop::return
Browser_Search::return
Browser_Favorites::return
Browser_Home::return
Volume_Mute::return
Volume_Down::return
Volume_Up::return
Media_Next::return
Media_Prev::return
Media_Stop::return
Media_Play_Pause::return
Launch_Mail::return
Launch_Media::return
Launch_App1::return
Launch_App2::return

#HotIf

2

Re: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

Не очень понятно, зачем один скрипт из другого запускать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

Просто имеется большой v1 скрипт, который постоянно запущен, и потому удобно запускать из него.

4

Re: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

Советую для отслеживания причины проблемы максимально минимизировать скрипт до размера, который сможет продемонстрировать проблему.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

1srafel пишет:

когда горячая строка не откликается на "102", если много раз перед этим набирались случайные цифры

Может делать Reset через время бездействия?

Справка пишет:

Immediately resets the hotstring recognizer.

Win 10 x64
AHK
                       Справка AHK v1 тебе в помощь.

6

Re: AHK v2: Заблокировать клавиатуру и мышь (+ AHK v1)

Через время бездействия - годный вариант, спасибо. И тут тоже про эту проблему с горячей строкой - autohotkey.com/boards/viewtopic.php?t=114814. Правильно ли понял, что там советуют добавить #InputLevel?