Verified Software Products Company
792 Phillips Road || Arroyo Grande, CA 93420-5019 || Phone: (805) 489-5309
Email: bkandler@verisof.com
SERVICES FREEBIES TIPS and TRICKS ARTICLES LINKS HOME
Our Products

Classes
BMPBMP
CryptoCrypto
CSVStringsCSVStrings
DataLoggerDataLogger
DatesDates
DebugRecorderDebugRecorder
FileNameSetFileNameSet
FileSenderFileSender
RDOConnectMasterRDOConnectMaster
ReportAidsReportAids
ShellerSheller
StringSetStringSet
WEBUtilitiesWEBUtilities

Modules
DAOLibDAOLib
GlobalsGlobals
RegistryRegistry

Programs
BatcherBatcher
HTMLGenHTMLGen
KillTimeKillTime
TimedMessageTimedMessage
BMP: This class allows you to load and interpret .BMP files. Just set the FileName property and execute the ReadFile method to load the file. It takes just 4 lines to read the file(Dim, Set, FileName=, ReadFile).

Additional properties then let you obtain the Size, Height, Width, ColorsUsed, and ColorTable. GetImage returns an array containing the image itself. It takes just 6 lines to retrieve all of the file's properties.

We use the BMP class to read black and white .BMP files containing signatures. We pass the GetImage results through a subroutine that converts the image into something that can be printed by a Hewlett Packard laser jet as part of a process that creates signed checks from blank check stock. To see sample use of BMP (including the HP subroutine) and its full interface definition, scroll down.
Download me at once!

Here is an example of how you might use BMP in one of your programs. We use this code to put signatures on checks. This subroutine uses the BMP object to read all the pertinent information about a .BMP file that contains a signature.

The most interesting item in this sample may be the function, MakeSignature, that is used near it's end. The MakeSignature function, which assumes that the image in the file is a simple black and white image, converts the image into a string that can be sent directly to a Hewlette Packard printer.

Since Windows does not like the escape character, you'll have to use the API provided via winspool.drv to step around it. The functions required are OpenPrinter, StartDocPrinter, StartPagePrinter, WritePrinter, EndPagePrinter, EndDocPrinter, and ClosePrinter. The last part of the sample set shows how this is done.
Sub LoadBMPfromFile(FName)
  Dim bmpobj as BMP                   'declare our BMP object
  Set bmpobj = New BMP                'initialize it
  bmpobj.FileName = FName             'supply the file name

  If bmpobj.ReadFile Then             'read BMP file
    ImgSz = bmpobj.Size               'get image size
    ReDim TheBytes(1 To ImgSz)        'adjust image receptacle size
    BytesPerRow = bmpobj.width        'get bytes in an image
    row Rows = bmpobj.Height          'get number of rows in image 
    Call bmpobj.GetImage(TheBytes)    'retrieve the image
    'generate printable form of image
    s = MakeSignatureString(ImgSz, Rows, BytesPerRow, TheBytes)  
  End If 
  Setbmpobj = Nothing                 'clean up memory 
End Sub
Function ResolutionCommand(width) As String 
'Returns an HP printer resolution command, based on width, 
'to cause the signiture to occupy approximately 2.5 inches.
  Dim i As Integer
  i = CInt(width / 2.5)

  If i < 100 Then
    i = 75
  ElseIf i < 150 Then
    i = 100
  ElseIf i < 200 Then
    i = 150
  ElseIf i < 300 Then
    i = 200
  ElseIf i < 600 Then
    i = 300
  Else
    i = 600
  End If
  ResolutionCommand = Chr$(27) + "*t" + Trim(str(i)) + "R"
End Function
Function MakeSignature(ImgSz, Rows, BytesInRow, TheBytes()) 
'Returns HP printer string
  Dim s     As String
  Dim row   As Integer
  Dim abyte As Integer
  Dim arow  As String
  Dim Esc   As String * 1
  Esc = Chr$(27)
  s = ResolutionCommand(BytesInRow * 8) 'set raster resolution
  s = s + Chr$(27) + "*r0F"            'set logical page orientation
  s = s + Chr$(27) + "*r1A"            'start at current cursor position

  For row = Rows To 1 Step -1
    arow = ""                          'init. the output string

    For abyte = 1 To BytesInRow - 2    'construct the output string
      arow = arow + Chr$(Not (TheBytes((row - 1) * BytesInRow + abyte)))
    Next                               'abyte
    'make it into a raster graphics command
    arow = Chr$(27) + "*b" + Trim(str(Len(arow))) + "W" + arow
    s = s + arow                       'output the row
  Next                                 'row
  s = s + Chr$(27) + "*rC"             'end graphics
  MakeSignatureString = s
End Function
Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" ( _
        ByVal pPrinterName As String, phPrn As Long, pDefault As Any) _
        As Long
Declare Function StartDocPrinter Lib "winspool.drv" Alias _
        "StartDocPrinterA" (ByVal hPrn As Long, ByVal Level As Long, _
        pDocInfo As DocInfo) As Long
Declare Function StartPagePrinter Lib "winspool.drv" (ByVal hPrn _
        As Long) As Long
Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrn As Long, _
        pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
Declare Function EndPagePrinter Lib "winspool.drv" (ByVal hPrn _
        As Long) As Long
Declare Function EndDocPrinter Lib "winspool.drv" (ByVal hPrn _
        As Long) As Long
Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrn _
        As Long) As Long

Type DocInfo
  pDocName    As String
  pOutputFile As String
  pDataType   As String
End Type
Type Defaults
  pDataType     As String
  pDevMode      As Long
  DesiredAccess As Long
End Type

Dim lhPrinter       As Long               'handle of printer
Dim PrintJobID      As Long
Dim ThePrinter      As String                 
Dim MyDocInfo       As DocInfo
Dim PrinterDefaults As Defaults
Dim lpcWritten      As Long
Dim Result          As Long
Dim lReturn         As Long

  PrinterDefaults.pDataType = "RAW" 'set up the printer
  PrinterDefaults.pDevMode = 0
  PrinterDefaults.DesiredAccess = 8 'PRINTER_ACCESS_USE
  ThePrinter = UCase$(Printers(0).DeviceName) 'get first printer name
  lReturn = OpenPrinter(ThePrinter, lhPrinter, PrinterDefaults) 
' get printer handle
  If lReturn = 0 Then
    MsgBox "Printer [" + ThePrinter + "] could not be found!", _
           vbCritical, "Ouch!"
    End 'give up
  End If
  MyDocInfo.pDocName = ProgramName 'set up the document
  MyDocInfo.pOutputFile = vbNullString
  MyDocInfo.pDataType = "RAW"
  PrintJobID = StartDocPrinter(lhPrinter, 1, MyDocInfo) 'start document
  Call StartPagePrinter(lhPrinter) 'start page
  Esc = Chr$(27)
  s = printer_setup_string 
  Result = WritePrinter(lhPrinter, ByVal s, Len(s), lpcWritten)
  s = Esc + "*p0100x0200Y" 'position on page
  Result = WritePrinter(lhPrinter, ByVal s, Len(s), lpcWritten)
  s = signaturestring 'write signature string
  Result = WritePrinter(lhPrinter, ByVal s, Len(s), lpcWritten)
  s = Esc + "E" 'clear printer
  Result = WritePrinter(lhPrinter, ByVal s, Len(s), lpcWritten)
  lReturn = EndPagePrinter(lhPrinter) 'end page
  lReturn = EndDocPrinter(lhPrinter) 'end document
  lReturn = ClosePrinter(lhPrinter) 'end Windows printer use

A .BMP file is composed of header records containing property information, a color table, and the image itself. The image is expressed as one byte per pixel where the content of the byte is a 1-based index into the color table for the color of the pixel. Below is the full interface definition for the BMP class.
Public Function ReadFile() As Boolean         'TRUE if successful
Public Property Let FileName(ByVal NewName As String) 'Sets the file name
Public Property Get Size() As Variant         'Get image size in bytes
Public Property Get Height() As Variant       'Get image height in rows
Public Property Get width() As Variant        'Get image width in bytes
Public Sub GetImage(Image())                  'Get image content
Public Property Get ColorsUsed() As Variant   'Get color cnt in ColorTable
Public Property Get ColorTable() As Variant   'Get color table for image
' The ColorTable is an array of RGBQuad items 
' such as "Dim CTab(ColorsUsed) as RGBQuad"
Type RGBQuad
  Blue  As Byte 'blue value for color map entry
  Green As Byte 'green value for color map entry
  Red   As Byte 'red value for color map entry
  Zero  As Byte '=0
End Type
This site designed by William D. Kandler (bkandler@verisof.com)
Updated: 5/1/02