来自背景/非活动/未聚焦窗口的 AutoIt PixelGetColor [英] AutoIt PixelGetColor from background/inactive/unfocused window

查看:29
本文介绍了来自背景/非活动/未聚焦窗口的 AutoIt PixelGetColor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PixelGetColor has an optional parameter hwnd (handle of window the pixel is read from). Therefore I assume it is possible to read from unfocused windows (i.e not minimized, but behind another window); but I can't get it to work like that.

  • Is my assumption wrong? If not, how would this be done? If so;

    • why the hwnd parameter?
    • is there another method involving pixel recognition?

解决方案

Abstract

You want to create a simple empty bitmap and transfer the DeviceContext content of the hidden window into it. Then you can read any value at any position.

Creating an empty bitmap

Includes

We will need to include the WinAPI definitions and constants.

#include <WinAPI.au3>
#include <WindowsConstants.au3>

And that's about it.

Initial struct

Now we have to create a new DLL struct from the $tagBITMAPINFO template. We need to fill the struct with the bitmaps parameters. To ensure compatibility across all AutoIt version, I will access the struct items by index.

1) Create compatible Device Context:

Local $hCompDC = _WinAPI_CreateCompatibleDC(0)

2) Create struct from template, fill with data:

Local $tBMI = DllStructCreate($tagBITMAPINFO)
DllStructSetData($tBMI, 1, DllStructGetSize($tBMI) - 4) ; size of struct
DllStructSetData($tBMI, 2, 400) ; width
DllStructSetData($tBMI, 3, 400) ; height
DllStructSetData($tBMI, 4, 1)
DllStructSetData($tBMI, 5, 32)  ; bits per pixel

You need to adjust the width and height parameters to match the region you want to transfer. In your case, I guess the size of the window would be a good choice, though the smaller the region, the faster.

3) Create GDI Object

Create a CreateDIBSection and save the important variables (object handle and struct pointer):

$aDIB = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
$hGDIObj = $aDIB[0]
$hPtr = $aDIB[4]

4) Activate

Select the object to use it:

_WinAPI_SelectObject($hCompDC, $hGDIObj)

5) Create a pixel-map

This is a dword-array of color values. Replace 160000 with width*height of your region:

$hPixelStruct = DllStructCreate("dword[160000]", $hPtr)

Capture window

Now we need to transfer the hidden window DeviceContext into our "virtual" context, but first the DC of the target (I'm using Paint as an example):

$hWnd = WinGetHandle("Paint")
$hWndDC = _WinAPI_GetDC($hWnd)

Let's transfer the DC into our DC, using PrintWindow:

Local $iX = 20 ; x coord of pixel in window DC (incl. title bar)
Local $iY = 20 ; y coord
DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "ptr", $hCompDC, "int", 0)

Reading single pixels

Since $hPixelStruct is a continuous stream of values, we have to do a little bit of math to point at the right pixel:

$iColor = MsgBox(0, "Color", '0x' & Hex(DllStructGetData($hPixelStruct, 1, $iY * 400 + $iX + 1), 6))

Cleaning up

Lastly, destroy the resources:

_WinAPI_ReleaseDC(0, $hCompDC)
_WinAPI_ReleaseDC($hWnd, $hWndDC)

Results

Works perfectly. Though this is only valid for hidden windows, NOT minimized, as minimized windows do not have any drawn context.

Script

Here's a Gist containing the script: minxomat/readcolor.au3

这篇关于来自背景/非活动/未聚焦窗口的 AutoIt PixelGetColor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆