'Thanks to Stephan Bullen for most of this API code
'Declare a UDT to store a GUID for the IPicture OLE Interface
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
#If Win64 Then
Type uPicDesc
Size As Long
Type As Long
hPic As LongPtr
hPal As LongPtr
End Type
Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function EmptyClipboard Lib "user32" () As LongPtr
Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function OleCreatePictureIndirect Lib "OleAut32.dll" (PicDesc As uPicDesc, _
RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Declare PtrSafe Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" ( _
ByVal hemfSrc As LongPtr, ByVal lpszFile As String) As LongPtr
Declare PtrSafe Function CopyImage Lib "user32" ( _
ByVal Handle As LongPtr, ByVal un1 As Long, ByVal n1 As Long, _
ByVal N2 As Long, ByVal un2 As Long) As LongPtr
Dim hPtr As LongPtr
#Else
Type uPicDesc
Size As Long
Type As Long
hPic As Long
hPal As Long
End Type
Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function EmptyClipboard Lib "user32" () As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long
Declare Function OleCreatePictureIndirect Lib "OleAut32.dll" (PicDesc As uPicDesc, _
RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" _
(ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
Declare Function CopyImage Lib "user32" (ByVal Handle As Long, _
ByVal un1 As Long, ByVal n1 As Long, ByVal N2 As Long, ByVal un2 As Long) As Long
Dim hPtr As Long
#End If
'The API format types we're interested in
Public Const CF_BITMAP = 2
Private Const CF_PALETTE = 9
Public Const CF_ENHMETAFILE = 14
Private Const IMAGE_BITMAP = 0
Private Const LR_COPYRETURNORG = &H4
'OLE Picture types
Private Const PICTYPE_BITMAP = 1
Private Const PICTYPE_ENHMETAFILE = 4
'======================================================================================================
Function PastePictureVBA7(Optional lXlPicType As Long = xlPicture) As IPicture
'Some pointers
Dim H As Long, hPicAvail As Long, hPtr As LongPtr, hPal As LongPtr
Dim lPicType As Long, hCopy As LongPtr
'Convert the type of picture requested from the xl constant to the API constant
lPicType = IIf(lXlPicType = xlBitmap, CF_BITMAP, CF_ENHMETAFILE)
'Check if the clipboard contains the required format
hPicAvail = IsClipboardFormatAvailable(lPicType)
If hPicAvail <> 0 Then
'Get access to the clipboard
H = OpenClipboard(0&)
If H > 0 Then
'Get a handle to the image data
hPtr = GetClipboardData(lPicType)
'Create our own copy of the image on the clipboard, in the appropriate format.
If lPicType = CF_BITMAP Then
hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
Else
hCopy = CopyEnhMetaFile(hPtr, vbNullString)
End If
'Release the clipboard to other programs
H = CloseClipboard
'If we got a handle to the image, convert it into a Picture object and return it
If hPtr <> 0 Then Set PastePictureVBA7 = CreatePictureVBA7(hCopy, 0, lPicType)
End If
Else
MsgBox "No clipboard data!"
End If
End Function
Public Function PastePicture(Optional lXlPicType As Long = xlPicture) As IPicture
Dim H As Long, hPicAvail As Long, hPtr As Long, hPal As Long, lPicType As Long, hCopy As Long
'Convert the type of picture requested from the xl constant to the API constant
lPicType = IIf(lXlPicType = xlBitmap, CF_BITMAP, CF_ENHMETAFILE)
'Check if the clipboard contains the required format
hPicAvail = IsClipboardFormatAvailable(lPicType)
If hPicAvail <> 0 Then
H = OpenClipboard(0&) 'Get access to the clipboard
If H > 0 Then
hPtr = GetClipboardData(lPicType) 'Get a handle to the image data
'Create our own copy of the image on the clipboard, in the appropriate format.
If lPicType = CF_BITMAP Then
hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
Else
hCopy = CopyEnhMetaFile(hPtr, vbNullString)
'MsgBox "HO"
End If
'clear then close clipboard
EmptyClipboard
H = CloseClipboard 'Release the clipboard to other programs
'If we got a handle to the image, convert it into a Picture object and return it
If hPtr <> 0 Then Set PastePicture = CreatePicture(hCopy, 0, lPicType)
End If
Else
MsgBox "No clipboard data!"
End If
End Function
Private Function CreatePictureVBA7(ByVal hPic As LongPtr, ByVal hPal As LongPtr, ByVal lPicType) As IPicture
' IPicture requires a reference to "OLE Automation"
Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPicture
' Create the Interface GUID (for the IPicture interface)
With IID_IDispatch
.Data1 = &H7BF80980
.Data2 = &HBF32
.Data3 = &H101A
.Data4(0) = &H8B
.Data4(1) = &HBB
.Data4(2) = &H0
.Data4(3) = &HAA
.Data4(4) = &H0
.Data4(5) = &H30
.Data4(6) = &HC
.Data4(7) = &HAB
End With
' Fill uPicInfo with necessary parts.
With uPicInfo
.Size = Len(uPicInfo) ' Length of structure.
.Type = IIf(lPicType = CF_BITMAP, PICTYPE_BITMAP, PICTYPE_ENHMETAFILE) ' Type of Picture
.hPic = hPic ' Handle to image.
.hPal = IIf(lPicType = CF_BITMAP, hPal, 0) ' Handle to palette (if bitmap).
End With
' Create the Picture object.
r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, 1, IPic)
' If an error occured, show the description
If r <> 0 Then Debug.Print "Create Picture: " '& fnOLEError(r)
' Return the new Picture object.
Set CreatePictureVBA7 = IPic
End Function
Private Function CreatePicture(ByVal hPic As Long, ByVal hPal As Long, ByVal lPicType) As IPicture
Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPicture
' Create the Interface GUID (for the IPicture interface)
With IID_IDispatch
.Data1 = &H7BF80980
.Data2 = &HBF32
.Data3 = &H101A
.Data4(0) = &H8B
.Data4(1) = &HBB
.Data4(2) = &H0
.Data4(3) = &HAA
.Data4(4) = &H0
.Data4(5) = &H30
.Data4(6) = &HC
.Data4(7) = &HAB
End With
' Fill uPicInfo with necessary parts.
With uPicInfo
.Size = Len(uPicInfo) ' Length of structure.
.Type = IIf(lPicType = CF_BITMAP, PICTYPE_BITMAP, PICTYPE_ENHMETAFILE) ' Type of Picture
.hPic = hPic ' Handle to image.
.hPal = IIf(lPicType = CF_BITMAP, hPal, 0) ' Handle to palette (if bitmap).
End With
' Create the Picture object.
r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic)
' If an error occured, show the description
If r <> 0 Then Debug.Print "Create Picture Error" ' & fnOLEError(r)
Set CreatePicture = IPic ' Return the new Picture object.
End Function
To operate, copy a picture to the clipboard and run this code...