Microsoft KB Archive/103115: Difference between revisions
m (Text replacement - ">" to ">") |
m (Text replacement - "<" to "<") |
||
Line 197: | Line 197: | ||
OleFileName = CopyOleBitmapToFile(OleField) | OleFileName = CopyOleBitmapToFile(OleField) | ||
If OleFileName | If OleFileName <> "" Then | ||
'Display the bitmap: | 'Display the bitmap: |
Revision as of 10:15, 20 July 2020
Article ID: 103115
Article Last Modified on 2/14/2005
APPLIES TO
- Microsoft Visual Basic 3.0 Professional Edition
This article was previously published under Q103115
SYMPTOMS
If you try to bind a picture control to a Microsoft Access database field that contains an OLE object such as a PaintBrush bitmap, you will correctly receive the error "Invalid picture."
CAUSE
This error occurs because the picture control can only bind to a bitmap, metafile, or icon stored in the database field -- not to an OLE object.
RESOLUTION
Using the method described below, you can simulate the binding of a picture control to a PaintBrush OLE (or bitmap) object.
MORE INFORMATION
If you use Microsoft Access to store a PaintBrush picture in an OLE field, there is no way to bind any control provided with Visual Basic version 3.0 to the OLE field. Ideally you could bind the MSOLE2 control to the data control, but no features were added to the MSOLE2 control to allow you to bind to a database field.
From Visual Basic, you can use a bound picture control to store and retrieve bitmaps, metafiles, and icons directly in a long binary or OLE database field. However, Microsoft Access will not be able to display the bitmap, metafile, or icon that you've stored.
Step-by-Step Example
The following example demonstrate how you can create an application that retrieves and displays a bitmap from an OLE field containing a PaintBrush object. To get it to work, you need to have the NWIND.MDB sample database provided with Microsoft Access.
- Start Visual Basic or from the File menu, choose New Project (ALT, F, N) if Visual Basic is already running. Form1 is created by default.
- From the File menu, choose New Module (ALT, F, M). Module1 is created.
- Add a picture control (Picture1) to Form1.
- Add a data control (Data1) to Form1.
- Set the Data1.Databasename property to NWIND.MDB and include the full path to this file. This file is a sample database that ships with Microsoft Access versions 1.0 and 1.1. Look for it in your Microsoft Access directory -- for example, C:\ACCESS.
- Set the Data1.RecordSource property to Employees.
Add the following code to the Data1_Reposition event procedure in Form1:
'********************************************************************** '* Title '* Data1_Reposition () '* '* Description '* Each time the data control is being repositioned to a new '* record, the bitmap contained in the "Photo" is displayed '* in Picture1. Therefore, it simulates binding the picture '* control to an OLE field containing a Microsoft Paint Brush '* picture object. '* '* The code requires a field named Photo, and it requires that '* the embedded OLE object be a Microsoft Paint Brush picture. '********************************************************************** Sub Data1_Reposition () Screen.MousePointer = 11 'Make sure this is the current record: If Not (Data1.Recordset.EOF And Data1.Recordset.BOF) Then 'Change Photo to the name of the OLE field 'for the record set you are using: DisplayOleBitmap Picture1, Data1.Recordset("Photo") End If Screen.MousePointer = 0 End Sub
Add the following code to Module1:
'********************************************************************** '* OLEACCES.BAS '* '* general-declarations section '********************************************************************** Option Explicit Global Const LENGTH_FOR_SIZE = 4 Global Const OBJECT_SIGNATURE = &H1C15 Global Const OBJECT_HEADER_SIZE = 20 Global Const CHECKSUM_SIGNATURE = &HFE05AD00 Global Const CHECKSUM_STRING_SIZE = 4 'PT : Window sizing information for object ' Used in OBJECTHEADER type Type PT Width As Integer Height As Integer End Type 'OBJECTHEADER : Contains relevant information about object ' Type OBJECTHEADER Signature As Integer 'Type signature (0x1c15) HeaderSize As Integer 'Size of header (sizeof(struct 'OBJECTHEADER) + cchName + 'cchClass) ObjectType As Long 'OLE Object type code (OT_STATIC, 'OT_LINKED, OT_EMBEDDED) NameLen As Integer 'Count of characters in object 'name (CchSz(szName) + 1) ClassLen As Integer 'Count of characters in class 'name (CchSz(szClass) + 1) NameOffset As Integer 'Offset of object name in 'structure (sizeof(OBJECTHEADER)) ClassOffset As Integer 'Offset of class name in 'structure (ibName + cchName) ObjectSize As PT 'Original size of object (see 'code below for value) OleInfo As String * 256 End Type Type OLEHEADER OleVersion As Long Format As Long OleInfo As String * 512 End Type 'Enter the following Declare statement as one, single line: Declare Function GetTempFileName Lib "Kernel" (ByVal cDriveLetter As Integer, ByVal lpPrefixString As String, ByVal wUnique As Integer, ByVal lpTempFileName As String) As Integer 'Enter the following Declare statement as one, single line: Declare Sub hmemcpy Lib "Kernel" (dest As Any, source As Any, ByVal bytes As Long) '********************************************************************** '* Title '* DisplayOleBitmap '* '* Description '* Causes the OLE bitmap in the given data field to be '* copied to a temporary file. The bitmap is then '* displayed in the given picture. '* '* Parameters '* ctlPict Picture control in which to display the '* bitmap image '* OleField Database field containing the OLE '* embedded Microsoft Paint Brush bitmap '********************************************************************** Sub DisplayOleBitmap (ctlPict As Control, OleField As Field) Const DT_LONGBINARY = 11 Dim r As Integer Dim Handle As Integer Dim OleFileName As String If OleField.Type = DT_LONGBINARY Then OleFileName = CopyOleBitmapToFile(OleField) If OleFileName <> "" Then 'Display the bitmap: ctlPict.Picture = LoadPicture(OleFileName) 'Delete the temporary file: Kill OleFileName End If End If End Sub '********************************************************************** '* Title '* CopyOleBitmapToFile '* '* Description '* Copies the bitmap contained in a OLE field to a file. '********************************************************************** Function CopyOleBitmapToFile (OleField As Field) As String Const BUFFER_SIZE = 8192 Dim tempFileName As String Dim Handle As Integer Dim Buffer As String Dim BytesNeeded As Long Dim Buffers As Long Dim Remainder As Long Dim ObjHeader As OBJECTHEADER Dim sOleHeader As String Dim ObjectOffset As Long Dim BitmapOffset As Long Dim BitmapHeaderOffset As Integer Dim r As Integer Dim i As Long tempFileName = "" If OleField.FieldSize() > OBJECT_HEADER_SIZE Then 'Get the Microsoft Access OLE header: sOleHeader = OleField.GetChunk(0, OBJECT_HEADER_SIZE) hmemcpy ObjHeader, ByVal sOleHeader, OBJECT_HEADER_SIZE 'Calculate the offset where the OLE object starts: ObjectOffset = ObjHeader.HeaderSize + 1 'Get enough bytes after the OLE header so that we get the 'bitmap header Buffer = OleField.GetChunk(ObjectOffset, 512) 'Make sure the class of the object is a Paint Brush object If Mid(Buffer, 12, 6) = "PBrush" Then BitmapHeaderOffset = InStr(Buffer, "BM") If BitmapHeaderOffset > 0 Then 'Calculate the beginning of the bitmap: BitmapOffset = ObjectOffset + BitmapHeaderOffset -1 'Calculate the size of the bitmap: 'Enter the following BytesNeeded statement as a single line: BytesNeeded = OleField.FieldSize() - OBJECT_HEADER_SIZE - BitmapHeaderOffset - CHECKSUM_STRING_SIZE + 1 'Calculate the number of buffers needed to copy 'the OLE object based on the bitmap size: Buffers = BytesNeeded \ BUFFER_SIZE Remainder = BytesNeeded Mod BUFFER_SIZE 'Get a unique, temp filename: tempFileName = Space(255) r = GetTempFileName(0, "", -1, tempFileName) 'Copy the bitmap to the temporary file chunk by chunk: Handle = FreeFile Open tempFileName For Binary As #Handle For i = 0 To Buffers - 1 'Enter the following Buffer statement as a single line: Buffer = OleField.GetChunk(BitmapOffset + i * BUFFER_SIZE, BUFFER_SIZE) Put #Handle, , Buffer Next 'Copy the remaining chunk of the bitmap to the file: 'Enter the following Buffer statement as a single line: Buffer = OleField.GetChunk(BitmapOffset + Buffers * BUFFER_SIZE, Remainder) Put #Handle, , Buffer Close #Handle End If End If End If CopyOleBitmapToFile = Trim(tempFileName) End Function
- From the Run menu, choose Start (ALT, R, S) or press the F5 key to run the program. You should see the photo of the first employee displayed in the picture box. By clicking the directional arrows on the data control, you can view the other employee photos.
Keywords: kbprb KB103115