Using ODBC to Access Image Data (Delphi 4)
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 Delphi, a simpler alternative is to use the LEAD control as a data-aware 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 http://www.leadtools.com/odbc32.htm. 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. |
|
|
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. |
|
|
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 LEADRasterView 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 LEADRasterView 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 LeadRasterView1. |
12. |
Add the LEAD RasterProcess Object Library to your project. |
|
|
On the Project pull-down menu, use the References option, and select the LEAD RasterProcess Object Library (14.5). |
|
13. |
Add the LEAD RasterIO Object Library to your project. |
|
|
On the Project pull-down menu, use the References option, and select the LEAD RasterIO Object Library (14.5). |
|
14. |
Add the LEAD Raster ODBC Object Library to your project. |
|
|
On the Project pull-down menu, use the References option, and select the LEAD Raster ODBC Object Library (14.5). |
|
15. |
Add the LEAD Raster Annotation ODBC Object Library to your project. |
|
|
On the Project pull-down menu, use the References option, and select the LEAD Raster Annotation Object Library (14.5). |
|
16. |
Add the following code to the general declarations section of your project. |
Public RasterIO As LEADRasterIO
Public RasterProc As LEADRasterProcess
Public WithEvents As LeadRasODBC As LEADRasterODBC
Public RasAnn As LEADRasterAnnotation
17. |
Add the following code to the end of the Form_Load event handler. |
'Create the RasterIO Object
Set RasterIO = CreateObject("LEADRasterIO.LEADRasterIO.145 ")
'Create the RasterProcess Object
Set RasterProc = CreateObject("LEADRasterProcess.LEADRasterProcess.145 ")
'Create the RasterODBC Object
Set LeadRasODBC = CreateObject("LEADRasterODBC.LEADRasterODBC.145 ")
'Create the RasAnn Object
Set RasAnn = CreateObject("LEADRasterAnnotation. LEADRasterAnnotation.145")
18. |
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. |
19. |
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. |
20. |
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
21. |
Add the following code to the form's Load procedure. |
LeadRasODBC.EnableMethodErrors = FALSE
On Error GoTo ERRORHANDLER
' Turn off automatic scrolling and repainting
LeadRasterView1.AutoScroll = False
LeadRasterView1.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"
LeadRasODBC.dbOpen DString, SelString, "photo", DB_OPENOPTIONS_NONE
' Set the LEAD control's database properties
LeadRasODBC.dbLoadBits = 24
LeadRasODBC.dbLockingMode = DB_LOCKINGMODE_OPTIMISTIC
' Enable use of the dbMove method in the data control's Reposition event
If (LeadRasODBC.dbIsBOF And LeadRasODBC.dbIsEOF) = False Then
NormalMove = True
End If
Exit Sub
ERRORHANDLER:
MsgBox Err.Source + " " + CStr(Err.Number) + Chr(13) + Err.Description
22. |
Add the following code to the form's Unload procedure. |
LeadRasODBC.dbClose
23. |
Add a CommonDialog control to your form. |
24. |
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
LeadRasterView1.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 RasterODBC object's recordset and make sure it is
' synchronized with the data control.
LeadRasODBC.dbRequery
NormalMove = True ' Do normal record synchronization
Dpeople.Recordset.MoveLast
If LeadRasODBC.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 + "'"
LeadRasterView1.Visible = True
' Load the image file and update the recordset
LeadRasODBC.dbEdit
RasterIO.Load LeadRasterView1.Raster, Myfile, 0, 0, 1
LeadRasODBC.Raster = LeadRasterView1.Raster
' Update the recordset using the appropriate format
If LeadRasterView1.Raster.BitmapBits = 1 Then
LeadRasODBC.dbUpdate FILE_LEAD1BIT, 1, 0
ElseIf LeadRasterView1.Raster.BitmapBits = 4 Then
LeadRasODBC.dbUpdate FILE_PCX, 4, 0
ElseIf LeadRasterView1.Raster.IsGrayscale = GRAY_NO Then
LeadRasODBC.dbUpdate FILE_CMP, 24, QFACTOR_QMS
Else 'save as grayscales
LeadRasODBC.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
25. |
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 ODBC control.
NormalMove = False
LeadRasterView1.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
LeadRasODBC.dbRequery
Dpeople.Recordset.MoveLast
NewPosition = Dpeople.Recordset.AbsolutePosition
LeadRasODBC.dbMove NewPosition
' Make sure the LEADODBC control is on the last record.
LeadRasODBC.dbMoveNext
If LeadRasODBC.dbIsEOF Then
LeadRasODBC.dbMovePrev
Else
MsgBox "Synchronization error!" + Chr(13) + "Restart the application"
Exit Sub
End If
' Return to the old record position, if possible.
NormalMove = True
LeadRasterView1.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
26. |
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
RasterProc.Flip LeadRasterView1.Raster
LeadRasODBC.dbEdit
' Update the recordset using the appropriate format
If LeadRasterView1.Raster.BitmapBits = 1 Then
LeadRasODBC.dbUpdate FILE_LEAD1BIT, 1, 0
ElseIf LeadRasterView1.Raster.BitmapBits = 4 Then
LeadRasODBC.dbUpdate FILE_PCX, 4, 0
ElseIf LeadRasterView1.Raster.IsGrayscale = GRAY_NO Then
LeadRasODBC.dbUpdate FILE_CMP, 24, QFACTOR_QMS
Else 'save as grayscale
LeadRasODBC.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
27. |
Add the following code to the LEADRasterODBC control's ODBCChange event: |
' Avoid processing events that occur before the bitmap is fully loaded
If LeadRasterView1.Raster.Bitmap = 0 Then
LeadRasterView1.ForceRepaint
Exit Sub
End If
RasAnn.LEADRaster = LeadRasODBC.Raster
LeadRasODBC.AnnContainer = 0
LeadRasODBC.AnnContainer = RasAnn.AnnContainer
' Calculate the display rectangle to fit the image inside the control
HeightAllowed = LeadRasterView1.ScaleHeight
WidthAllowed = LeadRasterView1.ScaleWidth
If (HeightAllowed * LeadRasterView1.Raster.BitmapWidth / LeadRasterView1.Raster.BitmapHeight) <= WidthAllowed Then
DisplayTop = 0
DisplayHeight = HeightAllowed
DisplayWidth = DisplayHeight * LeadRasterView1.Raster.BitmapWidth / LeadRasterView1.Raster.BitmapHeight
DisplayLeft = (LeadRasterView1.ScaleWidth - DisplayWidth) / 2
Else
DisplayLeft = 0
DisplayWidth = WidthAllowed
DisplayHeight = DisplayWidth * LeadRasterView1.Raster.BitmapHeight / LeadRasterView1.Raster.BitmapWidth
DisplayTop = (LeadRasterView1.ScaleHeight - DisplayHeight) / 2
End If
'Set the image display size
LeadRasterView1.SetDstRect DisplayLeft, DisplayTop, DisplayWidth, DisplayHeight
LeadRasterView1.SetDstClipRect DisplayLeft, DisplayTop, DisplayWidth, DisplayHeight
LeadRasterView1.ForceRepaint
28. |
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
29. |
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
LeadRasODBC.dbMove NewPosition - OldPosition
End If
30. |
Run your program to test it. |