home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Tool Box
/
SIMS_2.iso
/
vb_code1
/
ole_2_bm
/
ole2bm.bas
next >
Wrap
BASIC Source File
|
1994-05-07
|
11KB
|
230 lines
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' 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