1 (изменено: Botsy, 2021-06-13 00:17:52)

Тема: AHK: Запуск горячей кнопки через сторонний класс

Подскажите пожалуйста, а есть ли способ запускать горячую клавишу через сторонний класс эмуляции?
Например, вместо этого:


F1::
msgbox, test
return

Это:


Class_DD64.keyboard_press("F1")::
msgbox, test

Или может как-то через:


Hotkey, % Func, Button
Return

Func() {
Class_DD64.keyboard_press("F1")
}

Button:
msgbox, test

Дело в том, что лаунчер не пропускает стандартные нажатия из ahk. Если используется метод хука - то лаунчер ругается, а если стандартный reg, то запуск горячей кнопки надо делать не в активном окне лаунчера, что не очень удобно. Посмотрел через ListHotkeys.

UPD:
решил пока через If GetKeyState("F1", P), работает, но может есть более лучшее решение?

GD

2

Re: AHK: Запуск горячей кнопки через сторонний класс

Я ничего не понял. Что за сторонний класс эмуляции? Что значит «стандартные нажатия из ahk»? Код, вроде, никаких нажатий не отправляет.
Имеете в виду, определённое окно реагирует нежелательным образом, когда AHK пытается перехватить нажатия клавиш?

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

3

Re: AHK: Запуск горячей кнопки через сторонний класс

'Class_DD64' - можно ли на это посмотреть? Что за зверь?

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

4

Re: AHK: Запуск горячей кнопки через сторонний класс

teadrinker

"Что за сторонний класс эмуляции? Что значит «стандартные нажатия из ahk»?"
- Это класс который эмулирует клавиатуру и мышь, похожий на AutoHotInterseption. Т.е. методы эмуляции отличные от "стандартных" Send, Click и т.д.

"Код, вроде, никаких нажатий не отправляет."
- Не отправляет, но использует горячие клавиши. Не знаю можно ли так сказать, но они по своему характеру схожи с эмуляцией. Т.е. используют какие-то стандартные "способы" или "методы".

"Имеете в виду, определённое окно реагирует нежелательным образом, когда AHK пытается перехватить нажатия клавиш?"
- да. И если непосредственно Send и Click я смог заменить другим классом, то горячие клавиши не смог. Вот и пытаюсь запускать подпрограмму не стандартной горячей клавишей, эмулированной ahk, а со стороннего класса.

__Михаил__
Это класс для эмуляции клавиатуры и мышки на уровне железа. Тут https://github.com/ddxoft бесплатная демо версия на разных языках, из архива "drivers" нужны .dll. Для бесплатной версии ahk класс:

+ открыть спойлер

class DD extends DD_Helper
{
	; Simulate mouse button press
	; param:   1 = LButton Down,    2 = LButton Up
	;          4 = RButton Down,    8 = RButton Up
	;         16 = MButton Down,   32 = MButton Up
	;         64 = Button 4 Down, 128 = Button 4 Up
	;        256 = Button 5 Down, 512 = Button 5 Up
	btn(param) {
		return DllCall(this.dllFile "\DD_btn", "int", param)
	}

	; Simulate mouse move
	mov(x, y) {
		return DllCall(this.dllFile "\DD_mov", "int", x, "int", y)
	}

	; Simulate mouse move (relatively)
	movR(dx, dy) {
		return DllCall(this.dllFile "\DD_movR", "int", dx, "int", dy)
	}

	; Simulate mouse wheel
	; param: 1=upward 2=downward
	whl(param) {
		return DllCall(this.dllFile "\DD_whl", "int", param)
	}

	; Simulate keyboard
	; param1: DD code
	; param2: 1=Down 2=Up
	key(param1, param2) {
		return DllCall(this.dllFile "\DD_key", "int", param1, "int", param2)
	}

	; VKCode to DD code
	todc(VKCode) {
		return DllCall(this.dllFile "\DD_todc", "int", VKCode)
	}

	; Send string
	str(string) {
		return DllCall(this.dllFile "\DD_str", "astr", string)
	}

	; Get hwnd of active window
	GetActiveWindow() {
		; return DllCall(this.dllFile "\DD_GetActiveWindow", "ptr") ; seems not working
		return WinExist("A")
	}

	MouseMove(hwnd, x, y) {
		return DllCall(this.dllFile "\DD_MouseMove", "ptr", hwnd, "int", x, "int", y)
	}

	; The picture is saved to "C:\DD Snap\" folder
	SnapPic(hwnd, x, y, w, h) {
		return DllCall(this.dllFile "\DD_SnapPic", "ptr", hwnd, "int", x, "int", y, "int", w, "int", h)
	}

	PickColor(hwnd, x, y, mode=2) {
		return DllCall(this.dllFile "\DD_PickColor", "ptr", hwnd, "int", x, "int", y, "int", mode)
	}
}

class DD_Helper
{
	static _ := DD_Helper.InitClass()

	InitClass() {
		this.RunAsAdmin()
		this.LoadDll()
	}

	; https://www.autohotkey.com/docs/commands/Run.htm#RunAs
	RunAsAdmin() {
		full_command_line := DllCall("GetCommandLine", "str")

		if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)"))
		{
			try
			{
				if A_IsCompiled
					Run *RunAs "%A_ScriptFullPath%" /restart
				else
					Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
			}
			ExitApp
		}
	}

	LoadDll() {
		dllFile := (A_PtrSize=8) ? "DD64.dll" : "DD32.dll"

		if !this.hModule := DllCall("LoadLibrary", "Str", dllFile, "Ptr") {
			if !FileExist(dllFile) {
				throw, dllFile " not found."
			}
			throw, "LoadLibrary failed. DllFile is " dllFile
		}
		this.dllFile := dllFile
	}

	UnloadDll() {
		DllCall("FreeLibrary", "Ptr", this.hModule)
	}
	
	; Example: _btn("RButtonDown")
	_btn(sNick, x:="", y:="") {
		static oNick := { LButtonDown: 1, LButtonUp: 2
		                , RButtonDown: 4, RButtonUp: 8
		                , MButtonDown: 16, MButtonUp: 32
		                , 4ButtonDown: 64, 4ButtonUp: 128
		                , 5ButtonDown: 256, 5ButtonUp: 512 }
		if !( n := oNick[sNick] ) {
			throw, sNick " is not a valid nick."
		}
		if (x != "") {
			this.mov(x, y)
		}
		this.btn(n)
	}

	; Example: _btn_press("RButton")
	_btn_press(sNick, x:="", y:="", nCount:=1) {
		static oNick := { LButton: {Down: 1, Up: 2}
		                , RButton: {Down: 4, Up: 8}
		                , MButton: {Down: 16, Up: 32}
		                , 4Button: {Down: 64, Up: 128}
		                , 5Button: {Down: 256, Up: 512} }
		if !( o := oNick[sNick] ) {
			throw, sNick " is not a valid nick."
		}
		if (x != "") {
			this.mov(x, y)
		}
		Loop, % nCount {
			this.btn( o.Down )
			this.btn( o.Up )
			Sleep, 5
		}
	}

	; Example: _key("F11", "Down")
	;          _key("F11", "Up")
	_key(sKey, sflag) {
		ddCode := this._key_to_dc(sKey)
		this.key(ddCode, (sflag="Up") ? 2 : 1 )
	}

	; Example: _key_press("F11")
	;          _key_press("Ctrl", "A")
	_key_press(sKey*) {
		arr_ddCode := []

		for i, k in sKey {
			arr_ddCode[i] := this._key_to_dc(k)
			this.key(arr_ddCode[i], 1) ; Down
		}
		for i, ddCode in arr_ddCode {
			this.key(ddCode, 2) ; Up
		}
	}

	_key_pressEx(sKey, nCount := 1) {
		ddCode := this._key_to_dc(sKey)

		Loop, % nCount {
			this.key(ddCode, 1) ; Down
			this.key(ddCode, 2) ; Up
		}
	}

	; Example: _whl("down")
	;          _whl("up")
	_whl(sParam) {
		this.whl( (sParam="Up") ? 1 : 2 )
	}

	_key_to_dc(key) {
		static o := {"Win": "Lwin"}

		if o.HasKey(key)
			key := o[key]

		return this.todc( GetKeyVK(key) )
	}
}

GD

5

Re: AHK: Запуск горячей кнопки через сторонний класс

Botsy пишет:

Не отправляет, но использует горячие клавиши. Не знаю можно ли так сказать, но они по своему характеру схожи с эмуляцией

Нет, тут у вас путаница. Эмуляция клавиш — это когда AHK-скрипт посылает нажатия (например, командой Send), а горячие клавиши — это когда скрипт перехватывает нажатия, посланные извне. Это две совершенно разные вещи.
Не уверен, что получится, но можно попробовать использовать горячие клавиши с тильдой:

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

6 (изменено: Botsy, 2021-06-13 12:47:17)

Re: AHK: Запуск горячей кнопки через сторонний класс

teadrinker С тильдой пробовал, работало только в сочетании с SendMode, Input. Но в целом не подходит - т.к. используется хук и лаунчер ругался.
А по какому принципу ahk посылает нажатия? Лаунчер отслеживает и эмуляцию и горячие клавиши, может быть в них есть что-то общее? Например эти хуки.
GetKeyState же тоже перехватывает нажатия, но на эту команду не ругается и с ней работает.

GD

7

Re: AHK: Запуск горячей кнопки через сторонний класс

Ждете в цикле либо через хук активации нужного вам окна, после чего активируете нужную вам хотки.
После чего ждёте деактивации окна и деактивируете нужную вам хотки.

8

Re: AHK: Запуск горячей кнопки через сторонний класс

Malcev Не понял, а зачем это?

GD

9

Re: AHK: Запуск горячей кнопки через сторонний класс

Чтобы хотки регистрировались через reg.

loop
{
   Hotkey, 1, off
   WinWaitActive, Calculator
   Hotkey, 1, on
   WinWaitNotActive, Calculator
}

1::msgbox

Еще можно так

1::
if WinActive("Calculator")
   msgbox
else
{
   Hotkey, 1, off
   send 1
   Hotkey, 1, on
}

10

Re: AHK: Запуск горячей кнопки через сторонний класс

Malcev Так reg не подходит, т.к. лаунчер просто игнорирует их. Я писал это в 1-ом посте.
Допустим в лаунчере вызвать msgbox.


#IfWinActive Launcher
1::
msgbox, t
return
#IfWinActive

Или любым из ваших способов - ничего не произойдет. Лаунчер просто проигнорирует вызов msgbox. Пока работает только с командой GetKeyState:


loop, 
{
	If GetKeyState("1", P)
	{
		msgbox, t
		return
	}
}

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

GD

11

Re: AHK: Запуск горячей кнопки через сторонний класс

#IfWinActive Launcher
1::
msgbox, t
return
#IfWinActive

Тут у вас через хук.
В моем коде через reg.
Ваш ланчер всё это блокирует.
Что за ланчер такой?
Может тему надо в игры перенести?

12

Re: AHK: Запуск горячей кнопки через сторонний класс

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

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


XButton1::
msgbox, t
return
GD

13

Re: AHK: Запуск горячей кнопки через сторонний класс

В конкретном случае - XignCode3. Не считаю что глобально вопрос относится конкретно к игре, т.к. похожее было и в покерных клиентах

А покер это не игра?
И что еще можно ожидать от античитовой программы?
Наверняка она проверяет какие глобальные хуки установлены в системе и блокирует их.
Как устанавливает их автохотки вы можете почитать в исходниках программы.
Ну а заменить GetKeyState можно, наверное, на KeyWait, как работают эти функции можно опять же почитать в исходниках.