Что нового

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

Yashied

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

Код:
#Include <GUIToolbar.au3>
#Include <WinAPI.au3>

Global Const $sTitle = 'Super Specific Program'
Global Const $X = 50
Global Const $Y = 25

$hWnd = ControlGetHandle(WinGetHandle($sTitle), '', '[CLASS:TToolbar97;INSTANCE:1]')
DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0200, 'int', 0, 'dword', _WinAPI_MakeLong($X, $Y))
Sleep(50)
DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0201, 'int', 1, 'dword', _WinAPI_MakeLong($X, $Y))
Sleep(50)
DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0202, 'int', 1, 'dword', _WinAPI_MakeLong($X, $Y))


У меня это работает. Тебе необходимо только подобрать координаты $X и $Y твоей несчастной кнопки, куда собственно должна кликнуть мышка. Координаты определяются относительно левого верхнего угла TToolbar97.
 

vcomp71

Осваивающий
Сообщения
431
Репутация
25
По поводу фонового окна. Во всех примерах, сначала команда run идет, а потом окно желается фоновым. А нет механизма сразу запустить программу в фоновом режиме, и получить ее pid? Чтобы потом и хендл отлавливать окон и нажатия туда слать?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Что-то вроде этого.

Код:
#Include <Constants.au3>
#Include <WinAPI.au3>

$Pid = Run('Notepad.exe', '', @SW_HIDE)
If Not WinWait('Untitled - Notepad', '', 3) Then
	Exit
EndIf
$hWnd = WinGetHandle('Untitled - Notepad')
_WinAPI_SetWindowPos($hWnd, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_SHOWWINDOW))
 

vcomp71

Осваивающий
Сообщения
431
Репутация
25
А вот эта строчка для чего?
WinAPI_SetWindowPos($hWnd, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_SHOWWINDOW))


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

Vlasssov сказал(а):
А вот эта строчка для чего?
WinAPI_SetWindowPos($hWnd, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_SHOWWINDOW))
Тут ошибка, вот как заработало

WinAPI_SetWindowPos($hWnd, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_HIDEWINDOW))
 

Yashied

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

Код:
_WinAPI_SetWindowPos($hWnd, $HWND_BOTTOM, 0, 0, 0, 0, BitOR($SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_SHOWWINDOW))


Эта строчка нужна для того, чтобы показать окно на заднем плане без изменения фокуса. Если тебе нужно невидимое окно, то она вообще тебе не нужна.
 

Minek

Новичок
Сообщения
10
Репутация
0
Возможно ли предотвращать перехват фокуса IE8 при выполнении скрипта? Использую библиотеку IE.au3.
Скрипт выполняет команды каждую секунду, с каждым действием окно IE вылезает на передний план и становится активно. Свернутое работает, но хотелось бы видеть, что там происходит, да и работать на этом компьютере в других программах.
Пытался переползти под FF 3.5, ff.au3, но там беда с русским. Ни ссылок, ни состояния экрана в текстовом виде не получить по человечески. На оперу вообще ничего путного не нашел. :(
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
OffTopic:

При создании окна через _IECreate($URL, 0, 0) окна IE вообще не будет видно и соотв. все действия будут в фоне производиться.
 

Minek

Новичок
Сообщения
10
Репутация
0
Попробую еще один вопрос задать.
Возможно ли передать нажатие клавиши в какой то определенный фрейм текущей странички IE? Например нужно обновить CTRL+F5 какой нить фрейм.
Такая конструкция работает, но обновляет все окошко -

$hWnd = WinGetHandle("Новости")
WinActivate("Новости")
ControlSend($hwnd, "", "", "{F5}")

а вот такая не работает:

$oIE = _IEAttach ("Новости","windowtitle")
$oFrame = _IEFrameGetObjByName ($oIE, "tape")
WinActivate("Новости")
ControlSend($oFrame, "", "", "^{F5}")

К библиотеке IE.au3 просьба не отсылать - хочется разобраться именно с вводом через controlsend, если конечно это вообще возможно.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
А зачем использовать ControlSend?
Я так понимаю, стоит задача Refresh только одного фрейма?
Тогда может так:
Код:
#include <IE.au3>

$IE =_IECreate( " http://you_domain/index_file.html " )
     _IELoadWait ($IE)  ; Hello Neo! Attention will now reload...
     Sleep(2000)
     $Frames = _IEFrameGetObjByName ($IE, "mainFrame")
     _IEAction ($Frames, "refresh") ;Matrix Reloaded!
     _IELoadWait ($IE)
 

Minek

Новичок
Сообщения
10
Репутация
0
Потому что любое действие через IE.au3 помещает окошко IE на передний план и передает на него фокус. Что достало. :-X А через controlsend вроде как оно где было, там и осталось.
 

Yura

Знающий
Сообщения
36
Репутация
7
Не срабатывал ControlClick в игру, на которую писал бота. При поиске решений наткнулся на эту старую тему и исходя из здесь написанного разобрался в ситуации, хочу этим поделится и хочу еще кое-что уточнить.

В MSDN нашел описание функций PostMessage и SendMessage. Они обе отправляют сообщение по указанному дескриптору окна. Разница в том, что PostMessage помещает сообщение в очередь и сразу возвращается, а SendMessage отправляет сообщение и ждет, пока целевое окно это сообщение обработает. Как вариант сообщением может быть команда о нажатии кнопки мыши или перемещении.
В либе WinAPI.au3 есть _WinAPI_PostMessage, которая работает в фоновых окнах:
Код:
; #FUNCTION# ====================================================================================================================
; Author ........: Paul Campbell (PaulIA)
; Modified.......: jpm
; ===============================================================================================================================
Func _WinAPI_PostMessage($hWnd, $iMsg, $wParam, $lParam)
	Local $aResult = DllCall("user32.dll", "bool", "PostMessage", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0]
EndFunc   ;==>_WinAPI_PostMessage


Теперь посмотрим на UDF MouseClickPlus. Как уже написал Yashied, там лишние WinGetHandle, настройка привязки координат мыши и надо понимать какой именно Handle нам нужен: окна или контрола. Если не ошибаюсь по памяти, то и объявление локальных переменных типа Local $LBDown = 0x0201 там лишнее, они уже есть в WindowsConstants.au3. Но главное что есть в этой MouseClickPlus - это DllCall, который из user32.dll вызывает функцию SendMessage.
Поэтому у меня возникло мнение, что эта MouseClickPlus просто ниочем, _WinAPI_PostMessage делает ту же работу, только сразу возвращается к программе после вызова. А если в вызове ее dll поменять PostMessage на SendMessage, то наверняка будет делать абсолютно то же самое.

В другой теме видел вопрос о SendInput для эмуляции нажатия мышки. Из того что прочитал:
SendInput симулирует события нажатия мышки/клавиатуры на более низком уровне. Если воспользоваться функциями GetKeyState или GetAsyncKeyState, то нажатие через SendInput должно отобразится как и реальное нажатие пользователя. Для сравнения фейково нажатая кнопка через SendMessage там не отображается. От реального нажатия SendInput отличается тем, что не выставляет какого-то флага. Также SendInput как и реальная клавиатура и мышь может работать только с активным окном.

Теперь к возникшим вопросам.
1) Нашел в AutoIt функцию _SendMessage:
Код:
; #FUNCTION# ====================================================================================================================
; Author ........: Valik
; Modified.......: Gary Frost (GaryFrost) aka gafrost
; ===============================================================================================================================
Func _SendMessage($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult")
	Local $aResult = DllCall("user32.dll", $sReturnType, "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wParam, $lParamType, $lParam)
	If @error Then Return SetError(@error, @extended, "")
	If $iReturn >= 0 And $iReturn <= 4 Then Return $aResult[$iReturn]
	Return $aResult
EndFunc   ;==>_SendMessage

У меня она работает только в активном окне почему-то. Но в ней используется не SendMessage, а SendMessageW. В MSDN пишет, что "Unicode and ANSI names - SendMessageW (Unicode) and SendMessageA (ANSI)". Пожалуйста, тыкните где можно почитать что это или обьясните.

2) Второй вопрос. В нескольких примерах перед кликом мышкой видел:
Код:
_WinAPI_PostMessage($hWnd, $WM_SETCURSOR, $hWnd, _WinAPI_MakeLong($HTCLIENT, $WM_LBUTTONDOWN))
или прямо в этой теме
Код:
DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0200, 'int', 0, 'dword', _WinAPI_MakeLong($X, $Y)) ;MOUSEMOVE

Я понимаю зачем перемещать курсор при реализации например mousedrag. Но зачем его перемещать перед обычным кликом в фоновом окне? Вроде и без этого работает. Может это делается для большей схожести с работой человека, типа маскировка от антикликеров?))

3) Насколько я понял, ControlClick это реализация функции из 2-х команд, причем между ними нет паузы ($Sleep = 0):
Код:
Func MouseLeftClick3($hWnd, $X, $Y, $Sleep)
	_WinAPI_PostMessage($hWnd, $WM_LBUTTONDOWN, 0, _WinAPI_MakeLong($X, $Y))
	Sleep($Sleep)
	_WinAPI_PostMessage($hWnd, $WM_LBUTTONUP, 0, _WinAPI_MakeLong($X, $Y))
EndFunc

потому что в таком виде в этой игре у меня не кликает, а кликает только если дать между командами слип хоть 1 мс. Но как посмотреть реализацию команд ControlClick, MouseClick и т.д., которых я не нашел в папке AutoIT3\Include\ и они не включаются в проект через #include?
 

masheen

Новичок
Сообщения
25
Репутация
0
Yura сказал(а):
Не срабатывал ControlClick в игру, на которую писал бота....

Юра а в итоге, какой код то у тебя начал работать? какой начал кликать в свернутом окне?
 
Верх