Available in the LEADTOOLS Imaging toolkit. |
Using ODBC to Access Image Data (Visual Basic)
This lesson describes how to use the LEADTOOLS ODBC features to maintain images in a table with other data. In this lesson, you accomplish the following:
Create a database with one table containing images and names for the images.
Create an ODBC data source that references the table.
Use a data control to manage the table and to access the names.
Use the LEADTOOLS methods to access the images through the ODBC data source.
Use SQL SELECT statements to maintain a sorted view of the records.
Synchronize the record pointers so that the two views of the same table are always correct.
Note: In Visual Basic, a simpler alternative is to use the LEAD control as a data-aware control. Refer to Implementing a Database with a Data Control.
Note: The LEADTOOLS ActiveX requires ODBC drivers that can properly handle long binary fields. Examples have been tested and will work with version 3.0 of the Microsoft ODBC Desktop Driver Pack. (This driver pack ships with Access 95 and works on 32-bit systems.) You can download drivers from the LEAD BBS, the CompuServe forum, or the Worldwide Web home page. The CompuServe forum is at GO LEADTECH. The web page is ftp://ftp.leadtools.com/pub/utils/ODBC32.zip. The file to download is ODBC32.ZIP.
1. Start Visual Basic.
2. On the Add Ins menu, select the Data Manager option (Visual Data Manager in VB5).
3. Create a new database.
For VB4: On the Select File menu, select the New Database option.
For VB5: On the File menu, select New Database, and specify Microsoft Access 7.
4. Specify a file name of leadpic.mdb and click the Save button.
5. Add a table.
For VB4: Click the New button.
For VB5: Use the right mouse button, and select the New Table menu option.
6. In the Add Table window, specify a table named: people, with the following two fields:
a. Field name: who. Data Type: text. Size: 255
b. Field name: photo. Data Type: Long Binary (or Binary). Size: N/A.
7. Close the Database Manager.
8. Add a data control to the bottom of your form and change its properties as follows:
a. Set the DatabaseName property to leadpic.mdb. (Use the browser to get the full path name.)
b. Set the RecordSource property to the following:
SELECT who FROM people ORDER BY who
c. Set the Name property to Dpeople.
9. On the Tools pull-down menu, use the Custom Controls option to add the LEAD OLE Custom Control module to your project.
10. Select the LEAD Main ActiveX control; then add the control to your main form. Stretch and position the control as you want it to appear at run time.
11. In the Properties box for the LEAD control, make the following changes:
a. Set the BorderStyle property to 1. This adds a 1-pixel border to the control.
b. Set the Name property to Lead1.
12. Add a TextBox control to your form and change its properties as follows:
a. Set the DataSource property to Dpeople.
b. Set the DataField property to who.
c. Set the Name property to Cwho.
13. From the Windows Control Panel, create the ODBC data source as follows:
a. Open the ODBC administrator and click the Add button.
b. Select Microsoft Access driver and click the OK button.
c. Enter the name LEADODBC.
d. Click the Select directory button and select the path to the database that you created.
e. Click the OK button; click the next OK button; then click the Close button.
14. In Visual Basic, add the following code to your form's general declarations. In online help, you can use the Edit pull-down menu to copy the block of code.
' The Windows Sleep function lets us synchronize requeries on adds and deletes
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
' These are variables for implementing the dbMove method
Public OldPosition, NewPosition As Long
' This variable lets us make the dbMove method conditional
Public NormalMove As Boolean
15. Add the following code to the form's Load procedure.
On Error GoTo ERRORHANDLER
' Turn off automatic scrolling and repainting
Lead1.AutoScroll = False
Lead1.AutoRepaint = False
' Open the database.
' Use the same SELECT statement that is used for the data control.
' Note that the image field must be listed first in the SELECT statement.
DString = "ODBC;DSN=LEADODBC"
SelString = "SELECT photo,* FROM people ORDER BY who"
Lead1.dbOpen DString, SelString, "photo", DB_OPENOPTIONS_NONE
' Set the LEAD control's database properties
Lead1.dbLoadBits = 24
Lead1.dbLockingMode = DB_LOCKINGMODE_OPTIMISTIC
' Enable use of the dbMove method in the data control's Reposition event
If (Lead1.dbIsBOF And Lead1.dbIsEOF) = False Then
NormalMove = True
End If
Exit Sub
ERRORHANDLER:
MsgBox Err.Source + " " + CStr(Err.Number) + Chr(13) + Err.Description
16. Add the following code to the form's Unload procedure.
Lead1.dbClose
17. Add a CommonDialog control to your form.
18. Add a CommandButton control to your form, change its Caption property to Add Photo, and add the following code to its Click event:
On Error GoTo ERRORHANDLER
' Get an image file
' This filter list is complete, except for GIF.
CommonDialog1.Filter = "Grapics|*.cmp; *.jpg; *.jff; *.jtf; *.bmp; *.tif; *.tga; *.pcx; *.cal; *.mac; *.mac; *.img; *.msp; *.wpg; *.wpg; *.ras; *.pct; *.pcd; *.eps; *.wmf"
CommonDialog1.Flags = cdlOFNFileMustExist
CommonDialog1.DialogTitle = "Open File"
CommonDialog1.CancelError = True
CommonDialog1.ShowOpen
Myfile = CommonDialog1.filename
' Suspend use of the dbMove method in the data control's Reposition event
NormalMove = False
'Set the pointer to an hourglass
Screen.MousePointer = 11
' Hide the LEAD control to avoid unnecessary repaints
Lead1.Visible = False
' Add and update the record, without inserting the image
Dpeople.Recordset.AddNew
Cwho = Myfile
Dpeople.Recordset.Update
' Wait for the update to take effect
Call Sleep(5000)
' Requery the data control's recordset
Dpeople.Recordset.Requery
' Requery the LEAD control's recordset and make sure it is
' synchronized with the data control.
Lead1.dbRequery
NormalMove = True ' Do normal record synchronization
Dpeople.Recordset.MoveLast
If Lead1.dbCurrentRecord <> Dpeople.Recordset.AbsolutePosition Then
MsgBox "Synchronization error!" + Chr(13) + "Delete the record and exit"
Dpeople.Recordset.FindFirst "who = " + "'" + Myfile + "'"
Screen.MousePointer = 0
Exit Sub
End If
' Go to the new record, and show the LEAD control
Dpeople.Recordset.FindFirst "who = " + "'" + Myfile + "'"
Lead1.Visible = True
' Load the image file and update the recordset
Lead1.dbEdit
Lead1.Load Myfile, 0, 0, 1
' Update the recordset using the appropriate format
If Lead1.BitmapBits = 1 Then
Lead1.dbUpdate FILE_LEAD1BIT, 1, 0
ElseIf Lead1.BitmapBits = 4 Then
Lead1.dbUpdate FILE_PCX, 4, 0
ElseIf Lead1.IsGrayscale = GRAY_NO Then
Lead1.dbUpdate FILE_CMP, 24, QFACTOR_QMS
Else 'save as grayscale
Lead1.dbUpdate FILE_CMP, 8, QFACTOR_QMS
End If
'Set the mouse pointer back to the default
Screen.MousePointer = 0
Exit Sub
ERRORHANDLER:
'Set the mouse pointer back to the default
Screen.MousePointer = 0
If Dpeople.Recordset.EditMode = dbEditAdd Then
Dpeople.Recordset.CancelUpdate
End If
MsgBox Err.Source + " " + CStr(Err.Number) + Chr(13) + Err.Description
19. Add another CommandButton control to your form, change its Caption property to Delete Photo, and add the following code to its Click event:
On Error GoTo ERRORHANDLER
' Disable the normal record synchronization and hide the LEAD control.
NormalMove = False
Lead1.Visible = False
'Set the pointer to an hourglass
Screen.MousePointer = 11
' Save the current position
RecMarker = Dpeople.Recordset.AbsolutePosition
' Delete the record and wait for the deletion to take effect
Dpeople.Recordset.Delete
Call Sleep(5000)
' Requery the recordsets, move to the last record,
' and initialize the NewPosition global variable.
Dpeople.Recordset.Requery
Lead1.dbRequery
Dpeople.Recordset.MoveLast
NewPosition = Dpeople.Recordset.AbsolutePosition
Lead1.dbMove NewPosition
' Make sure the LEAD control is on the last record.
Lead1.dbMoveNext
If Lead1.dbIsEOF Then
Lead1.dbMovePrev
Else
MsgBox "Synchronization error!" + Chr(13) + "Restart the application"
Exit Sub
End If
' Return to the old record position, if possible.
NormalMove = True
Lead1.Visible = True
RelativePosition = RecMarker - NewPosition
If RelativePosition < 0 Then
Dpeople.Recordset.Move RelativePosition
End If
'Set the mouse pointer back to the default
Screen.MousePointer = 0
Exit Sub
ERRORHANDLER:
'Set the mouse pointer back to the default
Screen.MousePointer = 0
MsgBox Err.Source + " " + CStr(Err.Number) + Chr(13) + Err.Description
20. Add another CommandButton control to your form, change its Caption property to Flip Photo, and add the following code to its Click event:
On Error GoTo ERRORHANDLER
' Flip the image and update the record
Lead1.Flip
Lead1.dbEdit
' Update the recordset using the appropriate format
If Lead1.BitmapBits = 1 Then
Lead1.dbUpdate FILE_LEAD1BIT, 1, 0
ElseIf Lead1.BitmapBits = 4 Then
Lead1.dbUpdate FILE_PCX, 4, 0
ElseIf Lead1.IsGrayscale = GRAY_NO Then
Lead1.dbUpdate FILE_CMP, 24, QFACTOR_QMS
Else 'save as grayscale
Lead1.dbUpdate FILE_CMP, 8, QFACTOR_QMS
End If
Exit Sub
ERRORHANDLER:
If Dpeople.Recordset.EditMode = dbEditInProgress Then
Dpeople.Recordset.CancelUpdate
End If
MsgBox Err.Source + " " + CStr(Err.Number) + Chr(13) + Err.Description
21. Add the following code to the Lead1 control's Change event:
' Avoid processing events that occur before the bitmap is fully loaded
If Lead1.Bitmap = 0 Then Exit Sub
' Calculate the display rectangle to fit the image inside the control
HeightAllowed = Lead1.ScaleHeight
WidthAllowed = Lead1.ScaleWidth
If (HeightAllowed * Lead1.BitmapWidth / Lead1.BitmapHeight) <= WidthAllowed Then
DisplayTop = 0
DisplayHeight = HeightAllowed
DisplayWidth = DisplayHeight * Lead1.BitmapWidth / Lead1.BitmapHeight
DisplayLeft = (Lead1.ScaleWidth - DisplayWidth) / 2
Else
DisplayLeft = 0
DisplayWidth = WidthAllowed
DisplayHeight = DisplayWidth * Lead1.BitmapHeight / Lead1.BitmapWidth
DisplayTop = (Lead1.ScaleHeight - DisplayHeight) / 2
End If
'Set the image display size
Lead1.SetDstRect DisplayLeft, DisplayTop, DisplayWidth, DisplayHeight
Lead1.SetDstClipRect DisplayLeft, DisplayTop, DisplayWidth, DisplayHeight
Lead1.ForceRepaint
22. Add the following code to the Dpeople control's Validate event:
' Set the OldPosition, which is used in a calculation in the Reposition event
OldPosition = Dpeople.Recordset.AbsolutePosition
23. Add the following code to the Dpeople control's Reposition event:
' Use the dbMove method to move the LEAD control to the current record
If NormalMove Then
' The current position is the NewPosition
' The OldPosition is set in the Validate event
NewPosition = Dpeople.Recordset.AbsolutePosition
Lead1.dbMove NewPosition - OldPosition
End If
24. Run your program to test it.