Что нового

[Автоматизация] Как определить цвет точки в неактивном окне?

pgs2

Новичок
Сообщения
29
Репутация
0
Название темы - есть вопрос.
Хотелось бы с примером кода.
Вот например мне надо определить цвет точки:
Код:
Dim $titl = "Window", $klass = "MacromediaFlashPlayerActiveX2"

 $koord = ControlGetPos( $titl, "", $klass)
 $posX = 374 + $koord[0]
 $posY = 455 + $koord[1]
 $Cpos = PixelGetColor ($posX, $posY)

В активном окне работает, в неактивном нет.
Какой код должен быть, чтоб определить цвет этой точки в неактивном окне?
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Даа... Либо это секретная информация не подлежащая разглашению, либо это на столько сложно, что на форуме ни кто не знает ответа :(
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
OffTopic:
Скорее второе
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Я знаю! :laugh:
1. Снять скриншот неактивного окна, что делает функция _WinCapture вот в этом примере:

Код:
#NoTrayIcon
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()

$hGUI = WinGetHandle("AutoIt Help")
WinMove($hGUI, "", @DesktopWidth-100, @DesktopHeight)

$iWidth = _WinAPI_GetWindowWidth($hGUI)
$iHeight = _WinAPI_GetWindowHeight($hGUI)

$hParent = GUICreate("WindowViewer", 500, 400)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hParent)
GUISetState()

$hBMP = _WinCapture($hGUI, $iWidth, $iHeight)
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

_GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hImage, 0, 0, $iWidth, $iHeight, 50, 50, 400, 300)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hBMP)
Sleep(3000)

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
    Local $iH, $iW, $hDDC, $hCDC, $hBMP

    If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)

    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)

    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, 0x00330008)

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)

    Return $hBMP
EndFunc   ;==>_WinCapture


2. Воспользовавшись PixelGetColor.au3 снять цвет со скрина.

Скриншот из примера идет в память, и делается, даже если часть окна уехала за границы монитора, вообщем, работает на ура! Но именно для неактивных окон, т.е. для свернутых не работает.

PixelGetColor.au3, как я почитал, умеет снимать цвет из памяти...
только я не знаю как их соединить :( помогите пожалуйста! 2-ой день копаюсь, и все никак...
Давайте напишем на эту тему UDF, пусть будет...
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
pgs2 сказал(а):
ни кто не знает ответа :(
ИМХО никак не получится.
Я полагаю, что PixelGetColor берёт данные, из видео памяти, которая в свою очередь содержит информацию о том, что мы видим на экране. И если окно не имеет фокуса или свёрнуто, то PixelGetColor берёт цвет активного пикселя, на данный момент в указанных координатах, информация о котором хранится в видео памяти.
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Работаееет!!! :laugh: :laugh: :laugh: и я даже сам не понимаю как ;D
Для неактивного окна работает, как бы его не крутили (даже если за пределами экрана), для свернутого - нет.

Код:
#NoTrayIcon
#include <WinAPIEx.au3>
#include <WinAPI.au3>

$hWnd = WinGetHandle(""); Вписать заголовок окна
$iX = 0					; Вписать Х координату окна
$iY = 0					; Вписать У координату окна
; Учитывать то, что цвета у неактивного окна ДРУГИЕ, нежели у активного!
MsgBox (0, "", "0x" & Hex(_PixelGetColorEx ($iX, $iY, $hWnd), 6 ))

Func _PixelGetColorEx ($iX, $iY, $hWnd)
	Local $hDDC, $hCDC, $hBMP
    $iWidth = _WinAPI_GetWindowWidth($hWnd)
    $iHeight = _WinAPI_GetWindowHeight($hWnd)
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)
    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)	
	$sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
	Return $sColor
EndFunc   ;==>_PixelGetColorEx


ЗЫ: WinAPIEx.au3 брал отсюда
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#include <WinAPIEx.au3>
#include <WinAPI.au3>


При использовании WinAPIEx.au3 нет необходимости писать еще и WinAPI.au3, первый включает в себя второй. Можно просто так:

Код:
#include <WinAPIEx.au3>


А трюк с PrintWindow() хорошо придумал (?). И почему я ее не включил в библиотеку...
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Да, действительно работает! :thumbs_up:
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Ха! Действительно работает и цвет выдает с одной точки одинаковый, что в активном окне, что в неактивном( просто другой не такой как PGC) НО :'( Попробовал слепить цикл опроса точки с выводом цвета в окошко Edit. Комп встает колом, несколько секунд выдает цвета, потом вместо цвета (-1) видимо ошибка. Может переполнение буфера?
Код:
While 1
$c = _PixelGetColorEx ($posX, $posY, $hWnd)
GUICtrlSetData($Edit1,$posX&","& $posY&" "& $C)
WEnd

ЗЫ: А есть исходники Autoit Window Info (или давайте тихонечко посмотрим как оно устраено :whistle:smile:? ;D
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Да с задержкой уже легче. Sleep(50) самое то. Прикрутил счетчик на 111 проверке выдает цвет 0 на 112 проверке выдает цвет -1 дальше постоянно -1 и скорость возрастает, видимо что то перестает работать.
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Я пока не разобрался, но у этой функции странная зависимость от размера окна: чем окно меньше, тем больше циклов чтения она может выполнить и, соответсвенно скорость чтения выше... чудеса :shok:
 

r35p3ct

Продвинутый
Сообщения
228
Репутация
60
Хочется получить
Код:
PixelChecksum
для фонового окна, можно это как нить переделать?
Координаты для _PixelGetColorEx считаются относительно окна? а если пиксел на контроле, который соотв. может в окне быть в разных местах, как это можно учесть?
 

killbond

Осваивающий
Сообщения
96
Репутация
32
r35p3ct сказал(а):
Хочется получить
Код:
PixelChecksum
для фонового окна, можно это как нить переделать?

Думаю, если я получу исходник PixelChecksum, то я смогу переклепать...

Координаты для _PixelGetColorEx считаются относительно окна?

Да

если пиксел на контроле, который соотв. может в окне быть в разных местах, как это можно учесть?

Координаты нужного контрола можно получить с помощью
Код:
ControlGetPos

получив координаты, можно расчитать смещение до нужного пикселя и при доступе к координатам контрола учитывать это смещение.
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Вот эта конструкция работает как автомат калашникова. Показывает цвет в любой точке любого окна если ее(точку) видно глазами. :laugh: :thumbs_up:
Код:
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#Include <date.au3>
#include <GuiEdit.au3>
#include <GuiConstantsEx.au3>

;Opt("PixelCoordMode",2)

Opt("WinTitleMatchMode",1)
Opt("WinDetectHiddenText",1)
;Opt("MouseCoordMode",2)

Global $Title = "Bla-bla-bla",$klass = "MacromediaFlashPlayerActiveX2"

$hWnd = WinGetHandle($Title)
$Form1 = GUICreate("Координатор", 208, 278, 419, 182)
$Edit1 = GUICtrlCreateEdit("", 16, 8, 177, 233, BitOR($ES_AUTOVSCROLL,$ES_WANTRETURN,$WS_VSCROLL))
GUISetState(@SW_SHOW)
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit

	EndSwitch
;$koord = ControlGetPos( $titl, "", $klass) ; тут привязаться к окну и элементу окна
$pos = MouseGetPos()                             ; чтоб координаты стали относительные  
;$pos[0] = координата Х вместо курсора
;$pos[1] = координата Y вместо курсора
;$pos[0] = $pos[0]+ $koord[0]
;$pos[1] = $pos[1] + $koord[1]

Sleep(10)
_MouseClickOnScreenCoords("Main", $hWnd, $pos[0], $pos[1], 1)
WEnd


Func _MouseClickOnScreenCoords($sButton, $hWnd, $iX, $iY, $iSpeed=10)
    Local $Struct = DllStructCreate("int X;int Y")

    DllStructSetData($Struct, "X", $iX)
    DllStructSetData($Struct, "Y", $iY)

    _WinAPI_ScreenToClient($Title, $Struct)

    $iX = DllStructGetData($Struct, "X")
    $iY = DllStructGetData($Struct, "Y")
	
    Local $iOld_Opt = Opt("MouseCoordMode", 2)
    $Cpos = PixelGetColor ($iX, $iY)
	GUICtrlSetData($Edit1,$iX&","& $iY&"  "& $Cpos)

    Opt("MouseCoordMode", $iOld_Opt)
EndFunc

Осталось прикрутить это к конкретному окну, к относительным координатам конкретного элемента (как у меня было в вопросе) и вместо курсора использоать координаты конкретной точки.
Уже не соображаю сам, ушел спать. :wacko:
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Не понимаю, если ты функции _MouseClickOnScreenCoords передаешь уже впринципе, готовые координаты для клика, зачем тебе цвет точки в неактивном окне? И вообще цвет этой точки?

И потом, в этой же функции лучше сделать так - вместо
Код:
GUICtrlSetData($Edit1,$iX&","& $iY&"  "& $Cpos)

поставить
Код:
GUICtrlSetData ( $Edit1, @CRLF & $iX & "," & $iY & "  " & $Cpos )

Красивее будет :smile:

А цикл можно было бы короче и рациональнее сделать:
Код:
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    $pos = MouseGetPos()
    ;$koord = ControlGetPos( $titl, "", $klass)
    Sleep(10)
    _MouseClickOnScreenCoords("Main", $hWnd, $pos[0], $pos[1], 1)
WEnd


Но, это не мой скрипт... у каждого свой стиль.
OffTopic:
И что это за игра такая, которая требует кликанья каждые 10 милисекунд :blink:
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Частота кликанья как я понимаю не принципиальна. Задача - кликнуть (туда-то), когда там-то такой-то цвет. И всё это в конкретной флешке, находящейся в неактивном окне (а в идеале и вовсе в свёрнутом).
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
NoMad73rus сказал(а):
Частота кликанья как я понимаю не принципиальна. Задача - кликнуть (туда-то), когда там-то такой-то цвет. И всё это в конкретной флешке, находящейся в неактивном окне (а в идеале и вовсе в свёрнутом).
Абсолютно справедливо! Принципиальна скорость опроса, так как в циклы опроса цвета точки( которая еще динамично меняеться и иногда очень быстро), приходиться вставлять опрос по другим событиям, вызванным игрой или пользователем. И я уже смирился с недоступностью осуществить это в свернутом окне пусть это будет хотя бы работать в неактивном. Что в общем то у меня в последнем примере и получилось. Только я плохо понимаю как это работает :'( Надергал кусков скрипта из примеров что то изменил, заработало. Теперь мышка не нужна (это просто для наглядности прилеплено было), надо конкретные координаты привязывать. И через
Код:
$koord = ControlGetPos( $titl, "", $klass)
;$pos[0] = $pos[0]+ $koord[0]
;$pos[1] = $pos[1] + $koord[1]

задать поправку на относительные координаты флеша. Только что то подклинило, не могу привязаться к окну и флешу. Мышка подхватывает относительные координаты того окна, над которым курсор висит :wacko:


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

killbond сказал(а):
Не понимаю, если ты функции _MouseClickOnScreenCoords передаешь уже впринципе, готовые координаты для клика, зачем тебе цвет точки в неактивном окне? И вообще цвет этой точки?
От _MouseClickOnScreenCoords одно название осталось, она уже не кликает ни куда ))) (переименовать забыл) Нечем ей кликать. Зато по координатам из этой функции PGC в неактивном окне работает. И мне не надо координаты для клика мне нужен именно цвет точки по координатам. Логика реакций бота, на ход игрового процесса, построена на сканировании определенных точек.
 

Guezt

Продвинутый
Сообщения
335
Репутация
82
killbond
Поправил немного твою функцию, вернее добавил одну строчку вот так:
Код:
#NoTrayIcon
#include <WinAPIEx.au3>
$i = 0
$hWnd = WinGetHandle(""); Вписать заголовок окна
$iX = 0               ; Вписать Х координату окна
$iY = 0                ; Вписать У координату окна
; Учитывать то, что цвета у неактивного окна ДРУГИЕ, нежели у активного!

For $i = 1 to 1000
ConsoleWrite( @CRLF&$i&" "&Hex(_PixelGetColorEx ($iX, $iY, $hWnd),6))
Sleep(100)
Next

Func _PixelGetColorEx ($iX, $iY, $hWnd)
    Local $hDDC, $hCDC, $hBMP
    $iWidth = _WinAPI_GetWindowWidth($hWnd)
    $iHeight = _WinAPI_GetWindowHeight($hWnd)
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight) ; создаем битовый массив
    _WinAPI_SelectObject($hCDC, $hBMP)
    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
    $sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
   _WinAPI_DeleteObject($hBMP) ; очищаем битовый массив
    Return $sColor
EndFunc   ;==>_PixelGetColorEx


теперь вроде можно делать запрос бесконечно, коментарии в функции :smile:
 

killbond

Осваивающий
Сообщения
96
Репутация
32
ААААА!!! :thumbs_up: Молодчина!!! Теперь работает, проверял на 3000 циклах! У меня есть идея, как сделать и для свернутого окна - здесь есть исходники на C#, как сделать скриншот свернутого окна, пока не проверял, но над этим поработаю.
 
Верх