Приветствую, форумчане. Для повышения опыта (ну и ради забавы) решил написать аналог TeamViewer. Реализация следующая: скриншотятся активные окна, разбиваются на квадраты, далее квадраты проходят через фильтр GrayScale (серый градиент), затем сохраняются в png файлы; при этом ведется подсчет контрольной суммы пикселей для выявления обновлений в регионах активного окна. То есть новые скриншоты (в виде квадратиков) будут появляться только тогда, когда канвас содержит новую информацию. Таким образом, я добился минимального трафика. При сохранении файлов также используются в их имени идентификационные данные, такие как хэндл окна, размер изображения, координаты (индекс) квадрата (X, Y). Идентификация нужна для декодирования (или обратной склейки картинок).
Единственное, что меня беспокоит - это повышение загрузки процессора.
В общем код ниже, буду рад вашим советам и предложения. Для удобства я сделал фильтр процессов, так проводник исключен от скриншотов.
Единственное, что меня беспокоит - это повышение загрузки процессора.
В общем код ниже, буду рад вашим советам и предложения. Для удобства я сделал фильтр процессов, так проводник исключен от скриншотов.
Код:
#include <ScreenCapture.au3>
dim $PixSumLast[1]
$SquareSize = 200
$LastXSquare = 0
$LastYSquare = 0
While 1
MakeScreenShot()
Sleep(1000)
; Exit
WEnd
Func MakeScreenShot()
$ActiveWindow = WinGetHandle("[active]")
if $ActiveWindow=="" Then Return 0
$Pos = WinGetClientSize("[active]")
if $Pos==0 Then Return 0
$proc = WinGetProcess("[active]")
$ProcessName = ProcessGetName($proc)
If $ProcessName=="explorer.exe" then Return 0
$XSquare = Floor($Pos[0] / $SquareSize)
$YSquare = Floor($Pos[1] / $SquareSize)
if ($XSquare <> $LastXSquare) OR ($YSquare <> $LastYSquare) then
ReDim $PixSumLast[$XSquare+1][$YSquare+1]
endif
For $x = 0 To $XSquare
For $y = 0 To $YSquare
$PixSum = PixelChecksum($x*$SquareSize,$y*$SquareSize, ($x+1)*$SquareSize, ($y+1)*$SquareSize, 4, $ActiveWindow)
if $PixSumLast[$x][$y] == $PixSum then
ContinueLoop
EndIf
$PixSumLast[$x][$y] = $PixSum
_GDIPlus_Startup ()
$HBITMAP = _ScreenCapture_CaptureWnd ( "", $ActiveWindow, $x*$SquareSize, $y*$SquareSize, ($x+1)*$SquareSize, ($y+1)*$SquareSize, False)
$fFreeBmp = True
$hBmp = _GDIPlus_BitmapCreateFromHBITMAP($HBITMAP)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBmp)
_Greyscale($hBmp, $hContext)
_GDIPlus_ImageSaveToFile($hBmp, @ScriptDir & "\" & @YEAR & @MON & @MDAY & "-" & @HOUR & @MIN & @SEC & "-" & $ProcessName & "-" & $x & "-" & $y & "-" & $XSquare & "-" & $YSquare & "-" & $Pos[0] & "-" & $Pos[1] & "-" & $ActiveWindow & ".png")
_GDIPlus_GraphicsDispose($hContext)
_WinAPI_DeleteObject($HBITMAP)
_GDIPlus_BitmapDispose ($hBmp)
_GDIPlus_Shutdown()
Next
Next
EndFunc
Func ProcessGetName($PId)
If IsNumber($PId) = 0 Then
SetError(2)
ElseIf $PId > 9999 Then
SetError(1)
Else
Local $PList = ProcessList()
Local $i = 1
Local $ProcessName = ""
While $i <= $PList[0][0] And $ProcessName = ""
If $PList[$i][1] = $PId Then
$ProcessName = $PList[$i][0]
Else
$i = $i + 1
EndIf
WEnd
Return $ProcessName
EndIf
EndFunc ;==>ProcessGetName
Func _Greyscale($hImage, $hImageContext)
Local $tNegMatrix, $pNegMatrix, $hIA
$hIA = _GDIPlus_ImageAttributesCreate()
$aImageSize = _GDIPlus_ImageGetDimension($hImage)
If $hImage Then
$tNegMatrix = _GDIPlus_ColorMatrixCreateGrayScale()
$pNegMatrix = DllStructGetPtr($tNegMatrix)
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pNegMatrix)
_GDIPlus_GraphicsDrawImageRectRectIA($hImageContext, $hImage, 0, 0, $aImageSize[0], $aImageSize[1], 0, 0, $aImageSize[0], $aImageSize[1], $hIA)
_GDIPlus_ImageAttributesDispose($hIA)
EndIf
EndFunc
Func _GDIPlus_ImageGetDimension($hImage)
Local $aSize[2], $aResult
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "hwnd", $hImage, "float*", 0, "float*", 0)
If @error Then Return SetError(@error, @extended, -1)
$GDIP_STATUS = $aResult[0]
If $GDIP_STATUS Then Return -1
$aSize[0] = $aResult[2]
$aSize[1] = $aResult[3]
Return $aSize
EndFunc ;==>_GDIPlus_ImageGetDimension
Func _GDIPlus_ImageAttributesCreate()
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateImageAttributes", "int*", 0)
If @error Then Return SetError(@error, @extended, 0)
Return $aResult[1]
EndFunc ;==>_GDIPlus_ImageAttributesCreate
Func _GDIPlus_ColorMatrixCreateGrayScale()
Local Const $GDIP_RLUM = 0.3086
Local Const $GDIP_GLUM = 0.6094
Local Const $GDIP_BLUM = 0.0820
Local Const $tagGDIPCOLORMATRIX = "float m[25];"
Local $iI, $iJ, $tCM, $aLums[4] = [$GDIP_RLUM, $GDIP_GLUM, $GDIP_BLUM, 0]
$tCM = DllStructCreate($tagGDIPCOLORMATRIX)
For $iI = 0 To 3
For $iJ = 1 To 3
DllStructSetData($tCM, "m", $aLums[$iI], $iI * 5 + $iJ)
Next
Next
DllStructSetData($tCM, "m", 1, 19)
DllStructSetData($tCM, "m", 1, 25)
Return $tCM
EndFunc ;==>_GDIPlus_ColorMatrixCreateGrayScale
Func _GDIPlus_ImageAttributesSetColorMatrix($hImageAttributes, $iColorAdjustType = 0, $fEnable = False, $pClrMatrix = 0, $pGrayMatrix = 0, $iColorMatrixFlags = 0)
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetImageAttributesColorMatrix", "hwnd", $hImageAttributes, "int", $iColorAdjustType, "int", $fEnable, "ptr", $pClrMatrix, "ptr", $pGrayMatrix, "int", $iColorMatrixFlags)
If @error Then Return SetError(@error, @extended, False)
Return $aResult[0] = 0
EndFunc ;==>_GDIPlus_ImageAttributesSetColorMatrix
Func _GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hImage, $nSrcX, $nSrcY, $nSrcWidth, $nSrcHeight, $nDstX, $nDstY, $nDstWidth, $nDstHeight, $hImageAttributes = 0, $iUnit = 2)
Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRectRect", "hwnd", $hGraphics, "hwnd", $hImage, "float", $nDstX, "float", _
$nDstY, "float", $nDstWidth, "float", $nDstHeight, "float", $nSrcX, "float", $nSrcY, "float", $nSrcWidth, "float", _
$nSrcHeight, "int", $iUnit, "hwnd", $hImageAttributes, "int", 0, "int", 0)
If @error Then Return SetError(@error, @extended, False)
Return $aResult[0] = 0
EndFunc ;==>_GDIPlus_GraphicsDrawImageRectRectIA
Func _GDIPlus_ImageAttributesDispose($hImageAttributes)
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipDisposeImageAttributes", "hwnd", $hImageAttributes)
If @error Then Return SetError(@error, @extended, False)
Return $aResult[0] = 0
EndFunc ;==>_GDIPlus_ImageAttributesDispose