Sign in to follow this  
Followers 0
403forbidden

Screenshot Over TCP?

21 posts in this topic

Anyone know why transferring pictures captured using the "_ScreenCapture_Capture" function over TCP screws up the picture? I have made a TCP server-client setup, and I know it works. I take a screen-shot using a separate script, and transfer the file to the client from the server, saving it with the "FileWrite" function, opening it with flag 18, but it comes up as either invalid image in Picasa, or only the first 1/30th or so of the picture comes up at the top.

Any ideas?

403foridden

Share this post


Link to post
Share on other sites



You should probably look at saving it with _GDIPlus_* functions. _GDIPlus_ImageSaveToFile should do it :D

Share this post


Link to post
Share on other sites

Do you mean before I send it to the client? If not, then how do I get the image in an object on the client after it is sent over the network?

Share this post


Link to post
Share on other sites

Save it to a file as the client and then use something like this to send the file would be my guess. Not that I'm a particular expert on networking.

Share this post


Link to post
Share on other sites

When you take a screenshot, it saves it using the GDIPlus_ImageSaveToFile function...so saving it explicitly using that function would make no difference. Any other ideas?

Share this post


Link to post
Share on other sites

Client, sending the picture

#include <ScreenCapture.au3>
#include <File.au3>

TCPStartup()

Global $TCPConnect = TCPConnect(@IPAddress1, 3825)

$ScreenshotName = _TempFile(@ScriptDir, "~", ".jpg")
_ScreenCapture_SetJPGQuality(90)
_ScreenCapture_Capture($ScreenshotName)
$ScreenshotHandle = FileOpen($ScreenshotName, 16)
TCPSend($TCPConnect, FileRead($ScreenshotHandle))
FileClose($ScreenshotHandle)
FileDelete($ScreenshotName)

Server, receiving the picture.

#include <File.au3>

TCPStartup()

Global $TCPListen = TCPListen(@IPAddress1, 3825)

Do
    $TCPAccept = TCPAccept($TCPListen)
Until $TCPAccept <> -1

Do
    $TCPRecv = TCPRecv($TCPAccept, 134217728)
Until $TCPRecv <> ""

$ScreenshotName = _TempFile(@ScriptDir, "~", ".jpg")
$ScreenshotHandle = FileOpen($ScreenshotName, 18)
FileWrite($ScreenshotHandle, $TCPRecv)
FileClose($ScreenshotHandle)

Share this post


Link to post
Share on other sites

is there any way of doing this without writing the output to a file?


Only two things are infinite, the universe and human stupidity, and i'm not sure about the former -Alber EinsteinPractice makes perfect! but nobody's perfect so why practice at all?http://forum.ambrozie.ro

Share this post


Link to post
Share on other sites

I'm currently working on this as a feature for my script. The problem is that you are trying to send too much data at once. This isn't autoit's problem, it's your network adapter. I'm going to try taking multiple screenshots and combing them, but I doubt that will work.


There are 10 types of people in this world. Those that understand binary, and those that do not

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Here an example how to send an image without saving it to disk first!

It will take a screenshot, convert it to a jpg image and send to the server everything done in the memory!

Client Send - Receive Picture.au3

#include <memory.au3>
#include <screencapture.au3>

_GDIPlus_Startup()

TCPStartup()

Local $ConnectedSocket, $szData
Local $szIPADDRESS = @IPAddress1
Local $nPORT = 33891

$ConnectedSocket = -1

$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)

If @error Then Exit MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)

$iMsgBox = MsgBox(4, "Send image", "Send image to server?")
If $iMsgBox = 6 Then
    $hHBITMAP = _ScreenCapture_Capture("", 0, 0, 100, 100)
    $bImage = HBITMAP2BinaryString($hHBITMAP)
    ConsoleWrite(TCPSend($ConnectedSocket, Binary($bImage)) & @LF)
    _WinAPI_DeleteObject($hHBITMAP)
EndIf

_GDIPlus_Shutdown()

Exit

Func HBITMAP2BinaryString($HBITMAP) ;function by Andreik
    Local $BITMAP = _GDIPlus_BitmapCreateFromHBITMAP($HBITMAP)
    Local $JPG_ENCODER = _GDIPlus_EncodersGetCLSID("jpg")
    Local $TAG_ENCODER = _WinAPI_GUIDFromString($JPG_ENCODER)
    Local $PTR_ENCODER = DllStructGetPtr($TAG_ENCODER)
    Local $STREAM = DllCall("ole32.dll", "uint", "CreateStreamOnHGlobal", "ptr", 0, "bool", 1, "ptr*", 0)
    DllCall($ghGDIPDll, "uint", "GdipSaveImageToStream", "ptr", $BITMAP, "ptr", $STREAM[3], "ptr", $PTR_ENCODER, "ptr", 0)
    _GDIPlus_BitmapDispose($BITMAP)
    Local $MEMORY = DllCall("ole32.dll", "uint", "GetHGlobalFromStream", "ptr", $STREAM[3], "ptr*", 0)
    Local $MEM_SIZE = _MemGlobalSize($MEMORY[2])
    Local $MEM_PTR = _MemGlobalLock($MEMORY[2])
    Local $DATA_STRUCT = DllStructCreate("byte[" & $MEM_SIZE & "]", $MEM_PTR)
    Local $DATA = DllStructGetData($DATA_STRUCT, 1)
    Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data;ptr")
    Local $aCall = DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $STREAM[3], "dword", 8 + 8 * @AutoItX64, "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT))
    _MemGlobalFree($MEMORY[2])
    Return $DATA
EndFunc   ;==>HBITMAP2BinaryString

Server Send - Receive Picture.au3

#include <guiconstantsex.au3>
#include <gdiplus.au3>
#include <memory.au3>
#include <staticconstants.au3>

Local $szIPADDRESS = @IPAddress1
Local $nPORT = 33891
Local $MainSocket, $edit, $ConnectedSocket, $szIP_Accepted
Local $msg, $recv

TCPStartup()

$MainSocket = TCPListen($szIPADDRESS, $nPORT)

If $MainSocket = -1 Then Exit

GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200, 100, 100, Default, 0x00000008)
$edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
GUISetState()

$ConnectedSocket = -1

Do
    $ConnectedSocket = TCPAccept($MainSocket)
Until $ConnectedSocket <> -1

$szIP_Accepted = SocketToIP($ConnectedSocket)

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    $recv = TCPRecv($ConnectedSocket, 8192, 1)
    If @error Then ExitLoop
    If $recv <> "" Then GUICtrlSetData($edit, $recv)
WEnd

If $ConnectedSocket <> -1 Then TCPCloseSocket($ConnectedSocket)
TCPShutdown()

Global Const $IMAGE_BITMAP = 0
Global Const $STM_SETIMAGE = 0x0172

_GDIPlus_Startup()
$hBitmap = Load_BMP_From_Mem(Binary(GUICtrlRead($edit)), True)

$hGUI = GUICreate("Test", 320, 200)
$idPic = GUICtrlCreatePic("", 0, 0, 320, 200, $SS_CENTERIMAGE)
GUISetState()

_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap))

Do
Until GUIGetMsg() = -3

_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()
Exit

Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet
    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")
    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf
    $sockaddr = 0
    Return $aRet
EndFunc   ;==>SocketToIP

;======================================================================================
; Function Name:    Load_BMP_From_Mem
; Description:          Loads an image which is saved as a binary string and converts it to a bitmap or hbitmap
;
; Parameters:           $bImage:    the binary string which contains any valid image which is supported by GDI+
; Optional:                 $hHBITMAP:  if false a bitmap will be created, if true a hbitmap will be created
;
; Remark:                   hbitmap format is used generally for GUI internal images, $bitmap is more a GDI+ image format
;                               Don't forget _GDIPlus_Startup() and _GDIPlus_Shutdown()
;
; Requirement(s):       GDIPlus.au3, Memory.au3 and _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3
; Return Value(s):  Success: handle to bitmap (GDI+ bitmap format) or hbitmap (WinAPI bitmap format),
;                               Error: 0
; Error codes:              1: $bImage is not a binary string
;                               2: unable to create stream on HGlobal
;                               3: unable to create bitmap from stream
;
; Author(s):                UEZ
; Additional Code:    thanks to progandy for the MemGlobalAlloc and tVARIANT lines and
;                               Yashied for _GDIPlus_BitmapCreateDIBFromBitmap() from WinAPIEx.au3
; Version:                  v0.97 Build 2012-04-10 Beta
;=======================================================================================
Func Load_BMP_From_Mem($bImage, $hHBITMAP = False)
    If Not IsBinary($bImage) Then Return SetError(1, 0, 0)
    Local $aResult
    Local Const $memBitmap = Binary($bImage) ;load image  saved in variable (memory) and convert it to binary
    Local Const $len = BinaryLen($memBitmap) ;get length of image
    Local Const $hData = _MemGlobalAlloc($len, $GMEM_MOVEABLE) ;allocates movable memory  ($GMEM_MOVEABLE = 0x0002)
    Local Const $pData = _MemGlobalLock($hData) ;translate the handle into a pointer
    Local $tMem = DllStructCreate("byte[" & $len & "]", $pData) ;create struct
    DllStructSetData($tMem, 1, $memBitmap) ;fill struct with image data
    _MemGlobalUnlock($hData) ;decrements the lock count  associated with a memory object that was allocated with GMEM_MOVEABLE
    $aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "handle", $pData, "int", True, "ptr*", 0) ;Creates a stream object that uses an HGLOBAL memory handle to store the stream contents
    If @error Then Return SetError(2, 0, 0)
    Local Const $hStream = $aResult[3]
    $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "int*", 0) ;Creates a Bitmap object based on an IStream COM interface
    If @error Then Return SetError(3, 0, 0)
    Local Const $hBitmap = $aResult[2]
    Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data; ptr")
    DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, _
                                           "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;release memory from $hStream to avoid memory leak
    $tMem = 0
    $tVARIANT = 0
    If $hHBITMAP Then
        Local Const $hHBmp = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
        _GDIPlus_BitmapDispose($hBitmap)
        Return $hHBmp
    EndIf
    Return $hBitmap
EndFunc   ;==>Load_BMP_From_Mem

Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
    Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0
    $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
    If (@error) Or ($Ret[0]) Then Return 0
    $tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    $pBits = DllStructGetData($tData, 'Scan0')
    If Not $pBits Then Return 0
    $tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')
    DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))
    DllStructSetData($tBIHDR, 2, $Ret[2])
    DllStructSetData($tBIHDR, 3, $Ret[3])
    DllStructSetData($tBIHDR, 4, 1)
    DllStructSetData($tBIHDR, 5, 32)
    DllStructSetData($tBIHDR, 6, 0)
    $hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)
    If (Not @error) And ($hResult[0]) Then
        DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))
        $hResult = $hResult[0]
    Else
        $hResult = 0
    EndIf
    _GDIPlus_BitmapUnlockBits($hBitmap, $tData)
    Return $hResult
EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap

Start first Server Send - Receive Picture.au3 and then Client Send - Receive Picture.au3.

Because I'm not familiar with the tcp/ip stuff I took the tcp/ip stuff from the help file!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I'm currently working on this as a feature for my script. The problem is that you are trying to send too much data at once. This isn't autoit's problem, it's your network adapter. I'm going to try taking multiple screenshots and combing them, but I doubt that will work.

Did you know you're replying to a conversation that ended over two years ago?


Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Share this post


Link to post
Share on other sites

Server (run first)

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

Global Const $STM_SETIMAGE = 0x0172
Global Const $STM_GETIMAGE = 0x0173

TCPStartup()
$Main = TCPListen(@IPAddress1, 33891)
If @error Then
    Exit
EndIf

GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
GUISetState()

Do
    $Socket = TCPAccept($Main)
Until $Socket <> -1

Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0

_GDIPlus_Startup()

Do
    If Not IsBinary($bData) Then
        $bData = TCPRecv($Socket, 16384, 1)
        If @error Then
            ExitLoop
        EndIf
    EndIf
    If IsBinary($bData) Then
        If Not $Count Then
            DllStructSetData($tHeader, 1, $bData)
            $tData = DllStructCreate('dword', $pHeader)
            $Size = DllStructGetData($tData, 1)
            $tData = DllStructCreate('byte[' & $Size & ']')
            $pData = DllStructGetPtr($tData)
        EndIf
        $Lenght = BinaryLen($bData)
        $Sum = $Count + $Lenght
        If $Sum > $Size Then
            $dL = $Size - $Count
            $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $tByte = DllStructCreate('byte[' & $Lenght & ']')
            $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
            DllStructSetData($tByte, 1, $bData)
            $bData = DllStructGetData($tRecv, 1)
            $Sum = $Size
        Else
            $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $Count = $Sum
            $bData = 0
        EndIf
        If $Sum = $Size Then
            _SetScreenshot($Pic, $tData)
            $Count = 0
        EndIf
    EndIf
Until GUIGetMsg() = -3

_GDIPlus_Shutdown()

TCPCloseSocket($Socket)
TCPShutdown()

Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0)

    Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

    $hWnd = GUICtrlGetHandle($CtrlID)
    If Not $hWnd Then
        Return 0
    EndIf

    $pData = DllStructGetPtr($tData)
    $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
    $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
    $pMemory = _MemGlobalLock($hMemory)
    _MemMoveMemory($pData + 8, $pMemory, $iSize)
    _MemGlobalUnlock($hMemory)
    $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
    $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream)
    $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_ReleaseStream($pStream)
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen))
    $hPrev = _SendMessage($hWnd, $STM_GETIMAGE)
    If $hPrev <> $hScreen Then
        _WinAPI_DeleteObject($hScreen)
    EndIf
    If $fUpdate Then
        _WinAPI_UpdateWindow($hWnd)
    EndIf
    Return 1
EndFunc   ;==>_SetScreenshot

Func _GDIPlus_CreateBitmapFromStream($pStream)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $Ret[2]
EndFunc   ;==>_GDIPlus_CreateBitmapFromStream

Client

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

TCPStartup()
$Socket = TCPConnect(@IPAddress1, 33891)
If @error Then
    Exit
EndIf

_GDIPlus_Startup()

Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png'))
Global $pEncoder = DllStructGetPtr($tEncoder)

While 1
    TCPSend($Socket, _GetScreenshot(0, 0, 800, 600))
    If @error Then
        ExitLoop
    EndIf
    Sleep(1000)
WEnd

_GDIPlus_Shutdown()

TCPShutdown()

Func _GetScreenshot($iX = 0, $iY = 0, $iWidth = -1, $iHeight = -1)

    Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize

    If $iWidth = -1 Then
        $iWidth = @DesktopWidth
    EndIf
    If $iHeight = -1 Then
        $iHeight = @DesktopHeight
    EndIf
    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
    _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
    _WinAPI_DeleteObject($hScreen)
    $pStream = _WinAPI_CreateStreamOnHGlobal(0)
    _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder)
    _GDIPlus_BitmapDispose($hBitmap)
    $hMemory = _WinAPI_GetHGlobalFromStream($pStream)
    $pMemory = _MemGlobalLock($hMemory)
    $iSize = _MemGlobalSize($hMemory)
    $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']')
    $pOut = DllStructGetPtr($tOut)
    DllStructSetData($tOut, 1, DllStructGetSize($tOut))
    DllStructSetData($tOut, 2, $iSize)
    _MemMoveMemory($pMemory, $pOut + 8, $iSize)
    _WinAPI_ReleaseStream($pStream)
    Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1)
EndFunc   ;==>_GetScreenshot

Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams = 0)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return 1
EndFunc   ;==>_GDIPlus_SaveImageToStream

Share this post


Link to post
Share on other sites

Where can I download the "APIConstants.au3" and "WinAPIEx.au3"?

Share this post


Link to post
Share on other sites

szalaisanyi86,

Welcome to the AutoIt forum. :oops:

You can find them here. :bye:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Sorry and Thanks! :oops:

Share this post


Link to post
Share on other sites

@Yashied

(I know this is an old post but still interesting for me.....)

I tryed your client/server scripts and are working well on the same computer,

when i run the client, i get screenshots from the client script to server script;

but I get only a black screen if server and client are 2 separate computers....

of course i set the ip address of the server at the following line of code in the client script:

$Socket = TCPConnect("10.0.0.222", 33891) ; the ip of the server

why only a black screen in response?

any suggestion is welcome

thanks

Pincopanco


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

.... I found the problem myself,

If the client is started on the remote computer with psexec (like I do) is necessary to use the "-i" parameter in psexec otherwise a black screen is returned by the client.

with the following command for example I receive only a black screen:

psexec remotepc -u domainusername -p password -c client.exe

while withe with this command (added -i) I receive a regular screenshot of the client:

psexec remotepc -u domainusername -p password -i -c client.exe

bye


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Server (run first)

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

Global Const $STM_SETIMAGE = 0x0172
Global Const $STM_GETIMAGE = 0x0173

TCPStartup()
$Main = TCPListen(@IPAddress1, 33891)
If @error Then
    Exit
EndIf

GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
GUISetState()

Do
    $Socket = TCPAccept($Main)
Until $Socket <> -1

Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0

_GDIPlus_Startup()

Do
    If Not IsBinary($bData) Then
        $bData = TCPRecv($Socket, 16384, 1)
        If @error Then
            ExitLoop
        EndIf
    EndIf
    If IsBinary($bData) Then
        If Not $Count Then
            DllStructSetData($tHeader, 1, $bData)
            $tData = DllStructCreate('dword', $pHeader)
            $Size = DllStructGetData($tData, 1)
            $tData = DllStructCreate('byte[' & $Size & ']')
            $pData = DllStructGetPtr($tData)
        EndIf
        $Lenght = BinaryLen($bData)
        $Sum = $Count + $Lenght
        If $Sum > $Size Then
            $dL = $Size - $Count
            $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $tByte = DllStructCreate('byte[' & $Lenght & ']')
            $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
            DllStructSetData($tByte, 1, $bData)
            $bData = DllStructGetData($tRecv, 1)
            $Sum = $Size
        Else
            $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $Count = $Sum
            $bData = 0
        EndIf
        If $Sum = $Size Then
            _SetScreenshot($Pic, $tData)
            $Count = 0
        EndIf
    EndIf
Until GUIGetMsg() = -3

_GDIPlus_Shutdown()

TCPCloseSocket($Socket)
TCPShutdown()

Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0)

    Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

    $hWnd = GUICtrlGetHandle($CtrlID)
    If Not $hWnd Then
        Return 0
    EndIf

    $pData = DllStructGetPtr($tData)
    $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
    $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
    $pMemory = _MemGlobalLock($hMemory)
    _MemMoveMemory($pData + 8, $pMemory, $iSize)
    _MemGlobalUnlock($hMemory)
    $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
    $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream)
    $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_ReleaseStream($pStream)
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen))
    $hPrev = _SendMessage($hWnd, $STM_GETIMAGE)
    If $hPrev <> $hScreen Then
        _WinAPI_DeleteObject($hScreen)
    EndIf
    If $fUpdate Then
        _WinAPI_UpdateWindow($hWnd)
    EndIf
    Return 1
EndFunc   ;==>_SetScreenshot

Func _GDIPlus_CreateBitmapFromStream($pStream)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $Ret[2]
EndFunc   ;==>_GDIPlus_CreateBitmapFromStream

Client

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

TCPStartup()
$Socket = TCPConnect(@IPAddress1, 33891)
If @error Then
    Exit
EndIf

_GDIPlus_Startup()

Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png'))
Global $pEncoder = DllStructGetPtr($tEncoder)

While 1
    TCPSend($Socket, _GetScreenshot(0, 0, 800, 600))
    If @error Then
        ExitLoop
    EndIf
    Sleep(1000)
WEnd

_GDIPlus_Shutdown()

TCPShutdown()

Func _GetScreenshot($iX = 0, $iY = 0, $iWidth = -1, $iHeight = -1)

    Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize

    If $iWidth = -1 Then
        $iWidth = @DesktopWidth
    EndIf
    If $iHeight = -1 Then
        $iHeight = @DesktopHeight
    EndIf
    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
    _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
    _WinAPI_DeleteObject($hScreen)
    $pStream = _WinAPI_CreateStreamOnHGlobal(0)
    _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder)
    _GDIPlus_BitmapDispose($hBitmap)
    $hMemory = _WinAPI_GetHGlobalFromStream($pStream)
    $pMemory = _MemGlobalLock($hMemory)
    $iSize = _MemGlobalSize($hMemory)
    $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']')
    $pOut = DllStructGetPtr($tOut)
    DllStructSetData($tOut, 1, DllStructGetSize($tOut))
    DllStructSetData($tOut, 2, $iSize)
    _MemMoveMemory($pMemory, $pOut + 8, $iSize)
    _WinAPI_ReleaseStream($pStream)
    Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1)
EndFunc   ;==>_GetScreenshot

Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams = 0)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return 1
EndFunc   ;==>_GDIPlus_SaveImageToStream

 

Hello all,

I'm aware, that this is a very old thread. Still the mentioned method is the best, I've found so far, to stream a remote screen.

Now I have two questions about this, and hopefully somebody can help:

1. Is it possible, to decrease the picture resolution? This should have two advantages:

- You can see the entire remote screen, even if the remote computer uses a higher resolution.

- It should load quicker, as a smaller amount of data is being transfered.

2. Is it possible to use this method to stream the webcam picture instead of the screen picture?

I tried but failed on both so far.

Thanks a lot!

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Regarding

1.

Check out _GDIPlus_ImageScale() and _GDIPlus_ImageResize() but have in mind that resizing costs time which can decrease the FPS.

2.

I don't have a web cam but it should be possible, too.

 

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Regarding

1.

Check out _GDIPlus_ImageScale() and _GDIPlus_ImageResize() but have in mind that resizing costs time which can decrease the FPS.

2.

I don't have a web cam but it should be possible, too.

 

Br,

UEZ

Thank you! Will try.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0