Что нового

Работа с окном в фоновом режиме

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А зачем такие сложности? Разве родных AutoIt функций не достаточно для этого? Я бы это назвал не MouseClickPlus(), а MouseClickMinus(). :smile:
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
r35p3ct сказал(а):
Да вон она в спойлере...
Ах, эти спойлеры, ненавижу, их не видно :smile:. Прошу прощения, если не ошибаюсь когда то мы пользовались этим :smile:, точнее уделили несколько часов тому чтобы потратить время на настройку этой UDF, но в итоге пришли к выводу что лучше использовать простые маузклики, поскольку для евы остальное - смертиподобно.
Эта UDF если мне опять же не изменяет память написана изначально для Д2, она требует учитывать там различные отступы (например на ширину окна) и тд. Она достаточно сырая и требует доработки (по крайней мере в еве она у нас работала не корректно) и тестов.
Для какой игры кстати?

Собственно я нашел, вот как она у нас выглядела когда мы ее тестили и забросили по ненадобности:
Код:
Opt("MouseCoordMode", 0)
;===============================================================================
;
; Function Name:  _MouseClickPlus()
; Version added:  0.1
; Description:    Sends a click to window, not entirely accurate, but works 
;                 minimized.
; Parameter(s):   $WinTi     =  Title of the window to send click to
;                 $Button     =  "left" or "right" mouse button
;                 $X          =  X coordinate
;                 $Y          =  Y coordinate
;                 $Clicks     =  Number of clicks to send
; Remarks:        You MUST be in "MouseCoordMode" 0 to use this without bugs.
; Author(s):      Insolence <[email protected]>
;
;===============================================================================
$WinTi = "EVE"

_MouseOp($WinTi, "Click", "Left", 2, 773, 206-22)
	
Func _MouseOp($WinTi,$CType,$Button,$Clicks, $X1, $Y1 ,$X2=0 , $Y2=0)
	Local $LB       =  0x0001	;LeftButton
	Local $RB       =  0x0002	;RightButton
	Local $LBDown   =  0x0201	;LB Down
	Local $RBDown   =  0x0204	;RB Down
	Local $LBUp     =  0x0202	;LB Up
	Local $RBUp     =  0x0205	;RB Up
	Local $MM   	=  0x0200	;MouseMove
  	Local $i    	=  0
	
	Select 
	Case $Button = "Left"
		$Button     =  $LB
		$ButtonDown =  $LBDown
		$ButtonUp   =  $LBUp
	Case $Button = "Right"
		$Button     =  $RB
		$ButtonDown =  $RBDown
		$ButtonUp   =  $RBUp
	EndSelect
  
	Select
	Case $CType = "Click"
		For $i = 1 to $Clicks
			DllCall("user32.dll","int","SendMessage","hwnd",WinGetHandle($WinTi),"int",$MM,"int",0,"long",_MakeLong($X1, $Y1))
			Sleep(100)
			DllCall("user32.dll","int","SendMessage","hwnd",WinGetHandle($WinTi ),"int",$ButtonDown,"int",$Button,"long",_MakeLong($X1, $Y1))
			DllCall("user32.dll", "int", "SendMessage","hwnd",WinGetHandle( $WinTi ),"int",$ButtonUp,"int",$Button,"long",_MakeLong($X1, $Y1))
		Next
	Case $CType = "Drag"
		DllCall("user32.dll","int","SendMessage","hwnd",WinGetHandle($WinTi),"int",$MM,"int",0,"long",_MakeLong($X1, $Y1))
		DllCall("user32.dll","int","SendMessage","hwnd",WinGetHandle($WinTi ),"int",$ButtonDown,"int",$Button,"long",_MakeLong($X1, $Y1))
		DllCall("user32.dll","int","SendMessage","hwnd",WinGetHandle($WinTi ),"int",$MM,"int",0,"long",_MakeLong($X2, $Y2))
		DllCall("user32.dll", "int", "SendMessage","hwnd",WinGetHandle( $WinTi ),"int",$ButtonUp,"int",$Button,"long",_MakeLong($X2, $Y2))
	EndSelect		
EndFunc

Func _MakeLong($LoWord,$HiWord)
	Return BitOR($HiWord*0x10000,BitAND($LoWord,0xFFFF))
EndFunc


;~ _MouseClickPlus($WinTi, "left", 773-3, 208-22, 1)



Func _MouseClickPlus($WinTi, $Button = "left", $X = "", $Y = "", $Clicks = 1)
  Local $LB       =  0x0001
  Local $LBDown   =  0x0201
  Local $LBUp     =  0x0202
  
  Local $RB       =  0x0002   
  Local $RBDown   =  0x0204
  Local $RBUp     =  0x0205

  Local $MM     =  0x0200
  
  Local $i                = 0
  
  Select 
  Case $Button = "left"
     $Button     =  $LB
     $ButtonDown =  $LBDown
     $ButtonUp   =  $LBUp
  Case $Button = "right"
     $Button     =  $RB
     $ButtonDown =  $RBDown
     $ButtonUp   =  $RBUp
  EndSelect
  
  If $X = "" OR $Y = "" Then
     $MouseCoord = MouseGetPos()
     $X = $MouseCoord[0]
     $Y = $MouseCoord[1]
  EndIf
  
  For $i = 1 to $Clicks
     DllCall("user32.dll", "int", "SendMessage", _
        "hwnd",  WinGetHandle( $WinTi ), _
        "int",   $MM, _
        "int",   0, _
        "long",  _MakeLong($X, $Y))
        
     DllCall("user32.dll", "int", "SendMessage", _
        "hwnd",  WinGetHandle( $WinTi ), _
        "int",   $ButtonDown, _
        "int",   $Button, _
        "long",  _MakeLong($X, $Y))
        
     DllCall("user32.dll", "int", "SendMessage", _
        "hwnd",  WinGetHandle( $WinTi ), _
        "int",   $ButtonUp, _
        "int",   $Button, _
        "long",  _MakeLong($X, $Y))
  Next
EndFunc
;~ 22, 177-22 ; click
;~ 265-22,  548-3 ; drag
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
AutoIt - это вам не C/C++. Здесь DllCall() будет работать как черепаха в сравнении с родными функциями AutoIt (по процессорным меркам). А у тебя там целых три DllCall(), т.е. как три черепахи. :smile:
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Yashied сказал(а):
AutoIt - это вам не C/C++. Здесь DllCall() будет работать как черепаха в сравнении с родными функциями AutoIt (по процессорным меркам). А у тебя там целых три DllCall(), т.е. как три черепахи. :smile:
Поверь, двигает мышку и кликает эта UDF на ура и достаточно быстро, ее разве что надо доработать. Да и тем более мы же не для экшенов пишем ботов, а если учесть что бот должен работать в свернутом окне, дак там вобще не очень часто кликать нужно я думаю :smile:.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А можно какой-нибудь "Земной" пример привести, без EVE? Например с банальным блокнотом.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Какой смысл работать с блокнотом если он как раз таки поддерживает стандартные функции автоита? Смысл усложнять себе жизнь?
48.gif

А так там все достаточно просто, функция работает как и стандартный маузклик, только через длл + необходимо указать заголовок окна куда надо отправить команду.
Не вижу никакой логики в применении этой udf там где можно обойтись простым контролсэндом о_О
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Нет ну просто интересно, вот простая GUI. Можешь кликнуть по ней с помощью этой функции?
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Yashied сказал(а):
Разве родных AutoIt функций не достаточно для этого?
Да вот как раз пытаюсь разобраться какие из них можно заюзать, прошу ткнуть пальцем, ибо известным мне командам нужен хендл контролла, а тут его нельзя никак получить(может я конечно не до конца разобрался...)
Belfigor сказал(а):
Для какой игры кстати?
Узко специализированная прога по работе) Написаная на делфи, поэтому и такие сложности с контроллами. Кнопка находится на TToolbar97, надписи на ней нет, поэтому не могу вытащить ее хендл...
Так в итоге как ткнуть мышкой в фоновое приложение хоть каким нибудь способом? (скорость не важна)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
O, Delphi. :Censored: Не удивительно, что у тебя с этим проблемы. Большая прога? Есть возможность кинуть ссылку?
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Возможности нет иначе давно бы кинул(работает в сети, без сервера не запустится), поэтому колдую только на работе.
На кнопке есть вплывающая подсказка, но наверно по ней не найти ее.
Так что вот получается клик самое простое решение, но только хочется в фон...
ЗЫ Хватило бы примера с кликом хотя бы в фон калькулятора для наглядности.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Попробуй так, потом отпишись, что получается.

Код:
#Include <GUIToolbar.au3>

Global Const $sTitle = 'Super specific program that works with the server only'
Global Const $iButtonIndex = 0

$hWnd = ControlGetHandle(WinGetHandle($sTitle), '', '[CLASS:TToolbar97;INSTANCE:1]')
_GUICtrlToolbar_ClickIndex($hWnd, $iButtonIndex)
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Парадоксально но факт, в еве мне удалось кликнуть на элемент интерфейса, а вот ни в твоем примере ни в блокноте не получилось
14.gif

Хотя опять же год назад я тестил эту UDF только в еве :smile:

UPD: Попробуй использовать опцию Opt("MouseCoordMode", 0) , в EVE по другому она тыкает не туда куда надо, да и туда куда надо она тыкает с погрешностью в 5-10 пикселей.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А все потому, что WM_LBUTTONDOWN и др. работают для исходного окна, а не для элементов (controls), а в моем примере твоя функция тыкает на окно (то, что находится позади фона, фон - это Bitmap - Static Control). А бабочка находится на Bitmap'е и поэтому ничего не получается. С блокнотом тоже самое.

UPD: Opt("MouseCoordMode", 0) здесь вообще не пришей к :Censored: рукав. :smile: Window Messages его в принципе никак не могут использовать.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Yashied сказал(а):
UPD: Opt("MouseCoordMode", 0) здесь вообще не пришей к :Censored: рукав. :smile: Window Messages его в принципе никак не могут использовать.
Это совет из раздела шоманства, собственно повторное перечитывание этой темы: http://www.autoitscript.com/forum/index.php?showtopic=7112&hl=EVE%20Online&st=0 показало что у половины пользователей эта UDF работает а у половины нет, даже в Паинте ее запустить смог всего один человек, и его пример не сработал у других :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Belfigor сказал(а):
...даже в Паинте ее запустить смог всего один человек, и его пример не сработал у других...

Видимо это был автор этой функции. :smile:

В том виде, в котором эта функция есть, она НИКОГДА не будет работать в Paint'е! Чтобы это работало в Paint'е (в смысле рисовать, а не кнопки тыкать), нужно вместо

WinGetHandle($WinTi)

написать

ControlGetHandle(WinGetHandle($WinTi), '', '[CLASS:Afx:1000000:8;INSTANCE:1]')

:smile:
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Ухты, спасибо, возьму на заметку
63.gif
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Все эти WM_... сообщения нужно посылать не основному окну - WinGetHandle(), а тем элементам, на которые мы будем тыкать, т.е. ControlGetHandle().

В случае с EVE, там просто нет никаких элементов управления (я думаю). Все происходит в основном окне (ака DirectX). Поэтому эта :Censored: функция там работает "на ура". Чтобы понять как все это происходит, вот простой пример. Скомпилируй его в EXE и попробуй с помощью своей функции тыкнуть куда-нибудь, заодно оценишь скорость. :sleeping:

Код:
#Include <WinAPI.au3>

Global Const $WM_LBUTTONDOWN = 0x0201

GUICreate('MyGUI', 400, 400)
GUIRegisterMsg($WM_LBUTTONDOWN, 'WM_LBUTTONDOWN')
GUISetState()

Do
Until GUIGetMsg() = -3

Func WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)

    Local $hDC = _WinAPI_GetDC($hWnd)

    For $i = -3 To 3
        For $j = -3 To 3
            DllCall('gdi32.dll', 'int', 'SetPixelV', 'hwnd', $hDC, 'int', _WinAPI_LoWord($lParam) + $i, 'int', _WinAPI_HiWord($lParam) + $j, 'dword', 0x0000FF)
        Next
    Next
    _WinAPI_ReleaseDC($hWnd, $hDC)
    Return 0
EndFunc   ;==>WM_LBUTTONDOWN



Belfigor сказал(а):
Попробуй использовать опцию Opt("MouseCoordMode", 0) , в EVE по другому она тыкает не туда куда надо, да и туда куда надо она тыкает с погрешностью в 5-10 пикселей.

Это происходит только потому, что в этой функции присутствует MouseGetPos() и только в случае, если $X = "" и $Y = "". А погрешность объясняется тем, что окно имеет бордюры и заголовок, а значение 0 означает, что отсчет координат ведется от левого верхнего угла окна, а не клиентской облати. В то время, как WM_... всегда работают относительно клиентской области (без учета заголовка и бордюров). Здесь собственно и возникает несостыковка в твои 5-10 пикселей. Правильней было бы записать Opt("MouseCoordMode", 2).

Как видишь никакого шаманства тут нет. :smile:

И еще, нет никакого смысла при каждом удобном случае писать WinGetHandle(). Достаточно один раз определить хэндл окна и в дальнейшем использовать полученное значение. Это ведь не женщина, никуда не денется :smile:, а лишние (бессмысленные) вычисления нам не нужны.

:smoking:
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Yashied сказал(а):
Попробуй так, потом отпишись, что получается.

Код:
#Include <GUIToolbar.au3>

Global Const $sTitle = 'Super specific program that works with the server only'
Global Const $iButtonIndex = 0

$hWnd = ControlGetHandle(WinGetHandle($sTitle), '', '[CLASS:TToolbar97;INSTANCE:1]')
_GUICtrlToolbar_ClickIndex($hWnd, $iButtonIndex)

Результат таков, по этой панели скрипт пытается куда в начало ее кликать, проделал эксперимент с похожей панелью, у которой в начале есть кнопка, он кликнул на кнопку, а у этой в начале текст, вроде лейбла, увеличение ButtonIndex ничего не дало.
UPD: Попробывал ClickAccel,ClickButton эффект одинаковый( Походу это и не кнопка, может и картинка)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Попробуй ради интереса функцию Belfigor'а, только вместо

WinGetHandle($sTitle)


напиши

ControlGetHandle(WinGetHandle($sTitle), '', '[CLASS:TToolbar97;INSTANCE:1]')

Возможно кликнет куда надо.
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Yashied сказал(а):
Попробуй ради интереса функцию Belfigor'а, только вместо

WinGetHandle($sTitle)


напиши

ControlGetHandle(WinGetHandle($sTitle), '', '[CLASS:TToolbar97;INSTANCE:1]')

Возможно кликнет куда надо.
Код:
$hWnd1 = ControlGetHandle(WinGetHandle('Title'), '', '[CLASSNN:TButton3]')
WinSetState($hWnd1, '', @SW_DISABLE)
ControlClick($hWnd1, '', '[CLASSNN:TButton3]')
WinSetState($hWnd1, '', @SW_ENABLE)

На кнопку жмет) с WinGetHandle не работает.
Но вот как быть с псевдо-кнопкой на тулбаре?
 
Верх