1 (изменено: Странникх, 2018-01-22 01:48:53)

Тема: AHK: ControlSend как увеличить скорость или аналог команды

#NoEnv  
#Persistent
#SingleInstance Force
SetWorkingDir %A_ScriptDir%  
Menu, Tray, UseErrorLevel
Menu, Tray, NoStandard
Menu, Tray, Add, Reload
Menu, Tray, Add, Exit
OnExit, Exit
CoordMode, Pixel, Screen
SetBatchLines, -1
SetWinDelay, -1
SetControlDelay, -1
SetKeyDelay, -1

Global pToken := GDIP_StartUp()
	, wWin1 := "ahk_class GxWindowClass ahk_exe Win64.exe", hWin1, Scan0, Stride
	, sleep_time = 30
	, index, index_old, i = 0
	, x1 := "0", y1 := "0", x2, y2, x3, y3
	, StatusLoop := "Okay"
	, wWin2 := "ahk_class GxWindowClass ahk_exe Win65.exe", hWin2 := WinExist(wWin2)
	, wWin3 := "ahk_class GxWindowClass ahk_exe Win66.exe", hWin3 := WinExist(wWin3)

WinGetPos, x2, y2,,, ahk_id %hWin2% 
WinGetPos, x3, y3,,, ahk_id %hWin3% 

Loop
{
	sleep, -1	
	If !(hWin1 := WinExist(wWin1)) {
		TrayTip, % SubStr(A_ScriptName, 1, -4), Окно Win не найдено,, 2
		sleep, 10000
		Continue
	} 	
	If i > 3 ; Сброс индекса
		i := 0	
	i++ ; Индекс
	;~ Start := A_TickCount
	UpdateMemDC()
	current_window := i = 3 ? hWin3
				 : i = 2 ? hWin2
				 : i = 1 ? hWin1
				 : 0

		If !Pixel(x i + 114, y i + 188, 0x00FF00,, 300) ; #1
		ControlSend,, {vk32}, ahk_id %current_window%
		If !Pixel(x i + 122, y i + 188, 0x00FF00,, 300) ; #2
		ControlSend,, {vk33}, ahk_id %current_window%
		If !Pixel(x i + 129, y i + 188, 0x00FF00,, 300) ; #3
		ControlSend,, {vk58}, ahk_id %current_window%
		If !Pixel(x i + 135, y i + 188, 0x00FF00,, 300) ; #4
		ControlSend,, {vk36}, ahk_id %current_window%
		If !Pixel(x i + 142, y i + 188, 0x00FF00,, 300) ; #5
		ControlSend,, {vk35}, ahk_id %current_window%
		If !Pixel(x i + 149, y i + 188, 0x00FF00,, 300) ; #6
		ControlSend,, {vk37}, ahk_id %current_window%
		If !Pixel(x i + 114, y i + 194, 0x00FF00,, 300) ; #7
		ControlSend,, {vk38}, ahk_id %current_window%
		If !Pixel(x i + 122, y i + 194, 0x00FF00,, 300) ; #8
		ControlSend,, {vk52}, ahk_id %current_window%
		If !Pixel(x i + 129, y i + 194, 0x00FF00,, 300) ; #9
		ControlSend,, {vk42}, ahk_id %current_window%
		If !Pixel(x i + 135, y i + 194, 0x00FF00,, 50) ; #10
		ControlSend,, {vk46}, ahk_id %current_window%
}
Return
ProcessExist(Name){
	Process,Exist,%Name%
	return Errorlevel
}
Exit:	
{
	GDIP_Shutdown(pToken)
	DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd)
	ExitApp
}
Return
;; [Цвет]
UpdateMemDC() {
	Gdip_UnlockBits(pBitmap, BitmapData)
	Gdip_DisposeImage(pBitmap)
	pBitmap := Gdip_BitmapFromScreen()
	Gdip_LockBits(pBitmap, 0, 0, 1679, 1049, Stride, Scan0, BitmapData)
}
Pixel(x, y, color = "", variation = 0, delay = "") {
 Static oDelay := {}
 If (delay != "") {
   If (oDelay[x, y, color] != "" && A_TickCount - oDelay[x, y, color] < delay)
    Return 1
   oDelay[x, y, color] := A_TickCount
  }
 c := Gdip_GetLockBitPixel(Scan0, x, y, Stride)
 bgr := bgr(c)
 If color =
  Return bgr
 If variation
  Return Between(bgr, color, variation)
  Return bgr != color
}
bgr(color) {
  Return Format("{:#08x}", ((Color & 0xff) << 16) + (((Color & 0x00ff00) >> 8) << 8) + ((Color & 0xff0000) >> 16))
}
Between(Num, Pat, Range="") {                                														
	If !Range
		Return Num != Pat
	SetFormat, IntegerFast, h 
	If (StrLen(Num) != 8) {
		SetFormat, IntegerFast, d
		Return 1
	}
	n1 := (0xff0000 & Num) >> 16 
	n2 := (0x0000ff00 & Num) >> 8
	n3 := (0xff & Num)
	p1 := (0xff0000 & Pat) >> 16 
	p2 := (0x0000ff00 & Pat) >> 8
	p3 := (0xff & Pat)
	bool := (n1 >= p1 - Range && n1 <= p1 + Range) && (n2 >= p2 - Range && n2 <= p2 + Range) && (n3 >= p3 - Range && n3 <= p3 + Range)
	SetFormat, IntegerFast, d
	Return !bool
}

Очень медленно доходят нажатия в посылаемые окна. Прикрутил SetKeyDelay, SetBatchLines и даже от админа запуск делал, но скорость не устраивает при слишком интенсивном вызове команды в разные окна.

Такое ощущение, что есть какое-то ограничение на ControlSend при интенсивном вызове.

Возможно есть альтернатива команде ControlSend, например через DllCall? Быть может остались способы о которых я не знаю с тем же ControlSend? Или через PostMessage как-то можно реализовать посылку горячих клавиш?

PostMessage, 0x100, 0x20, 1, ahk_id %hWin1%
PostMessage, 0x101, 0x20, 1, ahk_id %hWin1%
PostMessage, 0x102, 0x20, 1, ahk_id %hWin1%
PostMessage, 0x312, 0x20, 1, ahk_id %hWin1% 

С этим вариантом как-то не особо удачно вышло, не работает. hWin1 содержит PID окна, но отправка туда не происходит.

2

Re: AHK: ControlSend как увеличить скорость или аналог команды

Странникх, нажатия идут с такой скоростью, с какой их принимает окно.
Ваша проблема лежит совсем не там где вы думаете, хе-хех.

Странникх пишет:

Очень медленно

Цифру назовете? Проверьте также скорость в блокноте, а потом включите в нем перенос слов и проверьте еще раз.

Странникх пишет:

ahk_id %hWin1%
hWin1 содержит PID

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

3

Re: AHK: ControlSend как увеличить скорость или аналог команды

stealzy пишет:

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

То есть если использовать PostMessage разницы не будет?

stealzy, может все таки есть альтернатива отправки в неактивное окно? Или на AHK можно что-то сделать с окном, чтобы его оживить? Просто очень странно, что на первом индексе первое окно получает намного больше отправленных клавиш по сравнению с остальными, хотя все остальные идентичные.

4

Re: AHK: ControlSend как увеличить скорость или аналог команды

stealzy пишет:

Ваше окно представляет собой html + js, не так ли? (неудивительно что ввод  медленнее нативных программ).
Это будет означать, что окно-клиент всего лишь представляет интерфейс к какому-то веб API.

Графическое окно игры. Первое окно получает все клавиши, второе и следующие в разы меньше. Почему так не понятно

5

Re: AHK: ControlSend как увеличить скорость или аналог команды

Некоторые последние разработки игр снабжаются настройкой, которая снижает нагрузку на ЦП. Посмотрите свои настройки в игре. Вас вряд ли хотят обмануть.
https://d.radikal.ru/d42/1801/13/5b3c3f914d64.jpg

6

Re: AHK: ControlSend как увеличить скорость или аналог команды

KusochekDobra, тоже думал в этом проблема. Настройки  похожие есть, их убирал, эффекта нет. Первое окно же работает исправно..

7

Re: AHK: ControlSend как увеличить скорость или аналог команды

А вы уверены, что это из-за ControlSend тормозит, а не из-за других функций?

8 (изменено: Странникх, 2018-01-23 00:16:07)

Re: AHK: ControlSend как увеличить скорость или аналог команды

Malcev, не уверен, может цикл влияет. В итоге я повесил 8 окон на 8 settimer с одинаковым временем вызова, проблему частично решило, посылка стала быстрее, но все равно не достаточная скорость.

И еще SetKeyDelay, 0 + ListLines Off повысило надежность и скорость соответственно. Однако этого не достаточно.

9

Re: AHK: ControlSend как увеличить скорость или аналог команды

Странникх пишет:

Malcev, не уверен, может цикл влияет

Так проверьте.
Имхо, что-то у вас там мудрёно всё.

10

Re: AHK: ControlSend как увеличить скорость или аналог команды

Malcev, может совет есть какой по вопросу каким еще способом можно отослать клавишу в неактивное окно? Собственно в этом вся суть, потестирую замену, посмотрю была ли связь с ControlSend тогда.

11

Re: AHK: ControlSend как увеличить скорость или аналог команды

Уберите из кода всю эту кучу функций и в цикле посылайте ControlSend.
Засеките время и сделайте выводы.

12 (изменено: Странникх, 2018-01-23 19:09:17)

Re: AHK: ControlSend как увеличить скорость или аналог команды

Malcev, в этом вся и проблема, что без всего лишнего становится только хуже, надежность в разы меньше. Видимо из-за условий на проверку пикселя появляется задержка, которая controlsend позволяет скинуть более корректно. Поэтому параметр SetKeyDekay пробовал в 10, 10 ставить, но не особо помогает, все равно не устраивает скорость. По сути скорость прохождения цикла больше задержки на скорость отправки и поэтому возникает такая проблема, значит дело именно в controlsend, в том, что он медленный и не успевает справиться с большим потоком нажатий в разные окна.

13

Re: AHK: ControlSend как увеличить скорость или аналог команды

Если вы хотите доказать, что ControlSend медленный, то вы должны тестировать именно сам ControlSend без всяких функций, написанных, кстати, с ошибками.
Протестируйте надёжность и скорость ControlSend с другими приложениями, например с блокнотом.
Если с блокнотом будет работать без ошибок, то значит вы ошиблись разделом - игры здесь не обсуждаются.

14

Re: AHK: ControlSend как увеличить скорость или аналог команды

Malcev пишет:

функций, написанных, кстати, с ошибками

Например?

15

Re: AHK: ControlSend как увеличить скорость или аналог команды

UpdateMemDC() {
	Gdip_UnlockBits(pBitmap, BitmapData)
	Gdip_DisposeImage(pBitmap)
	pBitmap := Gdip_BitmapFromScreen()
	Gdip_LockBits(pBitmap, 0, 0, 1679, 1049, Stride, Scan0, BitmapData)
}

pBitmap не глобальный.
Глубже не смотрел.

16

Re: AHK: ControlSend как увеличить скорость или аналог команды

Malcev пишет:

pBitmap не глобальный.

Без объявления глобальной все равно работает. Других ошибок нет раз работает.

17

Re: AHK: ControlSend как увеличить скорость или аналог команды

С таким подходом не удивляйтесь, что у вас что-то не работает.