Что нового

скриншот в бинарный код без промежуточного файла

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Версия Autoit:3.

Описание: Как снять скриншот экрана монитора и перевести его в бинарный код без создания промежуточного файла и также вывести в форму?
 

Arei

Скриптер
Сообщения
938
Репутация
115
интересный вопрос,присоединяюсь
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Sergey2210
Посмотрите в справке пример к функции _GDIPlus_BitmapCreateFromHBITMAP().
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Дело в том что мне нужно получить бынарный код скриншота без промежуточного файла и передать его по tcp , на счёт того как вывести в форму я уже нашёл способ
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Sergey2210 сказал(а):
Дело в том что мне нужно получить бынарный код скриншота без промежуточного файла и передать его по tcp , на счёт того как вывести в форму я уже нашёл способ

Тебе нужно данные файла .bmp или данные о цвете HBITMAP? Каким способом будут выводиться эти данные? Если копия файла, то вот:

Код:
#Include <WinAPIEx.au3>

Global Const $tagBITMAPFILEHEADER = 'ushort bfType;align 2;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits;'

Global $iBytes, $pBits

$W = @DesktopWidth
$H = @DesktopHeight

$tBD = DllStructCreate($tagBITMAPFILEHEADER & $tagBITMAPINFOHEADER & 'byte Bits[' & ($W * $H * 3) & ']')
$tBI = DllStructCreate($tagBITMAPINFOHEADER, DllStructGetPtr($tBD, 'biSize'))

DllStructSetData($tBD, 'bfType', 0x4D42)
DllStructSetData($tBD, 'bfSize', DllStructGetSize($tBD))
DllStructSetData($tBD, 'bfReserved1', 0)
DllStructSetData($tBD, 'bfReserved2', 0)
;~DllStructSetData($tBD, 'bfOffBits', Number(DllStructGetPtr($tBD, 'Bits') - DllStructGetPtr($tBD)))
DllStructSetData($tBD, 'bfOffBits', 14 + 40)

DllStructSetData($tBI, 'biSize', DllStructGetSize($tBI))
DllStructSetData($tBI, 'biWidth', $W)
DllStructSetData($tBI, 'biHeight', -$H)
DllStructSetData($tBI, 'biPlanes', 1)
DllStructSetData($tBI, 'biBitCount', 24)
DllStructSetData($tBI, 'biCompression', $BI_RGB)

$hBitmap = _WinAPI_CreateDIBSection(0, $tBI, $DIB_RGB_COLORS, $pBits)
$hDesktop = _WinAPI_GetDesktopWindow()
$hSrcDC = _WinAPI_GetDC($hDesktop)
$hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
$hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
_WinAPI_BitBlt($hDstDC, 0, 0, $W, $H, $hSrcDC, 0, 0, $SRCCOPY)
_WinAPI_SelectObject($hDstDC, $hDstSv)
_WinAPI_ReleaseDC($hDesktop, $hSrcDC)
_WinAPI_DeleteDC($hDstDC)
_WinAPI_GetBitmapBits($hBitmap, $W * $H * 3, DllStructGetPtr($tBD, 'Bits'))
_WinAPI_DeleteObject($hBitmap)

; Здесь структура $tBD содержит полностью данные файла .bmp

$hFile = _WinAPI_CreateFile(@ScriptDir & '\Desktop.bmp', 1, 4)
_WinAPI_WriteFile($hFile, DllStructGetPtr($tBD), DllStructGetSize($tBD), $iBytes)
_WinAPI_CloseHandle($hFile)


Если передавать только цвет, то еще проще.
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
мне нужен бинарный код скриншота,но чтоб никаких файлов не создавалось,как bin2img.au3 только наоборот,а за этот пример спасибо,он мне тоже пригодится...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Что значит бинарный код скриншота? Скриншот, это картинка, а кртинка может быть в разных форматах. Все зависит от способа ее вывода. А вообще, ты задаешь вопросы, мало понимая их смысл. Битмапы в API представлены их указателями (HBITMAP) и могут быть DIB или DDB. Для получения данных битмапа существует несколько функций, например _WinAPI_GetBitmapBits(). Изучай.

P.S

Мне вообще не очень нравится способ постановки твоих вопросов. Сначала речь идет о "получении бинарных данных скриншота", затем откуда не возьмись появляется передача по TCP. А дальше выяснится, что ты собираешься написать свой RDP? И в каждом конкретном случае, это будут совершенно разные способы получения и отображеия скриншота. Может лучше сразу писать что, зачем и для чего ты хочешь сделать?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Sergey2210 сказал(а):
мне нужен бинарный код скриншота,но чтоб никаких файлов не создавалось...

А что по твоему представляет переменная $tBD?

Sergey2210 сказал(а):
...как bin2img.au3 только наоборот...

Что такое bin2img.au3? По твоему я должен сам искать его в сети?
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Блин,пример,делаю скриншот,потом через FileOpen('',16) открываю файл скриншота,далее считываю в FileRead('',1024) и передаю уже бинарный код изображения,чтоб там где приняли,обратно преобразовали в файл скрина,только всё это нужно сделать чтоб скриншот не создавался в файл,а сразу взять его бинар и передать. Я не знаю что представляет переменная $tBD и что такое RDP...

А вот что такое bin2img.au3 (в прикреплённом файле)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
$tBD и есть "бинарный код скриншота". Можно по другому.

Код:
Func _ScreenToBinary()

	Local $tBD, $tBI, $W, $H, $hBitmap, $hDesktop, $hSrcDC, $hDstDC, $hDstSv, $pBits, $Bytes

	$W = @DesktopWidth
	$H = @DesktopHeight
	$tBD = DllStructCreate('ushort bfType;align 2;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits;' & $tagBITMAPINFOHEADER & 'byte Bits[' & ($W * $H * 3) & ']')
	$tBI = DllStructCreate($tagBITMAPINFOHEADER, DllStructGetPtr($tBD, 'biSize'))
	DllStructSetData($tBD, 'bfType', 0x4D42)
	DllStructSetData($tBD, 'bfSize', DllStructGetSize($tBD))
	DllStructSetData($tBD, 'bfReserved1', 0)
	DllStructSetData($tBD, 'bfReserved2', 0)
	DllStructSetData($tBD, 'bfOffBits', 14 + 40)
	DllStructSetData($tBI, 'biSize', DllStructGetSize($tBI))
	DllStructSetData($tBI, 'biWidth', $W)
	DllStructSetData($tBI, 'biHeight', -$H)
	DllStructSetData($tBI, 'biPlanes', 1)
	DllStructSetData($tBI, 'biBitCount', 24)
	DllStructSetData($tBI, 'biCompression', $BI_RGB)
	$hBitmap = _WinAPI_CreateDIBSection(0, $tBI, $DIB_RGB_COLORS, $pBits)
	$hDesktop = _WinAPI_GetDesktopWindow()
	$hSrcDC = _WinAPI_GetDC($hDesktop)
	$hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
	$hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
	_WinAPI_BitBlt($hDstDC, 0, 0, $W, $H, $hSrcDC, 0, 0, $SRCCOPY)
	_WinAPI_SelectObject($hDstDC, $hDstSv)
	_WinAPI_ReleaseDC($hDesktop, $hSrcDC)
	_WinAPI_DeleteDC($hDstDC)
	_WinAPI_GetBitmapBits($hBitmap, $W * $H * 3, DllStructGetPtr($tBD, 'Bits'))
	_WinAPI_DeleteObject($hBitmap)
	Return Binary(DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tBD) & ']', DllStructGetPtr($tBD)), 1))
EndFunc   ;==>_ScreenToBinary
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
А как это совместить со _ScreenCapture_Capture и как на примере показать в MsgBox() его бинарный код?
 

Bloodrinker

<Блуждающий...>
Сообщения
228
Репутация
19
в принципе можно, вот только MsgBox немного большой получится :whistle:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Здесь $bBmp, это обычный .bmp файл в бинарном виде. Можно даже написать так:

Код:
FileWrite('Screenshot.bmp', _ScreenToBinary())


Код:
#Include <WinAPIEx.au3>

$bBmp = _ScreenToBinary()
MsgBox(0, '', $bBmp)

Func _ScreenToBinary()

    Local $tBD, $tBI, $W, $H, $hBitmap, $hDesktop, $hSrcDC, $hDstDC, $hDstSv, $pBits, $Bytes

    $W = @DesktopWidth
    $H = @DesktopHeight
    $tBD = DllStructCreate('ushort bfType;align 2;dword bfSize;ushort bfReserved1;ushort bfReserved2;dword bfOffBits;' & $tagBITMAPINFOHEADER & 'byte Bits[' & ($W * $H * 3) & ']')
    $tBI = DllStructCreate($tagBITMAPINFOHEADER, DllStructGetPtr($tBD, 'biSize'))
    DllStructSetData($tBD, 'bfType', 0x4D42)
    DllStructSetData($tBD, 'bfSize', DllStructGetSize($tBD))
    DllStructSetData($tBD, 'bfReserved1', 0)
    DllStructSetData($tBD, 'bfReserved2', 0)
    DllStructSetData($tBD, 'bfOffBits', 14 + 40)
    DllStructSetData($tBI, 'biSize', DllStructGetSize($tBI))
    DllStructSetData($tBI, 'biWidth', $W)
    DllStructSetData($tBI, 'biHeight', -$H)
    DllStructSetData($tBI, 'biPlanes', 1)
    DllStructSetData($tBI, 'biBitCount', 24)
    DllStructSetData($tBI, 'biCompression', $BI_RGB)
    $hBitmap = _WinAPI_CreateDIBSection(0, $tBI, $DIB_RGB_COLORS, $pBits)
    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
    _WinAPI_BitBlt($hDstDC, 0, 0, $W, $H, $hSrcDC, 0, 0, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    _WinAPI_GetBitmapBits($hBitmap, $W * $H * 3, DllStructGetPtr($tBD, 'Bits'))
    _WinAPI_DeleteObject($hBitmap)
    Return Binary(DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tBD) & ']', DllStructGetPtr($tBD)), 1))
EndFunc   ;==>_ScreenToBinary
 

Bloodrinker

<Блуждающий...>
Сообщения
228
Репутация
19
мда... размеры впечатляют) но ведь попросили вывести...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
На мой взгляд совершенно бессмысленно создавать структуру .bmp (описание файла + заголовок + данные о цвете), а затем передавать по TCP. Намного проще и быстрее передать только данные о цвете.
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
он не передаёт бинарный код, и как мне потом вывести в форму картинку на другом компе если я буду передовать только данные о цвете?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Client.au3
Код:
#Include <WinAPIEx.au3>

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

While 1
	TCPSend($Socket, _GetScreenshot(0, 0, 800, 600))
	If @error Then
		ExitLoop
	EndIf
	If MsgBox(4 + 32, '', 'Continue?') <> 6 Then
		ExitLoop
	EndIf
WEnd

TCPShutdown()

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

    Local $tBD, $hBitmap, $hDesktop, $hSrcDC, $hDstDC, $hDstSv, $pBits

	If $iWidth = -1 Then
		$iWidth = @DesktopWidth
	EndIf
    If $iHeight = -1 Then
		$iHeight = @DesktopHeight
	EndIf
    $tBD = DllStructCreate($tagBITMAPINFOHEADER & 'byte RGB[' & ($iWidth * $iHeight * 3) & ']')
	If @error Then
		Return 0
	EndIf
    DllStructSetData($tBD, 'biSize', 40)
    DllStructSetData($tBD, 'biWidth', $iWidth)
    DllStructSetData($tBD, 'biHeight', -$iHeight)
    DllStructSetData($tBD, 'biPlanes', 1)
    DllStructSetData($tBD, 'biBitCount', 24)
    DllStructSetData($tBD, 'biCompression', $BI_RGB)
    $hBitmap = _WinAPI_CreateDIBSection(0, $tBD, $DIB_RGB_COLORS, $pBits)
    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
    _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    _WinAPI_GetBitmapBits($hBitmap, $iWidth * $iHeight * 3, DllStructGetPtr($tBD, 'RGB'))
    _WinAPI_DeleteObject($hBitmap)
    Return Binary(DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tBD) & ']', DllStructGetPtr($tBD)), 1))
EndFunc   ;==>_GetScreenshot


Server.au3
Код:
#Include <WinAPIEx.au3>

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

GUICreate('MyGUI', 800, 600)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
GUISetState()

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

Global $tData = DllStructCreate('byte[' & (800 * 600 * 3 + 40) & ']')
Global $pData = DllStructGetPtr($tData)
Global $Size = DllStructGetSize($tData)
Global $tPart, $Count = 0

Do
	$bData = TCPRecv($Socket, $Size, 1)
	If @error Then
		ExitLoop
	EndIf
	If IsBinary($bData) Then
		$Lenght = BinaryLen($bData)
		$tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
		DllStructSetData($tPart, 1, $bData)
		$Count += $Lenght
		If $Count = $Size Then
			_SetScreenshot($Pic, $tData)
			$Count = 0
		EndIf
	EndIf
Until GUIGetMsg() = -3

TCPCloseSocket($Socket)
TCPShutdown()

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

	Local $tBD, $hBitmap, $pBits

	$hWnd = GUICtrlGetHandle($CtrlID)
	If Not $hWnd Then
		Return 0
	EndIf
    $hBitmap = _WinAPI_CreateDIBSection(0, $tData, $DIB_RGB_COLORS, $pBits)
	_WinAPI_SetBitmapBits($hBitmap, DllStructGetSize($tData) - 40, DllStructGetPtr($tData) + 40)
	_WinAPI_DeleteObject(_SendMessage($hWnd, 0x0172, 0, $hBitmap))
	$hPrev = _SendMessage($hWnd, 0x0173)
	If $hPrev <> $hBitmap Then
		_WinAPI_DeleteObject($hBitmap)
	EndIf
	If $fUpdate Then
		_WinAPI_UpdateWindow($hWnd)
	EndIf
	Return 1
EndFunc   ;==>_SetScreenshot
 

VladUs

Скриптер
Сообщения
621
Репутация
181
Yashied Вы талант ... Вы :king:
Это очень большая удача, что Вы у нас есть...
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Большое спасибо,просто супер...а без MsgBox() можно сделать? Пробывал,скрипт вылетает...
 
Верх