如何在MS Access VBA中获取MSForms.DataObject内容的大小

时间:2019-06-27 19:16:01

标签: vba ms-access access-vba clipboarddata

我已将BMP图像复制到剪贴板,并将其粘贴到MS Access(2016)中的表单对象框架控件中。

我需要知道的是图像在剪贴板上占用的内存大小(尽管如果有必要,可以在对象框架控件中获取大小信息后再找方法)。例如,图像是76582字节还是652字节还是942002字节等?

这是我用来将剪贴板中的图像粘贴到对象框架控件中的代码:

With Me.imgGrabbedFrame 'Bound Object Frame control
    .Class = "Paintbrush Picture"
    .OLETypeAllowed = acOLEEmbedded
    .Action = acOLEPaste
End With

有没有办法让剪贴板上的对象占用内存?

2 个答案:

答案 0 :(得分:3)

您可以只计算框架的value属性的长度。这包括任何OLE元信息。

LenB(Me.imgGrabbedFrame.Value)

返回值是以字节为单位的长度。

可以在剪贴板上进行计算,但是要复杂得多。

为此,首先让我们定义一些与剪贴板一起使用的功能:

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

然后,我们定义一个函数来迭代剪贴板上的不同格式:

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

此功能会将所有可用的剪贴板格式打印到立即窗口。如果是内置格式,它将打印一个数字。您可以找到数字here的列表。对于图像数据,通用的数字是8,对于设备无关的位图CF_DIB,或者对于CF_DIBV5(同一事物的更现代的变体)是17。

如果要使用一种自定义格式,让我们定义一个函数以获取其编号。如果发生错误或剪贴板格式不存在,此函数将返回0:

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

然后,最后一个确定剪贴板格式的大小的函数:

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

如果我们知道剪贴板上有DIB,则使它的大小像GetClipboardLength(8)一样简单。请注意,这是DIB的大小,并且由于保存而可能与粘贴时的数据大小实际上并不相同,因为可能会进行其他处理。

关于剪贴板上的 size的注释:剪贴板上的size可能大于或小于粘贴内容的大小,具体取决于实现方式。程序可以(并且经常会)将同一事物的多个表示形式放置在剪贴板上(文本,富文本格式,图像,OLE数据对象),并且还可以以仅在访问时才将其复制的方式放置在剪贴板上。这就是为什么在复制大对象后关闭Office程序时,经常会询问您是否要将该对象保留在剪贴板上。

答案 1 :(得分:0)

您可以将此功能与图像控件的属性部分中的图像url路径的字符串值一起使用

FileLen("C:\Temp\test file.xls")