Что нового

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

Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Все я вроде со своей проблемой справился :thumbs_up:
Код:
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#Include <date.au3>
#include <GuiEdit.au3>


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

Global $titl = "Internet Explorer",$klass = "MacromediaFlashPlayerActiveX2",$c , $pos[2], $x, $y,$iX, $iY
$Form1 = GUICreate("Координатор", 208, 278, 419, 182)
$Edit1 = GUICtrlCreateEdit("", 16, 8, 177, 233, BitOR($ES_AUTOVSCROLL,$ES_WANTRETURN,$WS_VSCROLL))
GUISetState(@SW_SHOW)

While GUIGetMsg() <> $GUI_EVENT_CLOSE
	$pos[0] = 418 ;координата Х
	$pos[1] = 269 ;координата Y
	Sleep(10)
	_WinAPI_PixelGetColor($pos[0],$pos[1])
	GUICtrlSetData($Edit1,$iX&","& $iY&"  "&$pos[0]&","&$pos[1]&" "& $C)
WEnd

Func _WinAPI_PixelGetColor($x,$y) ;работает в неактивном(активном) окне с визуально видимыми точками
	Local $Struct = DllStructCreate("int X;int Y")
	$Ckoord = ControlGetPos( $titl, "", $klass) ; тут привязаться к окну и элементу окна
	$Wkoord = WinGetPos( $titl )                ; чтоб координаты стали относительные
	$iX = $x + $Ckoord[0] + $Wkoord[0] + 4       ; пересчет на относительные координаты
	$iY = $y + $Ckoord[1] + $Wkoord[1] + 23      ; с учетом бордюра(4) и титульной строки (23)
	DllStructSetData($Struct, "X", $iX)
    DllStructSetData($Struct, "Y", $iY)
    _WinAPI_ScreenToClient($titl, $Struct)
    $iX = DllStructGetData($Struct, "X")
    $iY = DllStructGetData($Struct, "Y")
    $c = PixelGetColor ($iX, $iY)
    Return $c ;возвращает цвет точно такой же как и PixelGetColor
EndFunc

А вариант со скриншотом у меня не проходит ( Комп слишком слабый и графика встает колом... Вот еслиб область скриншота уменьшить(желательно до 1 точки) :smile:
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Пробывал такое решение, только проблемма в том, что значения 4 и 23 для каждого браузера и для каждого пользователя будут разные, у меня вот было 8 и 31
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
NoMad73rus сказал(а):
Пробывал такое решение, только проблемма в том, что значения 4 и 23 для каждого браузера и для каждого пользователя будут разные, у меня вот было 8 и 31
Хм... Интересно это зависит от настроек проводника(или виндоса) или это стандартные значения для каждого проводника? На сколько я понял от настроек винды.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
NoMad73rus [?]
проблемма в том, что значения 4 и 23 для каждого браузера и для каждого пользователя будут разные
Это не проблема, я обычно использую такой метод:

Код:
Func _WinAPI_PixelGetColor($x, $y, $titl, $klass) ;работает в неактивном(активном) окне с визуально видимыми точками
    Local $Struct = DllStructCreate("int X;int Y")
    $Ckoord = ControlGetPos( $titl, "", $klass) ; тут привязаться к окну и элементу окна
    $Wkoord = WinGetPos( $titl )                ; чтоб координаты стали относительные
    $WClient = WinGetClientSize( $titl )                ; клиентская часть окна
	$iBorder = ($Wkoord[2] - $WClient[0]) / 2 ;получаем ширину бордюра
	$iCaption = ($Wkoord[3] - $WClient[1]) - $iBorder ;получаем высоту заголовка окна
    $iX = $x + $Ckoord[0] + $Wkoord[0] + $iBorder       ; пересчет на относительные координаты
    $iY = $y + $Ckoord[1] + $Wkoord[1] + $iCaption      ; с учетом бордюра(4?) и титульной строки (23?)
    DllStructSetData($Struct, "X", $iX)
    DllStructSetData($Struct, "Y", $iY)
    _WinAPI_ScreenToClient($titl, $Struct)
    $iX = DllStructGetData($Struct, "X")
    $iY = DllStructGetData($Struct, "Y")
    $c = PixelGetColor ($iX, $iY)
    Return $c ;возвращает цвет точно такой же как и PixelGetColor
EndFunc


Можно ещё конечно использовать _WinAPI_GetSystemMetrics.

P.S
А не проще воспользоваться опцией PixelCoordMode, результат тот же:

Код:
Func _WinAPI_PixelGetColor($iX, $iY, $vTitle, $vCtrlID) ;работает в неактивном(активном) окне с визуально видимыми точками
	Local $iOpt = Opt("PixelCoordMode", 0)
	Local $hControl = ControlGetHandle($vTitle, "", $vCtrlID)
	If @error Then Return SetError(1, 0, 0)
	
	Local $nColor = PixelGetColor($iX, $iY, $hControl)
	Opt("PixelCoordMode", $iOpt)
    Return $nColor
EndFunc
 
Автор
P

pgs2

Новичок
Сообщения
29
Репутация
0
Конечно проще :rofl:
В школе английский учить надо было, сам бы читать смог справку :'(
 

Dador

Новичок
Сообщения
6
Репутация
4
Есть решение гораздо проще и быстрее, правда для него есть условие - окно должно быть видно, но не обязательно активно. С опцией PixelCoordMode не работало.
Вот пример (кусок кода выдрал, но думаю понятно):
Код:
$listWindows=WinList($sTitle)
	For $wind=1 To $listWindows[0][0] Step 1
			$clientsize=WinGetClientSize($listWindows[$wind][0])
			$pos=WinGetPos($listWindows[$wind][0])
			$headsize=$pos[3]-$clientsize[1]
			$coorWindows[$wind][0]=$pos[0]
			$coorWindows[$wind][1]=$pos[1]+$headsize
	Next

Func getcolor($coor,$wind)
		Return Hex(PixelGetColor( $coor[0]+$coorWindows[$wind][0], $coor[1]+$coorWindows[$wind][1], $listWindows[$wind][0]),6);
EndFunc
;$coor - координаты
;$coorWindows - что надо добавить к координатам, чтобы они стали относительно к экрану (т.е. для ширины X координата, для высоты X координата + верхняя штучка окна от винды)
;$listWindows - список окон


p.s. когда писал сообщение не заметил что есть и 2ая страница...)
 

swg

Новичок
Сообщения
8
Репутация
0
killbond сказал(а):
Я знаю! :laugh:
1. Снять скриншот неактивного окна, что делает функция _WinCapture вот в этом примере:
Не мешало бы указать первоисточник 2007 года если не ошибаюсь.
Не работает в win2008 серв. Подозреваю не работает и в 7.
 

kimv2

Новичок
Сообщения
3
Репутация
0
попробовал функцию _PixelGetColorEx от killbond'a на одной машине win7x64, все работает как часы. а на второй winXP sp3 функция в 99 из 100 случаев возвращает 0, причем только в клиенте игры. в остальных окнах нормальный результат. буду признателен, если подскажете в какую сторону копать и как это исправить
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
kimv2 сказал(а):
попробовал функцию _PixelGetColorEx от killbond'a на одной машине win7x64, все работает как часы. а на второй winXP sp3 функция в 99 из 100 случаев возвращает 0, причем только в клиенте игры. в остальных окнах нормальный результат. буду признателен, если подскажете в какую сторону копать и как это исправить
О какой функции идёт речь? Не видя её вряд ли кто то сможет что то посоветовать. И потом вы уверены, что это продолжение этой темы?
 

kimv2

Новичок
Сообщения
3
Репутация
0
прошу прощения. просто функция эта неоднократно тут выкладывалась.
тестовый скрипт выглядит как:
Код:
#include <WinAPIEx.au3>
$hWnd = WinGetHandle("abc") 

While 1
   $c =  _PixelGetColorEx (100, 100, $hWnd)
	MsgBox(0,"",$c)
	sleep(700)
WEnd

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, $hCDC)
    _WinAPI_DeleteDC($hCDC)
	_WinAPI_DeleteObject($hBMP)
    Return $sColor
EndFunc

проблема как показали тесты только в 3д приложениях. на одной машине всё время возвращает нормальное значение. на другой, то в 70% случаях, то 1 раз выдаст значение, а потом начинает писать нули, после запуска скрипта. железо на обоих по производительности примерно одинаково. грешил на вин ХП, но при установки 7, directx11, .net ситуация не изменилась.
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Попробуй поставить в цикле с функцией паузу
Код:
Sleep(500)

А вообще это не самая лучшая реализация этого действия...
Я сделал так: http://autoit-script.ru/index.php?topic=4462.0
Вроде сейчас работает на всех машинах.
 

edward_freedom

Осваивающий
Сообщения
200
Репутация
44
NoMad73rus
Ты лучше расскажи, как сделал, чтобы и на Xp и 7 _PixelGetColorEx одни цвета показывал :scratch:
 

kimv2

Новичок
Сообщения
3
Репутация
0
да пробовал и 1 секунду ставил. не помогает. и разбивку на 2 функции попробовал, всёравно возвращает нули.
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
А AutoIt Window Info нормально ловит цвет на этой машине? Обычный PixelGetColor что выдаёт?
 

_ToBe_

Осваивающий
Сообщения
142
Репутация
35
Решил поэкспериментировать, была задача брать пиксель в клиентской области неактивного окна, в итоге поменял несколько значение и получилось :smile:
Может кому пригодится :smile:

Код:
Func _detekt ($iX, $iY)
        $sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
        Return $sColor
EndFunc

Func _BitmapWin()
    _WinAPI_DeleteDC($hCDC)
    _WinAPI_DeleteObject($hBMP) ; очищаем битовый массив
    $iWidth = _WinAPI_GetClientWidth($hWnd)     ;Тут поменял
    $iHeight = _WinAPI_GetClientHeight($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", 1)  ; и тут "0" на "1" изменил :)
    $sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
    _WinAPI_ReleaseDC($hWnd, $hDDC)
EndFunc
 

Vick

Новичок
Сообщения
1
Репутация
0
Всем доброго времени суток. Перепробовал разные методы, но в 3D приложениях выдает чёрные скриншоты, есть ли способ обойти это ограничение?
Или всё же способ получить цвет пикселя в неактивном приложении, рассматриваются варианты на Net языках...
 
Верх