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;
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.
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)
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)
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))
Lastly, destroy the resources:
_WinAPI_ReleaseDC(0, $hCompDC)
_WinAPI_ReleaseDC($hWnd, $hWndDC)
Works perfectly. Though this is only valid for hidden windows, NOT minimized, as minimized windows do not have any drawn context.
Here's a Gist containing the script: minxomat/readcolor.au3