Что нового

Как получить рисунок из буфера обмена

mef-t

Осваивающий
Сообщения
306
Репутация
30
Доброго времени суток.

Суть вопроса указана в теме.
По существу:
В буфере обмена содержится какая-то информация. Любая. Для примера берем растровое изображение, скопированное из буфера обмена.
Мне нужно эту информацию поместить в переменную.
Затем проделать с буфером обмена другие операции.
Затем очистить буфер обмена.
И поместить в него исходную информацию.

P.S. я бы хотел обойтись без создания файлов.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Код:
_ClipBoard_Open()
_ClipBoard_GetData()
;+ "См. также".
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Нужна ли эта функция _ClipBoard_Open()
На сколько я понял, _ClipBoard_GetData() работает без нее.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
mef-t [?]
Затем проделать с буфером обмена другие операции.
Для ваших других операций может понадобиться Open(в частности те функции, что написаны в "См. Также"). Для GetData она не нужна.
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Если использовать только _ClipBoard_GetData(), то оно ничего не возвращает.
@extended содержит 0.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Код:
_ClipBoard_Open(0)
	$hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
	_ClipBoard_Close()

Так получите Handle to a bitmap.
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Спасибо.
Помогло.

Большая просьба подсказать, как после этой операции, работы с буфером и другим содержимым и очистки буфера вернуть полученные данные обратно?
В том же Paint выдает, что данные из буфера обмена невозможно вставить

использовал конструкцию по аналогии
Код:
_ClipBoard_Open(0)
	_ClipBoard_SetDataEx($hBitmap, $CF_BITMAP)
    _ClipBoard_Close()
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
mef-t

Сделал подробно с возможностью вносить изменения средствами GDIPlus.
Код:
#include <WinAPIEx.au3>
#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <Clipboard.au3>

_ClipBoard_Open(0)
_GDIPlus_Startup()

$hBitmap = _ClipBoard_GetDataEx( $CF_BITMAP )
$tBitmapSize = _WinAPI_GetBitmapDimension( $hBitmap )
	$iWidth = DllStructGetData( $tBitmapSize, 1 )
	$iHeight = DllStructGetData( $tBitmapSize, 2 )

$hGdiBitmap = _GDIPlus_BitmapCreateFromHBITMAP( $hBitmap )
$hGdiBitmapClone = _GDIPlus_BitmapCloneArea( $hGdiBitmap, 0, 0, $iWidth, $iHeight )
_WinAPI_DeleteObject( $hGdiBitmap )

MsgBox( 64, "", "Width: " & $iWidth & @LF & _
	"Height: " & $iHeight & @LF & _
	"Original: " & $hBitmap & @LF & _
	"Clone: " & $hGdiBitmapClone )
_ClipBoard_Empty()

$hGdiHBitmapClone = _GDIPlus_BitmapCreateHBITMAPFromBitmap( $hGdiBitmapClone )
$hBitmap = __ImageCreateGDICompatibleHBITMAP( $hGdiHBitmapClone )
_WinAPI_DeleteObject( $hGdiHBitmapClone )
_WinAPI_DeleteObject( $hGdiBitmapClone )

_ClipBoard_SetDataEx( $hBitmap,  $CF_BITMAP )
_ClipBoard_Close()
_GDIPlus_Shutdown()

MsgBox( 64, "", "Пробуй вставить изображение" )

; ****
Func __ImageCreateGDICompatibleHBITMAP( $hBitmap )
	Local $hBitmap2 = _WinAPI_CopyImage( $hBitmap, 0, 0, 0, BitOr( $LR_COPYDELETEORG, $LR_COPYRETURNORG ) )
	; ---
	Return $hBitmap2
EndFunc
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Добрый день.

Из всего перечисленного, если я воспользуюсь только:
Код:
_ClipBoard_Open(0)
$hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
$hBitmap = _WinAPI_CopyImage( $hBitmap, 0, 0, 0, BitOr( $LR_COPYDELETEORG, $LR_COPYRETURNORG ))
_ClipBoard_Empty()
;~ любые действия
_ClipBoard_SetDataEx($hBitmap, $CF_BITMAP)
_ClipBoard_Close()

То у меня все так же работает.
Другими словами, мне требуется выполнить только
Код:
$hBitmap = _WinAPI_CopyImage( $hBitmap, 0, 0, 0, BitOr( $LR_COPYDELETEORG, $LR_COPYRETURNORG ))

Просьба подсказать, действительно ли этого достаточно, или же весь описанный код предназначен для решения каких то проблем?
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
mef-t
Достаточно, я просто изначально хотел сделать по-другому, затем решил сделать возможность изменять в GDIPlus. Вот и получились дебри, зато по крайней мере подробно.

Проблема у тебя заключалась в том, что после очистки буфера битмап удаляется и, следовательно, указатель на него становится не действительным. А тут ты копируешь битмап перед его удалением.
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Да, я уже разобрался. Спасибо.
Проблема именно в этом и была.
 

SECTOR

Продвинутый
Сообщения
399
Репутация
59
Поднимаю тему.
Необходимо сохранить в файл изображение с прозрачностью (код от из примеров убивает её).
Было бы не плохо если найдется решение. Сам не осилил, поиск молчит.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Некоторые программы, например Word и Gimp, поддерживают специальный формат буфера обмена под названием "PNG"
Код:
#include <Clipboard.au3>

Global Const $CF_PNG = 49690
$Data = _ClipBoard_GetData($CF_PNG)
If $Data Then FileWrite("test.png", $Data)
 

SECTOR

Продвинутый
Сообщения
399
Репутация
59
Некоторые программы, например Word и Gimp, поддерживают специальный формат буфера обмена под названием "PNG"
Забавно, но в моем случае код формата оказался другим
Код:
#include <Clipboard.au3>
#include <Array.au3>

Global $iFormat = 0, $sFile = @ScriptDir & "\test.png"

_ClipBoard_Open(0)

While 1
    $iFormat = _ClipBoard_EnumFormats($iFormat)
    If $iFormat = 0 Then ExitLoop
    ConsoleWrite(StringFormat("> Format %d: %s\n",$iFormat,_ClipBoard_GetFormatName($iFormat)))
WEnd

;~ Global Const $CF_PNG = 49690
Global Const $CF_PNG = 49458
$Data = _ClipBoard_GetData($CF_PNG)
If $Data Then
    ConsoleWrite("+ PNG" & @CRLF)
    FileDelete($sFile)
    FileWrite($sFile, $Data)
Else
    ConsoleWrite("! None" & @CRLF)
EndIf

_ClipBoard_Close()

Жаль, но это не сто процентный способ рения задачи.
Я вот всё думаю про форматы CF_DIB и CF_DIBV5, возможно из них удастся что-то выудить.
Но не приложу ума как с ними работать.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Верх