AutoIt PixelGetColor来自后台/非活动/非聚焦窗口

时间:2015-03-01 20:44:45

标签: background autoit

PixelGetColor有一个可选参数 hwnd (从中读取像素的窗口句柄)。因此,我认为可以从未聚焦的窗口读取(即未最小化,但在另一个窗口后面);但我无法让它像那样工作。

  • 我的假设错了吗?如果没有,这将如何做?如果是的话;

    • 为什么是hwnd参数?
    • 还有另一种涉及像素识别的方法吗?

1 个答案:

答案 0 :(得分:1)

摘要

您想要创建一个简单的空位图,并将隐藏窗口的DeviceContext内容传输到其中。然后你可以在任何位置读取任何值。

创建空位图

<强>含

我们需要包含WinAPI定义和常量。

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

就是这样。

初始结构

现在我们必须从$tagBITMAPINFO模板创建一个新的DLL结构。我们需要用bitmaps参数填充结构。为了确保所有AutoIt版本的兼容性,我将通过索引访问结构项。

1)创建兼容的设备上下文:

Local $hCompDC = _WinAPI_CreateCompatibleDC(0)

2)从模板创建结构,填充数据:

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

您需要调整宽度和高度参数以匹配您要传输的区域。在你的情况下,我猜窗口的大小将是一个不错的选择,虽然区域越小越快。

3)创建GDI对象

创建CreateDIBSection并保存重要变量(对象句柄和结构指针):

$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)激活

选择要使用它的对象:

_WinAPI_SelectObject($hCompDC, $hGDIObj)

5)创建像素图

这是一个颜色值的dword数组。将160000替换为您所在地区的width*height

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

捕获窗口

现在我们需要将隐藏窗口DeviceContext转移到我们的“虚拟”上下文中,但首先是目标的DC(我使用Paint作为示例):

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

让我们使用PrintWindow将DC转移到我们的DC:

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)

读取单个像素

由于$hPixelStruct是一个连续的值流,我们必须做一些数学运算才能指向正确的像素:

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

清理

最后,破坏资源:

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

结果

完美无缺。虽然这仅适用于隐藏窗口,但未最小化,因为最小化窗口没有任何绘制的上下文。

screenshot

脚本

这是一个包含脚本的要点:minxomat/readcolor.au3