home *** CD-ROM | disk | FTP | other *** search
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' OLE2BM.BAS ver. 1.1 VB 3.0 Pro Module rev. 5/07/94
- '____________________________________________________________________________
- '
- ' The VB 3.0 Pro code in this module provides a way to transfer bitmap data
- ' back and forth between a PaintBrush object within an OLE 2.0 control (use
- ' MSOLE2.VBX, not OLECLIENT.VBX!) and a picture box on a container form such
- ' that the user can edit the bitmap manually in PaintBrush along the way.
- '
- ' This capability is useful when you wish to draw certain bitmap elements
- ' programmatically before or after hand editing.
- '
- ' The considerable effort required in the support procedures below is quite
- ' typical of the wall one hits in attempting to gain programmatic control
- ' over data in embedded OLE 2.0 objects under VB. Getting the data into the
- ' OLE2 control is relatively easy--getting it out is the hard part.
- '
- ' If you know a simpler way to get the data out, I'd love to hear from you!
- '
- ' NB: The function OleFile2Picture() buffers bitmap data in a big VB string.
- ' This procedure must be rewritten to handle bitmaps larger than or near 64K
- ' in size.
- '
- ' Jeremy McCreary
- ' Cliffshade Computing
- ' CIS [72341,3716]
- '____________________________________________________________________________
-
- Option Explicit
- DefInt A-Z
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Bitmap-related constants and data structures
- '____________________________________________________________________________
-
- Global Const OLE_CREATE_EMBED = 0 ' Ole control .Action settings
- Global Const OLE_ACTIVATE = 7
- Global Const OLE_SAVE_TO_FILE = 11
-
- Global Const OLE_CHANGED = 0 ' Ole control .Updated event code
-
- Global Const SRCCOPY = &HCC0020 ' BitBlt raster op: Overwrite destination
-
- Global Const CBM_INIT = &H4& ' Init created DIB with the data passed
- Global Const DIB_RGB_COLORS = 0 ' DIB file color tables use RGB values
- Global Const OBJECT_HEADER_SIZE = 20 ' OLE file header length
-
- Type BitmapFileHeaderType ' File header common to =all= Win 3.x .BMP files
- bfType As Integer ' Always contains string abbreviation "BM"
- bfSize As Long ' Bitmap file size in bytes
- bfReserved1 As Integer ' Set to 0 (Mouse cursor hotspot x coord)
- bfReserved2 As Integer ' Set to 0 (Mouse cursor hotspot y coord)
- bfOffBits As Long ' Offset from start of this header to start of data
- End Type
-
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Required Windows 3.1 API declarations in type-safe form.
- '____________________________________________________________________________
-
- Declare Function AnsiPrev Lib "User" (ByVal VBStr$, ByVal VBStr$) As Long
- Declare Function BitBlt Lib "GDI" (ByVal DesthDC, ByVal DestX, ByVal DestY, ByVal DestWidth, ByVal DestHeight, ByVal SourcehDC, ByVal SourceX, ByVal SourceY, ByVal ROP As Long)
- Declare Function CreateCompatibleDC Lib "GDI" (ByVal hDC)
- Declare Function CreateDIBitmapPacked Lib "GDI" Alias "CreateDIBitmap" (ByVal hDC, ByVal lpPackedDIB&, ByVal InitFlag&, ByVal lpDataBits&, ByVal lpBitmapInfo&, ByVal ColorUse)
- Declare Function DeleteDC Lib "GDI" (ByVal hDC)
- Declare Function DeleteObject Lib "GDI" (ByVal hObj)
- Declare Function GetTempFileName Lib "Kernel" (ByVal DriveLetterAscii, ByVal PrefixName$, ByVal Unique, ByVal NameBuffer$)
- Declare Function SelectObject Lib "GDI" (ByVal hDC, ByVal hObject)
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Transfer an embedded bitmap object from an OLE 2.0 (MSOLE2.VBX) control to
- ' a VB picture box via the intermediaries of a temporary OLE file and a
- ' packed DIB memory structure.
- '____________________________________________________________________________
- Sub Ole2Pic (pic As PictureBox, ole As Control)
- Dim f, h0, hbm, hmem, hpic, r
- Dim file$, kind$
-
- file$ = TempFileName$("") ' Open a temporary OLE file
- f = FreeFile
- Open file$ For Binary As f
- ole.FileNumber = f ' Make its handle the save destination
- ole.Action = OLE_SAVE_TO_FILE ' Save the embedded data as an OLE 2.0 file
- Close f
- kind$ = ole.Class ' Get correct object type
-
- hbm = OLEFile2Picture(pic, kind$, file$) ' Extract the bitmap from the OLE file
- If hbm Then ' Copy the extracted DDB into picture box
- hpic = pic.hDC
- hmem = CreateCompatibleDC(hpic)
- h0 = SelectObject(hmem, hbm) ' Select the DDB into the memory DC
- r = BitBlt(hpic, 0, 0, CInt(pic.ScaleWidth), CInt(pic.ScaleHeight), hmem, 0, 0, SRCCOPY)
- r = SelectObject(hmem, h0) ' Restore the object previously selected
- r = DeleteObject(hbm) ' Recover system resources
- r = DeleteDC(hmem)
- pic.Refresh ' Update the screen now
- End If
-
- Kill file$ ' Waste the temporary OLE file
-
- End Sub
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Copy the device-independent bitmap (DIB) contained in a PaintBrush object
- ' OLE 2.0 file to a packed DIB memory image, create a device-dependent bitmap
- ' (DDB) from the packed DIB, and return the DDB handle for future reference.
- '
- ' NB: Once the DDB is created (i.e., once the packed DIB color table has been
- ' translated to the nearest available device-specific colors), subsequent
- ' display of the bitmap goes =much= faster than if displayed directly as a
- ' packed DIB, say with StretchDIBits().
- '____________________________________________________________________________
- Function OLEFile2Picture (pic As PictureBox, kind$, OLEfile$)
- Dim hbm, hOLE, k
- Dim buffers As Long, bytes As Long, ptr As Long, remainder As Long
- Dim BitmapOffset As Long, lpDataBits As Long, lpPackedDIB As Long
- Dim buffer$, PackedDIB$
- Dim bfh As BitmapFileHeaderType
- Const BUFFER_SIZE = 8192 ' File input buffer length
- Const STRING_LIMIT = 65500
- Const MB = 16 ' Stop style MsgBox
-
- hOLE = FreeFile ' Open the source OLE file
- Open OLEfile$ For Binary As hOLE
-
- If LOF(hOLE) > OBJECT_HEADER_SIZE Then
- buffer$ = Space$(BUFFER_SIZE)
- Get hOLE, 1, buffer$ ' Get first bufferfull of OLE file data
- ptr = InStr(buffer$, kind$) ' Look for a correct object class name
- If ptr Then ' Find the bitmap's starting offset
- BitmapOffset = InStr(ptr, buffer$, "BM")
- If BitmapOffset Then ' Read the embedded bitmap file
- Get hOLE, BitmapOffset, bfh ' Read the bitmap file header
- bytes = bfh.bfSize - Len(bfh) ' Calculate number of buffers needed
- If bytes > STRING_LIMIT Then ' Can't use a VB string buffer
- MsgBox "Sorry, your bitmap is too large to buffer in a VB string.", MB, "OLE2 File Error"
- GoTo OLEFile2PictureExit ' Beat feet
- Else ' Initialize string to eventual size to
- PackedDIB$ = Space$(bytes) ' avoid "Out of string space" error
- End If
- buffer$ = Space$(BUFFER_SIZE)
- buffers = bytes \ BUFFER_SIZE
- remainder = bytes Mod BUFFER_SIZE
- ptr = 1& ' ptr -> 1st byte of bitmapinfo header
- Do Until ptr > bytes - remainder ' Build up a packed DIB memory image in
- Get hOLE, , buffer$ ' a VB string, 1 bufferfull at a time
- Mid$(PackedDIB$, ptr, BUFFER_SIZE) = buffer$
- ptr = ptr + BUFFER_SIZE
- Loop
- buffer$ = Space$(remainder) ' Now get what's left
- Get hOLE, , buffer$
- Mid$(PackedDIB$, ptr) = buffer$
- lpPackedDIB = SSegAddr(PackedDIB$) ' Get a long pointer to packed DIB
- lpDataBits = lpPackedDIB + bfh.bfOffBits - Len(bfh) ' and data bits
- ' Create a device-dependent bitmap (DDB) compatible with the target
- ' picture box device context.
- hbm = CreateDIBitmapPacked(pic.hDC, lpPackedDIB, CBM_INIT, lpDataBits, lpPackedDIB, DIB_RGB_COLORS)
- PackedDIB$ = "" ' Free up memory
- buffer$ = ""
- Else
- MsgBox "Sorry, couldn't find an embedded bitmap within the first " & Format$(BUFFER_SIZE) & " bytes of your OLE2 file.", MB, "OLE2 File Error"
- End If
- Else
- MsgBox "Sorry, couldn't find the '" & kind$ & "' class name in your OLE2 file header.", MB, "OLE2 File Error"
- End If
- Else
- MsgBox "Sorry, your OLE2 file is too small to contain a bitmap.", MB, "OLE2 File Error"
- End If
-
- OLEFile2PictureExit:
- Close hOLE ' Done with the OLE file
- OLEFile2Picture = hbm ' Pass back the DDB handle
-
- End Function
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Embed the bitmap contained within a VB picture box in an OLE 2.0 control
- ' (MSOLE2.VBX) via a temporary .BMP file.
- '
- ' NB: The OLE control =requires= the .SourceDoc file to have the extension
- ' "BMP" in order to embed its data as a PaintBrush object.
- '____________________________________________________________________________
- Sub Pic2Ole (pic As PictureBox, ole As Control)
- Dim r
- Dim file$
-
- file$ = TempFileName$("BMP") ' Get a temporary file name with .BMP ext.
- SavePicture pic.Image, file$ ' Save the picture box bitmap as a DIB file
- ole.Class = "PBrush" ' Specify creation of Pbrush bitmap object
- ole.SourceDoc = file$ ' Make the temporary file the data source
- ole.Action = OLE_CREATE_EMBED ' Embed the data as an OLE 2.0 object
- Kill file$ ' Waste the temporary file
-
- End Sub
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Get a long pointer to the VB string passed using an AnsiPrev() trick.
- '____________________________________________________________________________
- Function SSegAddr (VB$) As Long
-
- SSegAddr = AnsiPrev(ByVal VB$, ByVal VB$)
-
- End Function
-
- '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ' Create a temporary file, which will live briefly in the subdirectory
- ' specified by the user's TEMP environment variable--with luck perhaps
- ' on a ram drive for speed.
- '____________________________________________________________________________
- Function TempFileName$ (ext$)
- Dim r
- Dim file$
- Const DOT = 46 ' ANSI code for period
-
- file$ = Space$(255) ' Allow plenty of room for the name
- r = GetTempFileName(0, "", -1, file$) ' Let Windows supply a name
- file$ = Trim(file$) ' Strip off any excess white space
- If Len(ext$) Then ' Replace the .TMP extension
- r = InStr(file$, ".TMP") ' Find the .TMP extension
- If r Then ' Replace if present
- If Asc(ext$) <> DOT Then r = r + 1 ' Does ext. passed include period?
- Mid$(file$, r) = ext$ ' Replace .TMP with new extension
- End If
- End If
-
- TempFileName$ = file$ ' Pass back the temporary file name
-
- End Function
-
-