tryhi 发表于 2010-6-27 16:53:12

这段代码运行后内存不断增加,直至发生错误退出

本帖最后由 tryhi 于 2010-7-23 21:37 编辑

#include <GDIPlus.au3>
;~ #include <screencapture.au3>
If Not(ProcessExists("calc.exe")) Then Run("calc.exe")
WinWait("计算器")
$hwnd=WinGetHandle("计算器")
While 1
ToolTip(_poscolorread($hWnd,221,97))
Sleep(100)
WEnd


Func _PosColorRead($hWnd,$PosX,$PosY)
      ;定义程序必须的变量
      Local $iColor,$PosArray,$X=$PosX,$Y=$PosY
      ;调用函数抓取窗体 从0,0到X,Y的 区域 返回的是一个数组. 多抓取的5个像素点是为了给图片做冗余,防止读不出该坐标的颜色.
      $PosArray=LToArray($hWnd,$X+5,$Y+5)
      ;从数组中读出要读取的坐标的颜色.
      $iColor = $PosArray[$PosX][$PosY]
      ;返回该颜色
      Return $iColor
EndFunc

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
      ;定义程序必须的变量
      Local $iH, $iW, $hDDC, $hCDC, $hBMP
      ;如果调用该函数时候没指定宽和高,则调用AIP获取窗口的宽和高作为抓图区域的宽和高
      If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
      If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)
      ;创建一个DC句柄
    $hDDC = _WinAPI_GetDC($hWnd)
      ;创建一个与DC句柄兼容的内存句柄
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
      ;从DC句柄创建一个宽高为调用值的位图句柄
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
      ;将位图句柄复制到内存区域中去
    _WinAPI_SelectObject($hCDC, $hBMP)
      ;用 printwindow 取得程序窗口
    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
      ;释放DC句柄
    _WinAPI_ReleaseDC($hWnd, $hDDC)
      ;释放内存句柄
    _WinAPI_DeleteDC($hCDC)
;~   _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP)
    ;返回创建好的位图句柄
    Return $hBMP
EndFunc

Func LToArray($hand,$iWidth=-1,$iHeight = -1);成功则返回数组.失败返回0.
      ;定义子程序必须的变量
    Local $hBitmap, $BitmapData, $i_width, $i_height, $Scan0, $pixelData, $s_BMPData, $i_Stride
      ;初始化GDI+库
      _GDIPlus_Startup()
      ;如果调用函数时候没有指定宽和高, 则调用API获取宽和高.
      If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hand)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hand)
      ;调用函数获取指定窗体的位图句柄.
      $hBMP = _WinCapture($hand, $iWidth, $iHeight)
      ;从位图句柄创建Bitmap对象
      $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
      ;如果未创建成功,则直接退出.未创建成功可能是因为无效的图形句柄
      If @error Then
                _GDIPlus_ShutDown ()
                Return 0
      EndIf      
      ;获取位图句柄的宽和高.
      $i_width = _GDIPlus_ImageGetWidth($hBitmap)
      $i_height = _GDIPlus_ImageGetHeight($hBitmap)      
      ;锁定位图句柄中用于输入输出的部分. 将位图句柄中的数据格式格式化成24位的RGB格式.
    $BitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $i_width, $i_height, $GDIP_ILMREAD, $GDIP_PXF24RGB)
      ;以下几句可能是BMP的数据格式, 我不懂. 这是大牛阿福给的
    $i_Stride = DllStructGetData($BitmapData, "Stride")
    $Scan0 = DllStructGetData($BitmapData, "Scan0")
    $pixelData = DllStructCreate("ubyte lData[" & (Abs($i_Stride) * $i_height) & "]", $Scan0)
    $s_BMPData = DllStructGetData($pixelData, "lData")
    $s_BMPData = StringTrimLeft($s_BMPData,2)
      ;解锁BMP位图数据区块.
    _GDIPlus_BitmapUnlockBits($hBitmap, $BitmapData)
      ;销毁位图句柄
    _GDIPlus_ImageDispose($hBitmap)
      ;删除位图对象.
      _WinAPI_DeleteObject ($hBitmap)
      ;关闭GDI库
      _GDIPlus_Shutdown()
      ;定义变量.
      Local $a_return[$i_width][$i_height], $x=$i_width-5, $y=$i_height-5, $s
      ;从位图数据中取出指定的那行.
      $s=StringMid($s_BMPData, $y*($i_Stride*2)+1, $i_width*6)
      ;从该行中读出指定的那个坐标.
      $a_return[$x][$y]= StringMid($s,$x*6+1 ,6)
      ;BGR转RGB.
      $a_return[$x][$y]= "0x"&StringRight($a_return[$x][$y],2)&StringMid($a_return[$x][$y],2,2)&StringLeft($a_return[$x][$y],2)
      Return $a_return
EndFunc 本文出自lanfengc 的绝对可用的后台取色

我的机器上测试大约只能循环400次,每一次增加一点内存,到最后出现错误

xunzhang22 发表于 2010-6-27 16:53:13

#include <GDIPlus.au3>
;~ #include <screencapture.au3>
If Not(ProcessExists("calc.exe")) Then Run("calc.exe")
WinWait("计算器")
$hwnd=WinGetHandle("计算器")
While 1
ToolTip(_poscolorread($hWnd,221,97))
Sleep(100)
WEnd


Func _PosColorRead($hWnd,$PosX,$PosY)
      ;定义程序必须的变量
      Local $iColor,$PosArray,$X=$PosX,$Y=$PosY
      ;调用函数抓取窗体 从0,0到X,Y的 区域 返回的是一个数组. 多抓取的5个像素点是为了给图片做冗余,防止读不出该坐标的颜色.
      $PosArray=LToArray($hWnd,$X+5,$Y+5)
      ;从数组中读出要读取的坐标的颜色.
      $iColor = $PosArray[$PosX][$PosY]
      ;返回该颜色
      Return $iColor
EndFunc

Func _WinCapture($hWnd, $iWidth = -1, $iHeight = -1)
      ;定义程序必须的变量
      Local $iH, $iW, $hDDC, $hCDC, $hBMP
      ;如果调用该函数时候没指定宽和高,则调用AIP获取窗口的宽和高作为抓图区域的宽和高
      If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hWnd)
      If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hWnd)
      ;创建一个DC句柄
    $hDDC = _WinAPI_GetDC($hWnd)
      ;创建一个与DC句柄兼容的内存句柄
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
      ;从DC句柄创建一个宽高为调用值的位图句柄
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
      ;将位图句柄复制到内存区域中去
    _WinAPI_SelectObject($hCDC, $hBMP)
      ;用 printwindow 取得程序窗口
    DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
      ;释放DC句柄
    _WinAPI_ReleaseDC($hWnd, $hDDC)
      ;释放内存句柄
    _WinAPI_DeleteDC($hCDC)
;~   _ScreenCapture_SaveImage(@DesktopDir&"\window.jpg", $hBMP)
    ;返回创建好的位图句柄
    Return $hBMP
EndFunc

Func LToArray($hand,$iWidth=-1,$iHeight = -1);成功则返回数组.失败返回0.
      ;定义子程序必须的变量
    Local $hBitmap, $BitmapData, $i_width, $i_height, $Scan0, $pixelData, $s_BMPData, $i_Stride
      ;初始化GDI+库
      _GDIPlus_Startup()
      ;如果调用函数时候没有指定宽和高, 则调用API获取宽和高.
      If $iWidth = -1 Then $iWidth = _WinAPI_GetWindowWidth($hand)
    If $iHeight = -1 Then $iHeight = _WinAPI_GetWindowHeight($hand)
      ;调用函数获取指定窗体的位图句柄.
      $hBMP = _WinCapture($hand, $iWidth, $iHeight)
      ;从位图句柄创建Bitmap对象
      $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
      ;如果未创建成功,则直接退出.未创建成功可能是因为无效的图形句柄
      If @error Then
                _GDIPlus_ShutDown ()
                Return 0
      EndIf      
      ;获取位图句柄的宽和高.
      $i_width = _GDIPlus_ImageGetWidth($hBitmap)
      $i_height = _GDIPlus_ImageGetHeight($hBitmap)      
      ;锁定位图句柄中用于输入输出的部分. 将位图句柄中的数据格式格式化成24位的RGB格式.
    $BitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $i_width, $i_height, $GDIP_ILMREAD, $GDIP_PXF24RGB)
      ;以下几句可能是BMP的数据格式, 我不懂. 这是大牛阿福给的
    $i_Stride = DllStructGetData($BitmapData, "Stride")
    $Scan0 = DllStructGetData($BitmapData, "Scan0")
    $pixelData = DllStructCreate("ubyte lData[" & (Abs($i_Stride) * $i_height) & "]", $Scan0)
    $s_BMPData = DllStructGetData($pixelData, "lData")
    $s_BMPData = StringTrimLeft($s_BMPData,2)
      ;解锁BMP位图数据区块.
    _GDIPlus_BitmapUnlockBits($hBitmap, $BitmapData)
      ;销毁位图句柄
    _GDIPlus_ImageDispose($hBitmap)
      ;删除位图对象.
      _WinAPI_DeleteObject ($hBitmap)
      _WinAPI_DeleteObject ($hBMP);这里没有删除位图,说明是一下,楼主提问题的时候一直在循环测试什么东西没有销毁,找了很多,测试了 几百次,终于找到了问题的根源。我和楼主一起研究几天,这个50金我拿了,感谢楼主!
      ;关闭GDI库
      _GDIPlus_Shutdown()
      ;定义变量.
      Local $a_return[$i_width][$i_height], $x=$i_width-5, $y=$i_height-5, $s
      ;从位图数据中取出指定的那行.
      $s=StringMid($s_BMPData, $y*($i_Stride*2)+1, $i_width*6)
      ;从该行中读出指定的那个坐标.
      $a_return[$x][$y]= StringMid($s,$x*6+1 ,6)
      ;BGR转RGB.
      $a_return[$x][$y]= "0x"&StringRight($a_return[$x][$y],2)&StringMid($a_return[$x][$y],2,2)&StringLeft($a_return[$x][$y],2)
      Return $a_return
EndFunc

tryhi 发表于 2010-6-27 17:13:39

50块金钱没人要啊

xunzhang22 发表于 2010-6-27 18:48:41

期待高手的回答!!!!!!!!!

xunzhang22 发表于 2010-6-27 19:04:50

涉及到内存问题,不是一般的那解决!!!!!!!!!!!!!希望写本程序的高手来关注一下!!!

tryhi 发表于 2010-6-27 19:13:45

我终于解决了,花了整整一天时间
页: [1]
查看完整版本: 这段代码运行后内存不断增加,直至发生错误退出