1 (изменено: kamelotto, 2016-06-27 20:03:55)

Тема: AHK: Отключить скрипт во время набора текста

Бывает, что какой-то из запущенных скриптов вмешивается в процесс набора текста. Можно ли как то сделать так, что бы этот скрипт выключался или блокировался на время набора текста, а потом снова продолжал работать?

2

Re: AHK: Отключить скрипт во время набора текста

Можно, если правильно тему оформить.

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

3

Re: AHK: Отключить скрипт во время набора текста

teadrinker
А что не правильно оформлено?
Я задал вопрос без конкретного скрипта, потому, что такие скрипты могут быть разные. Нужен общий вариант. Алгоритм по которому действовать в случае обнаружения такой накладки. Желательно с указанием, какие команды и функции использовать. Не помешает и пара примеров, если возможно написать универсальные варианты.

4

Re: AHK: Отключить скрипт во время набора текста

kamelotto пишет:

А что не правильно оформлено?

Заголовок, отсутствует префикс языка.

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

5

Re: AHK: Отключить скрипт во время набора текста

teadrinker
Упсь!
Исправил.

6

Re: AHK: Отключить скрипт во время набора текста

kamelotto пишет:

Можно ли как то сделать так, что бы этот скрипт выключался или блокировался на время набора текста

А по какому признаку будем определять, что набор текста закончен?

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

7 (изменено: kamelotto, 2016-06-28 04:46:50)

Re: AHK: Отключить скрипт во время набора текста

teadrinker пишет:

А по какому признаку будем определять, что набор текста закончен?

Можно по фокусу ввода ориентироваться. Когда мигает вертикальная палочка в поле ввода текста или в блокноте, тогда значит включён режим ввода текста, А когда нет палочки, значит фокус снят и снова можно задействовать скрипт.
Правда я не уверен, что это можно определить.

8

Re: AHK: Отключить скрипт во время набора текста

Сомневаюсь, что из этой затеи может что-то путное получиться.
Программ различных много и у многих контролы нестандартные.
Может достаточно использовать горячие клавиши при активности/неактивности какого либо окна/окон?

9

Re: AHK: Отключить скрипт во время набора текста

Да, определить наличие каретки можно не всегда. Как вариант могу предложить блокировать указанный скрипт на какое-то время после физического нажатия любой клавиши на клавиатуре.

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

10

Re: AHK: Отключить скрипт во время набора текста

teadrinker
А что? Это тоже мысль. Нужно только на практике попробовать, как это будет в пользовании.

11

Re: AHK: Отключить скрипт во время набора текста

Тогда завтра напишу.

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

12

Re: AHK: Отключить скрипт во время набора текста

teadrinker
Буду ждать

13

Re: AHK: Отключить скрипт во время набора текста

Скрипт, посылающий нажатия:

^vk50::  ; Ctrl + P
	SetTimer, SendKey, % (i := !i) ? "On" : "Off"
	Return

SendKey:
	if !GetKeyState("Ctrl", "P")
		SendInput, {!}
	Return

Скрипт, блокирующий первый скрипт:

#Persistent
ScriptName := "KeySender.ahk"  ; имя скрипта, который нужно поставить на паузу
BlockPeriod := 3000        ; время, на которое нужно остановить скрипт
Blocker.Init(ScriptName, BlockPeriod)
Return

class Blocker
{
	Init(ScriptName, time)  {
		this.ScriptName := ScriptName
		this.BlockTime := time
		this.UnBlock := this.UnBlockTimer.Bind(this)
		this.hHookKeybd := DllCall("SetWindowsHookEx"
			, Int, WH_KEYBOARD_LL := 13
			, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
			, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
			, UInt, 0, Ptr)
	}
	Block()  {
		if !hWnd := this.GetScriptMainWindow()
			Return
		if !this.Blocked  {
			this.Blocked := 1
			WinMenuSelectItem, % "ahk_id" hWnd,, 1&, 5&
		}
		timer := this.UnBlock
		SetTimer, % timer, % "-" this.BlockTime
	}
	UnBlockTimer()  {
		WinMenuSelectItem, % "ahk_id" this.GetScriptMainWindow(),, 1&, 5&
		this.Blocked := 0
	}
	GetScriptMainWindow()  {
		SetTitleMatchMode, 2
		DetectHiddenWindows, On
		Return WinExist(this.ScriptName)
	}
}
	
LowLevelKeyboardProc(nCode, wParam, lParam)
{
	static LLKHF_INJECTED := 0x10, INJECTED
	flags := NumGet(lParam + 8, "UInt")
	INJECTED := (flags & LLKHF_INJECTED) >> 4
	SetTimer, EventHandling, -10
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
	
EventHandling:
   if !INJECTED
		Blocker.Block()
	Return
}

Сохраняем первый скрипт, как KeySender.ahk. Запускаем его. Потом запускаем второй скрипт. Открываем блокнот, нажимаем Ctrl + P (старт посыла клавиш), и посылающий скрипт через время, указанное во втором скрипте (3000 мс), начинает отправлять в блокнот клавишу {!}. Пробуем что-нибудь напечатать. После каждого физического нажатия клавиш посылающий скрипт должен ставиться на паузу на 3 секунды.

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

14 (изменено: kamelotto, 2016-06-29 16:33:07)

Re: AHK: Отключить скрипт во время набора текста

teadrinker
Спасибо. Это интересное решение. И похоже оно работает. Буду тестировать.
Вариант с приостановкой скрипта, это удобно.
Однако было бы не плохо, ещё иметь возможность выключить его совсем, с момента набора текста. Бывают такие скрипты, которые просто висят в памяти и редко используются. Их можно и совсем отключить, когда дело доходит до текста. Скажем переписка в соцсети. Это, как правило надолго, и скрипты могут мешать, и как то понятно, что они долго не понадобятся, если началась переписка.

15

Re: AHK: Отключить скрипт во время набора текста

Выключить совсем — в смысле, завершить?

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

16

Re: AHK: Отключить скрипт во время набора текста

teadrinker пишет:

Выключить совсем — в смысле, завершить?

Наверное да. В случае чего потом запускать снова. И ещё сразу....
Как можно указать несколько скриптов в обоих вариантах?

17

Re: AHK: Отключить скрипт во время набора текста

Если завершать несколько скриптов, то так:

#Persistent
ScriptNames := ["KeySender.ahk", "KeySender2.ahk"]  ; имена скриптов, которые нужно завершить
Blocker.Init(ScriptNames)
Return

class Blocker
{
	Init(ScriptNames)  {
		this.ScriptNames := ScriptNames
		this.hHookKeybd := DllCall("SetWindowsHookEx"
			, Int, WH_KEYBOARD_LL := 13
			, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
			, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
			, UInt, 0, Ptr)
	}
	Terminate()  {
		SetTitleMatchMode, 2
		DetectHiddenWindows, On
		for k, v in this.ScriptNames
			if WinExist(v)
				WinClose
	}
}
	
LowLevelKeyboardProc(nCode, wParam, lParam)
{
	static LLKHF_INJECTED := 0x10, INJECTED
	flags := NumGet(lParam + 8, "UInt")
	INJECTED := (flags & LLKHF_INJECTED) >> 4
	SetTimer, EventHandling, -10
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
	
EventHandling:
   if !INJECTED
		Blocker.Terminate()
	Return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18 (изменено: kamelotto, 2016-06-29 19:32:42)

Re: AHK: Отключить скрипт во время набора текста

teadrinker
С ним что то не так. Он работает вроде. То есть закрывает указанные скрипты во время введения первого символа текста. Но так же закрывает эти скрипты по команде, их вызывающей, когда мы не работаем в текстовом поле.
Видимо команды запуска этих скриптов воспринимаются, как набор текста и поэтому происходит завершение. То есть не получается в дальнейшем запустить отключенные скрипты, когда они понадобились снова.
Хм... Похоже первый тупичёк

19

Re: AHK: Отключить скрипт во время набора текста

Попробуйте так:

#Persistent
ScriptNames := ["KeySender.ahk", "KeySender2.ahk"]  ; имена скриптов, которые нужно завершить
Blocker.Init(ScriptNames)
Return

class Blocker
{
	Init(ScriptNames)  {
		this.ScriptNames := ScriptNames
		this.oWMI := ComObjGet("winmgmts:")
		this.hHookKeybd := DllCall("SetWindowsHookEx"
			, Int, WH_KEYBOARD_LL := 13
			, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
			, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
			, UInt, 0, Ptr)
	}
	Terminate()  {
		SetTitleMatchMode, 2
		DetectHiddenWindows, On
		for k, name in this.ScriptNames
			if WinExist(name) && (this.GetLifeTime(name) > 2)  ; закрываем процесс скрипта, если он был создан более двух секунд назад
				WinClose
	}
	GetLifeTime(name)  {
		WinGet, PID, PID, % name
		LifeTime -= this.oWMI.Get("Win32_Process.Handle=" PID).CreationDate, s
		Return LifeTime
	}
}
	
LowLevelKeyboardProc(nCode, wParam, lParam)
{
	static LLKHF_INJECTED := 0x10, INJECTED, msg
		  , oMsg := {0x100: "WM_KEYDOWN", 0x101: "WM_KEYUP", 0x104: "WM_SYSKEYDOWN", 0x105: "WM_SYSKEYUP"}
	msg  	:= wParam
	flags := NumGet(lParam + 8, "UInt")
	INJECTED := (flags & LLKHF_INJECTED) >> 4
	SetTimer, EventHandling, -10
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
	
EventHandling:
   if InStr(oMsg[msg], "DOWN") && !INJECTED
		Blocker.Terminate()
	Return
}

Здесь скрипт завершается, только если был запущен более двух секунд назад.

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

20 (изменено: kamelotto, 2016-06-29 21:57:15)

Re: AHK: Отключить скрипт во время набора текста

teadrinker
Похоже это не правильный путь. При запущенном отключающем скрипте (назовём его "завершитель". Тот, который Вы пишете), два других скрипта: "KeySender.ahk"и "KeySender2.ahk" можно загрузить в память и они там будут висеть. Но запустить их выполнение, например  нажав Ctrl+P не удаётся. Происходит завершение его и он исчезает из трея. Завершаются оба скрипта, по команде, вызывающей любой из них.

21

Re: AHK: Отключить скрипт во время набора текста

Да, не подумал. Тогда, наверное, лучше остановиться на первом варианте, либо останавливать все нужные скрипты по одной горячей клавише.

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

22 (изменено: kamelotto, 2016-06-30 02:54:39)

Re: AHK: Отключить скрипт во время набора текста

teadrinker
Да. Наверное Вы правы. Видимо искусственный интеллект так просто в AHK не написать.
Спасибо вам за труды.  Жаль только комментариев маловато. Сижу теперь и пытаюсь сам разобрать, какая строка за что отвечает. Но это уже ....

23

Re: AHK: Отключить скрипт во время набора текста

kamelotto
Сам часто пользуюсь скриптами, которые нужны только в определенные моменты, и затем их нужно также по быстрому выключить... Придумал себе такое (Возможно не каждому удобно).

1) Основной скрипт, в нем прописываю горячие клавиши на запуск нужных мне скриптов (Запускается при запуске Windows).
Run.ahk


SetWorkingDir %A_ScriptDir%
#SingleInstance force
#NoTrayIcon  ; Скрытый режим, чтобы иконка не мозолила глаз :)

F12:: ExitApp  
^F12:: Reload

F11:: Run, Таймер\Timer.ahk ; Запуск скрипта "Таймер"

F10::
Sendinput +{F11} ; (Нажимает Shift + F11) Закроет скрипт "Таймер", если запущен.
Run, Запись\Rec.ahk ; Запуск скрипта "Запись"

 

2) Далее в самих скриптах пишу.

Timer.ahk


SetWorkingDir %A_ScriptDir% 
Menu, Tray, Icon, Таймер\timer.ico ; Иконка помогает быстро определить какой скрипт запущен 
TrayTip, Таймер, Запущен ; Уведомление тоже не помешает

F11:: ExitApp ; Завершить скрипт

+F11:: ExitApp ; (Shift+F11) Также завершить скрипт. Если необходимо при запуске другого скрипта, завершить этот. 

Rec.ahk


SetWorkingDir %A_ScriptDir% 
Menu, Tray, Icon, Запись\Rec.ico 
TrayTip, Запись, Запущена

F10:: ExitApp

Теперь использование. Нажимаю F11 - запускается скрипт "Таймер", нажимаю еще раз F11 - закрываю скрипт, и т.п с остальными.

P.S. Прошу строго не судить, пишу как могу, на основе полученных знаний и собственных экспериментов.