Что нового

Использование DllCall для эмуляции клавиатуры

xamd

AION bot developer
Сообщения
66
Репутация
24
Дорогие товарищи, очень нужна помощь: надо отправить в свёрнутое окно с титулом AION Client нажатие клавиши пробел (0х20, если не ошибаюсь).

Насколько я понимаю, это реально сделать только через DllCall. Находил тысячу и один скрипт, как сделать это для мыши, но, черт побери, как сделать это для клавиатуры? )

Если возможно оформить ответ в виде функции _Send($Handle, $key), буду безумно благодарен.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
xamd
я не вник в суть темы и в ответ. возможно Yuri именно ЛС и имел в виду, что конечно попирает концепцию форума и открытости. все лишнее потер. придерживайтесь основного русла беседы, коллеги ;)
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
С превеликим удовольствием. У тебя самого не найдется решения? Мне нужно с помощью DllCall отправить в свёрнутое приложение команду(ну, скажем, пробел). Как реализовать?
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
"возможно Yuri именно ЛС и имел в виду, что конечно попирает концепцию форума и открытости."

Извините, но про что это? Если можно, то в личку.

По поводу нажатия в свернутое окно:
тут не надо Dll. Щас пример для блокнота оформлю.

Код:
Run("Notepad.exe")
WinWaitActive("Безымянный - Блокнот")
Sleep(2000)
WinSetState("Безымянный - Блокнот", "", @SW_MINIMIZE)
ControlSend("Безымянный - Блокнот", "", "Edit1", "{SPACE}")
ControlSend("Безымянный - Блокнот", "", "Edit1", "Пробел")

Так вроде наглядно.
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
Черт, тут ты знаешь класс объекта, в который пишешь, в данном случае Edit1, да и активировать необязательно в таком случае, можно обычным controlsend'ом сделать. А я не знаю класса объекта, и хочу обойтись без активации окна. Есть способ с DllCall'ом, кто-нибудь его знает? Именно на примере клавиатуры.
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
Есть такая штука, как AutoIt Window Info
С помощью его можно класс чего-то определенного узнать.
Возможно Вас Win32API интересует.
Тогда Вам тему вопроса надо изменить.
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
Извините пожалуйста, но вы начинаете меня подбешивать. Я знаю, о WI, но в приложениях типа игр(в моём случае MMORPG AION) внутриигровая структура не показывается через эту замечательную программу. Отсюда следует, что controlsend не работает, а send работает только при активном окне, а т.к. я пишу бота для вышеуказанного приложения, мне принципиально важно, чтобы он работал в свёрнутом окне, и вариант "развернул-нажал-свернул" не прокатит. Я уже перерыл кучу источников и не могу найти ни 1 рабочего скрипта для нажатия клавиши ПРОБЕЛ в своём приложении. Я могу(как ни странно) controlsend'ом посылать любые буквы и цифры, но, черт побери, не системные клавиши. Теперь ясен вопрос? Поэтому мне нужен DllCall, используя вызов библиотеки user32 можно каким-то образом сэмулировать нажатие клавиши по её вирт. коду(у пробела он 0x20). Пожалуйста, если вы можете мне помочь - помогите, если нет - извините, но вы ошиблись темой.

Прошу прощения за грубость, но это Ваш второй ответ не в попад, а я уставший, после работы и маюсь этим уже вторые сутки :smile:


Добавлено:
Сообщение автоматически объединено:

r35p3ct сказал(а):
xamd [?]
А я не знаю класса объекта, и хочу обойтись без активации окна.
Код:
ControlSend("ЗАГОЛОВОК ОКНА", "", "", "{SPACE}")

0 реакции
даже с

Opt("SendKeyDelay", 0)
Opt("SendKeyDownDelay", 100)
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
Вот теперь Ваш вопрос с пояснениями гораздо яснее выглядит.
И теперь более-менее стало понятно.
Прошу простить за нетактичность.
Прошу не счесть за флуд модераторов.
Юрий.
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
xamd [?]
0 реакции
даже с
Код:
$hWnd=WinGetHandle('Точное название заголовка');Хендл окна
$class='[class:КЛАСС ОКНА]';Либо через класс окна
Opt("SendKeyDelay",150)
ControlSend($hWnd,'','','{SPACE}',0)
ControlSend($class,'','','{SPACE}',0)

Если не работает, значит либо кривое название окна, класса либо какая то защита от таких манипуляций. Эти варианты 100% рабочие.
Желательно увидеть данные из Au3Info, чтобы не гадать.
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
защита от таких манипуляций стоит, поэтому и хочу через dllcall.
я прекрасно знаю как controlSend'ом отправить, но он не работает в моем случае.
Не просто же так тему назвал DllCall. Все остальные варианты уже пробывал
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
в блокнот исправно пробел приходит:
Код:
$hwnd = ControlGetHandle('Безымянный', '', 'Edit1')
DllCall("user32.dll", "long", "SendMessage", _
                "hwnd", $hwnd, _
                "int", 0x0102, _
                "int", 0x20, _
                "int", 0)

Но ControlSend это скорее всего тоже самое.
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
не проходит (
а через PostMessage знаешь как можно сделать?


Код:
; #FUNCTION# ====================================================================================================================
; Name...........: SimulKey
; Description ...: Simulate a Key-Send to a specified handle in the Background
; Author ........: Felix Lehmann
; Modified.......: If you modify this Script, please enter your name here
; Remarks .......: -
; Related .......: -
; Parameters ....: $hwnd = Specified Window to Send to
; ...............: $key = Key or String to Send (If String $string have to be enabled [see $string])
; ...............: $string = Set this to 1 If your "$key" is a string
; ...............: $state = Set this to 'up' or 'down' if u want a special event | Default is press the Key 1 Time
; ...............: $delay = The delay to hold the key down
; Return Values .: 1 = Done | -1 = Couldn't load user32.dll
; Link ..........; -
; ===============================================================================================================================
Func SimulKey($hWnd, $key, $string = 0, $state = 'skip', $delay = 10)
	;//Open DLL (user32)
	$user32 = DllOpen('user32.dll')
	If $user32 = -1 Then
		SetError(-1, 1, -1)
	EndIf

	;//Handle Special Keys
	Switch StringLower($key)
		Case 'enter'
			$WM_ENTER = 0x0d
			$dCall = DllCall($user32, 'int', "MapVirtualKey", 'int', $WM_ENTER, 'int', 0)
			$lParam = BitOR(BitShift($dCall[0], -16), 1)
		Case 'space'
			$WM_SPACE = 0x20
			$dCall = DllCall($user32, 'int', "MapVirtualKey", 'int', $WM_SPACE, 'int', 0)
			$lParam = BitOR(BitShift($dCall[0], -16), 1)
		Case 'tab'
			$WM_TAB = 0x09
			$dCall = DllCall($user32, 'int', "MapVirtualKey", 'int', $WM_TAB, 'int', 0)
			$lParam = BitOR(BitShift($dCall[0], -16), 1)
			;//Handle Standard Keys
		Case Else
			;//Stringmode 1
			If $string = 1 Then
				$split = StringSplit($key, "")
				For $ctn = 1 To $split[0]
					$split[$ctn] = Asc(StringLower($split[$ctn]))
				Next
				For $ctn = 1 To $split[0]
					$dCall = DllCall($user32, 'int', "VkKeyScan", 'int', $split[$ctn])
					$lParamAsc = DllCall($user32, 'int', "MapVirtualKey", 'int', $dCall[0], 'int', 0)
					$lParam = BitOR(BitShift($lParamAsc[0], -16), 1)
					$lUpParam = BitOR($lParam, 0xC0000000)
					DllCall($user32, 'int', "PostMessage", 'hwnd', $hWnd, 'int', $WM_KEYDOWN, 'int', $dCall[0], 'int', $lParam)
					Sleep($delay)
					DllCall($user32, 'int', "PostMessage", 'hwnd', $hWnd, 'int', $WM_KEYUP, 'int', $dCall[0], 'int', $lUpParam)
					Sleep(100)
				Next
				;//Stringmode 0
			ElseIf $string = 0 Then
				$key = Asc(StringLower($key))
				$dCall = DllCall($user32, 'int', "VkKeyScan", 'int', $key)
				$lParamAsc = DllCall($user32, 'int', "MapVirtualKey", 'int', $dCall[0], 'int', 0)
				$lParam = BitOR(BitShift($lParamAsc[0], -16), 1)
			EndIf
	EndSwitch
	$lUpParam = BitOR($lParam, 0xC0000000)
	If $string = 0 Then
		Switch StringLower($state)
			Case 'skip'
				DllCall($user32, 'int', "PostMessage", 'hwnd', $hWnd, 'int', $WM_KEYDOWN, 'int', $dCall[0], 'int', $lParam)
				Sleep($delay)
				DllCall($user32, 'int', "PostMessage", 'hwnd', $hWnd, 'int', $WM_KEYUP, 'int', $dCall[0], 'int', $lUpParam)
			Case 'down'
				DllCall($user32, "int", "PostMessage", "hwnd", $hWnd, "int", $WM_KEYDOWN, "int", $dCall[0], "int", $lParam)
			Case 'up'
				DllCall($user32, "int", "PostMessage", "hwnd", $hWnd, "int", $WM_KEYUP, "int", $dCall[0], "int", $lParam)
		EndSwitch
	EndIf
	DllClose($user32)
	Return 1
EndFunc   ;==>SimulKey


вот что нашел, но у меня не работает (
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
xamd [?]
а через PostMessage знаешь как можно сделать?
просто заменив SendMessage на PostMessage

Может так получится:
Код:
$hwnd = ControlGetHandle('Безымянный', '', 'Edit1')
DllCall("user32.dll", "long", "PostMessage", "hwnd", $hwnd, "int", 0x0100, "int", 0x20,"int", 0)
DllCall("user32.dll", "long", "PostMessage", "hwnd", $hwnd, "int", 0x0101, "int", 0x20,"int", 0)
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
черт, не работает! (

Есть еще варианты, как можно отправить окну сообщение?
P.S. Как ни странно, ControlSend работает с цифрами 1-9, энтером, табом, но пробел и WASD игнорирует
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Код:
DllCall("user32.dll", 'int', 'keybd_event', 'byte', 0x20 , 'byte', 0, 'uint', 0, 'ptr', 0)

посылает только в активное окно.
 
Автор
X

xamd

AION bot developer
Сообщения
66
Репутация
24
в активное могу Send()'ом отправить
 

skype4com

Новичок
Сообщения
11
Репутация
1
to xamd: получилось ли отправить в AION пробел? Если получилось, то как?
Заметил такую вещь: можно переназначить клавиши движения на другие (WASD -> 1234), не помогает. Значит эти клавиши (управление движением) как то совсем по другому отрабатываются, явно не простым нажатием. Если активировать чат (ENTER) клавиши управления доступны(WASD+SPACE).

Немного не в тему: может пробовал в L2 кликать? Как поймать окно? Названия нету, класса нету... В активном окне могу, эт понятно.
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Немного оффтоп.
Не повезло Вам с защитой. например у меня в Lineage 2 отлично работает вот такой код (в свёрнутом виде):
Код:
$sL2Win = "[TITLE:Lineage II; CLASS:l2UnrealWWindowsViewportWindow]"
ControlSend ($sL2Win, "", "", "{F1}")


Сейчас у нас там Эвент и я на автопилоте добываю ништяки вот таким вот скриптом:
; на F1 положить "Селедущая цель"
; на F2 паложить "Лекарство купидона"

$sL2Win = "[TITLE:Lineage II; CLASS:l2UnrealWWindowsViewportWindow]" ; заголовок и класс окна
$iTimer1 = TimerInit() ; врубаем таймер для лекарств
$iTimer2 = TimerInit() ; врубаем таймер для цели

While 1 ; основной цикл программы
sleep (100) ; пауза 0,2 сек, чтобы не грузить процессор
If WinExists ($sL2Win) <> 0 Then ; если окно существует
If TimerDiff($iTimer1) >= 2000 Then ; проверка первого таймера, если прошло 2 сек, то
ControlSend ($sL2Win, "", "", "{F2}") ; посылаем нажатие клавиши F2
$iTimer1 = TimerInit() ; перезапускаем таймер
EndIf
If
TimerDiff($iTimer2) >= 5000 Then ; проверка второго таймера, если прошло 5 сек, то
ControlSend ($sL2Win, "", "", "{F1}") ; посылаем нажатие клавиши F1
$iTimer2 = TimerInit() ; перезапускаем таймер
EndIf
EndIf
WEnd
 
Верх