I have a BMP image copied to the clipboard that I will paste into a form object frame control in MS Access (2016).
What I need to know is the memory size that the image takes up on the clipboard (although it would be alright if there was a way to get the size information after it was in the object frame control if necessary). For example, is the image 76,582 bytes or 652 bytes or 942,002 bytes, etc?
Here is the code I use to paste the image from the clipboard into the object frame control:
With Me.imgGrabbedFrame 'Bound Object Frame control
.Class = "Paintbrush Picture"
.OLETypeAllowed = acOLEEmbedded
.Action = acOLEPaste
End With
Is there a way to get the memory taken up by an object on the clipboard?
You can just calculate the length of the value property of the frame. That's including any OLE meta-information.
LenB(Me.imgGrabbedFrame.Value)
The return value is the length in bytes.
Calculating it while on the clipboard is possible, but substantially more complicated.
To do that, first, let us define several functions to work with the clipboard:
Public Declare PtrSafe Function GetClipboardFormatNameW Lib "User32" (ByVal format As Long, ByVal lpszFormatName As LongPtr, ByVal cchMaxCount As Long) As Long
Public Declare PtrSafe Function OpenClipboard Lib "User32" (Optional ByVal hWndNewOwner As LongPtr) As Boolean
Public Declare PtrSafe Function CloseClipboard Lib "User32" () As Boolean
Public Declare PtrSafe Function EnumClipboardFormats Lib "User32" (ByVal format As Long) As Long
Public Declare PtrSafe Function CountClipboardFormats Lib "User32" () As Long
Public Declare PtrSafe Function GlobalSize Lib "Kernel32" (ByVal hMem As LongPtr) As LongPtr
Public Declare PtrSafe Function GetClipboardData Lib "User32" (ByVal uFormat As Long) As LongPtr
Then, let's define a function to iterate the different formats that are on the clipboard:
Public Sub ListClipboardFormats()
Dim l As Long
Dim format As Long
Dim b As String
OpenClipboard
b = String(255, vbNullChar)
For l = 1 To CountClipboardFormats
format = EnumClipboardFormats(format)
GetClipboardFormatNameW format, StrPtr(b), 255
If Left(b, 1) = vbNullChar Then
Debug.Print format
Else
Debug.Print b
End If
b = String(255, vbNullChar)
Next
CloseClipboard
End Sub
This function will print all available clipboard formats to the immediate window. If it's a built-in format, it will print a number. You can find the list of numbers here. A common number for image data is 8, for CF_DIB, a device-independent bitmap, or 17 for CF_DIBV5, a more modern variant of the same thing.
If we want to use one of the custom formats, let's define a function to get its number. This function will return 0 in case of an error or a non-existent clipboard format:
Public Function GetClipboardFormatByName(strName As String) As Long
Dim format As Long
Dim b As String
Dim l As Long
OpenClipboard
For l = 1 To CountClipboardFormats
b = String(255, vbNullChar) 'Initialize string buffer
format = EnumClipboardFormats(format) 'Get next format
GetClipboardFormatNameW format, StrPtr(b), 255 'Copy name to buffer
If Left(b, Len(strName)) = strName Then
GetClipboardFormatByName = format
Exit Function
End If
Next
CloseClipboard
End Function
Then, the final function to determine the size of what's on the clipboard if we have its format:
Public Function GetClipboardLength(ClipboardFormat As Long) As Long
OpenClipboard
Dim hClipboardGlobal As LongPtr
hClipboardGlobal = GetClipboardData(ClipboardFormat)
If hClipboardGlobal <> 0 Then
GetClipboardLength = GlobalSize(hClipboardGlobal)
End If
CloseClipboard
End Function
If we know a DIB is on the clipboard, this makes getting it's size as simple as GetClipboardLength(8)
. Note that this is the size of the DIB, and that might not actually be identical to the size of the data, when pasted, as it's saved, since additional processing might occur.
A note for size on the clipboard: size on the clipboard might be larger or smaller than the size of what you paste depending on the implementation. Programs can (and often will) put multiple representations of the same thing on the clipboard (text, rich text, image, OLE data object), and can also put it there in such a way it's only copied when accessed. That's why, when closing an Office program after copying a large object, you're often asked if you want to keep that object on the clipboard.