来自 background/inactive/unfocused window 的 AutoIt PixelGetColor
AutoIt PixelGetColor from background/inactive/unfocused window
PixelGetColor 有一个可选参数 hwnd(从中读取像素的 window 句柄)。因此,我认为可以从未聚焦的 windows 中读取(即未最小化,但在另一个 window 之后);但我无法让它像那样工作。
我的假设错了吗?如果没有,这将如何完成?如果是的话;
- 为什么是 hwnd 参数?
- 还有没有其他涉及像素识别的方法?
摘要
您想创建一个简单的空位图并将隐藏的 window 的 DeviceContext 内容传输到其中。然后你可以在任何位置读取任何值。
正在创建空位图
包括
我们需要包括 WinAPI 定义和常量。
#include <WinAPI.au3>
#include <WindowsConstants.au3>
仅此而已。
初始结构
现在我们必须从 $tagBITMAPINFO
模板创建一个新的 DLL 结构。我们需要用位图参数填充结构。为了确保所有 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
您需要调整宽度和高度参数以匹配您要传输的区域。在你的情况下,我想 window 的大小将是一个不错的选择,尽管区域越小,速度越快。
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) 激活
Select 使用对象:
_WinAPI_SelectObject($hCompDC, $hGDIObj)
5) 创建像素图
这是一个颜色值的双字数组。将 160000 替换为您所在地区的 width*height
:
$hPixelStruct = DllStructCreate("dword[160000]", $hPtr)
捕获window
现在我们需要将隐藏的 window DeviceContext 转移到我们的 "virtual" 上下文中,但首先是目标的 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)
结果
完美运行。虽然这仅对 hidden windows 有效,但未最小化,因为最小化 windows 没有任何绘制的上下文。
脚本
这是包含脚本的 Gist:minxomat/readcolor.au3
PixelGetColor 有一个可选参数 hwnd(从中读取像素的 window 句柄)。因此,我认为可以从未聚焦的 windows 中读取(即未最小化,但在另一个 window 之后);但我无法让它像那样工作。
我的假设错了吗?如果没有,这将如何完成?如果是的话;
- 为什么是 hwnd 参数?
- 还有没有其他涉及像素识别的方法?
摘要
您想创建一个简单的空位图并将隐藏的 window 的 DeviceContext 内容传输到其中。然后你可以在任何位置读取任何值。
正在创建空位图
包括
我们需要包括 WinAPI 定义和常量。
#include <WinAPI.au3>
#include <WindowsConstants.au3>
仅此而已。
初始结构
现在我们必须从 $tagBITMAPINFO
模板创建一个新的 DLL 结构。我们需要用位图参数填充结构。为了确保所有 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
您需要调整宽度和高度参数以匹配您要传输的区域。在你的情况下,我想 window 的大小将是一个不错的选择,尽管区域越小,速度越快。
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) 激活
Select 使用对象:
_WinAPI_SelectObject($hCompDC, $hGDIObj)
5) 创建像素图
这是一个颜色值的双字数组。将 160000 替换为您所在地区的 width*height
:
$hPixelStruct = DllStructCreate("dword[160000]", $hPtr)
捕获window
现在我们需要将隐藏的 window DeviceContext 转移到我们的 "virtual" 上下文中,但首先是目标的 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)
结果
完美运行。虽然这仅对 hidden windows 有效,但未最小化,因为最小化 windows 没有任何绘制的上下文。
脚本
这是包含脚本的 Gist:minxomat/readcolor.au3