Как получить размер содержимого MSForms.DataObject в MS Access VBA - PullRequest
0 голосов
/ 27 июня 2019

У меня есть изображение BMP, скопированное в буфер обмена, которое я вставлю в элемент управления фреймом объекта формы в MS Access (2016).

Что мне нужно знать, так это размер памяти, на который занимает изображениебуфер обмена (хотя было бы хорошо, если бы был способ получить информацию о размере после того, как она была в элементе управления фреймом объекта при необходимости).Например, составляет ли изображение 76 582 байта, или 652 байта, или 942 002 байта и т. Д.?

Вот код, который я использую для вставки изображения из буфера обмена в элемент управления фреймом объекта:

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

Есть ли способ получить память, занятую объектом в буфере обмена?

Ответы [ 2 ]

3 голосов
/ 27 июня 2019

Вы можете просто рассчитать длину значения свойства кадра.Это включает любую метаинформацию 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

Эта функция выводит все доступные форматы буфера обмена в ближайшее окно.Если это встроенный формат, он напечатает число.Вы можете найти список номеров здесь .Общее число для данных изображения - 8, для CF_DIB, бит-карта, не зависящая от устройства, или 17 для CF_DIBV5, более современного варианта того же самого.

Если мы хотим использовать один из пользовательских форматов, давайтеопределить функцию, чтобы получить ее номер.Эта функция будет возвращать 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, и он может фактически не совпадать с размером данных при вставке и сохранении, поскольку может произойти дополнительная обработка.

Примечание для размера в буфере обмена : размер в буфере обмена может быть больше или меньше размера того, что вы вставляете, в зависимости от реализации.Программы могут (и часто будут) помещать в буфер обмена несколько представлений одной и той же вещи (текст, форматированный текст, изображение, объект данных OLE), а также могут размещать их там таким образом, чтобы они копировались только при обращении к ним.Вот почему при закрытии приложения Office после копирования большого объекта вас часто спрашивают, хотите ли вы сохранить этот объект в буфере обмена.

0 голосов
/ 27 июня 2019

Эту функцию можно использовать со строковым значением пути URL-адреса изображения в разделе свойств элемента управления изображением

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