This continues the step-by-step tutorial for HB++. This uses the Delivery sample found in your HB++\Samples directory.
Start a new program with HB++.
· Create a new Minimal Project and save it with the following:
o Project Name: MyDelivery
o Project filename: <your path>\ MyDelivery directory. Example: C:\My Project\HB++\Tutorials\MyDelivery\MyDelivery.hbp
· Go to Project > Settings and for the Title of Debug and Release, make sure it says “MyDelivery”.
· Check to make sure that frmMain Caption is “MyDelivery”.
· Run the program. A blank form with a Title of MyDelivery should display on the Emulator.
We will now add the tables from the Delivery directory. In the Project window, right-click Tables > Add Files, navigate to the HB++\Samples\Delivery directory, and select TItem and TLocation. Then, select each file, do Save As… and save them in your MyDelivery directory. For each file, go to the Properties window and change Bundled to True and PDB to Create And Install Once. Note the table Structure and examine the Data. The tables are connected by LocationID.
Create a new Module called AppMain and copy and paste the following code. Not much happening here. A couple of global variables and the same InitScreenMode we saw in the MyAutograph sample.
'=========================================================================
'
Delivery Sample - Main
Module
'=========================================================================
'=========================================================================
'
PUBLIC MEMBERS
'=========================================================================
Public
lFrmMainLastFilter as Long
Public
lFrmMainLastRow as Long
Public
lFrmItemLastRow as Long
'=========================================================================
'
PUBLIC SUBS AND
FUNCTIONS
'=========================================================================
public sub InitScreenMode()
dim sc
as new ScreenMode
sc.FindFirstMode
While sc.BitDepth>8
sc.FindNextMode
Wend
Set ScreenMode=sc
End Sub
Copy and paste the following in clsApplication, overwriting the original code. No surprises so far.
'=========================================================================
' Delivery Sample - Main Class
'=========================================================================
Private Sub Application_NormalLaunch()
dim
fMain as new frmMain
Call
InitScreenMode
lFrmMainLastFilter = 1
lFrmMainLastRow=0
lFrmItemLastRow=0
fMain.Show
hbFormModeless+hbFormGoto
End Sub
Now we will copy all images from the Delivery directory to your new MyDelivery directory. Start by creating a new image family. Right-click on Image Families > Add Images….

For Image Family, type “Box” and press Next.

Select Insert and exiting file and press Next.

Navigate to your Delivery directory, select Box.bmp, and press Next

Select Return to step 2 and press Next.

Select Box16, change Palatte to 16 grey levels, and press Next.

Select Close this wizard and press Next to finish the process.
Now do the same with the other families, Validate, Locked, Delivery11 and Delivery22. This is a bit tedious, but you will end up with 5 families and 10 bmps.
Optional: You may want to select each bmp and then Save As… into your new MyDelivery directory.
Now we are going to take a real shortcut. Delete frmMain, and from the Project Menu (or from the Project window, or by pressing ctrl+D) select Add Files and add frmMain from the HB++\Samples\Delivery directory. We are assuming you know how to create controls by now, but in GridLocation, be sure to tap the Columns "…" to see what is happening. You will see a User draw type, which we will explain later.
Note that the following Menu has been added for you.
Select frmMain and go to File menu > Save frmMain As… and save this to your MyDelivery file, overwriting your original frmMain. (If you do not do this, you will change the HB++ Delivery sample.)
Delete all code in frmMain and add the following code. Compile to make sure there are no errors. The form will fill with data from the tables you included intially. Comments are in red. The code can be read from beginning to end and hopefully it will make sense.
''=========================================================================
' Delivery Sample - Location List Form
'=========================================================================
'=========================================================================
' PRIVATE MEMBERS
'=========================================================================
private mrsLocation as TLocation 'New Table
private mTimerAutoSelect as New Timer 'New Timer, used
to create delay
'=========================================================================
' FORM EVENTS
'=========================================================================
Private Sub Form_Load()
'PopupFilter
'There are only
three items, and they do not change,
'so the popup list is created each time by code when the form
opens.
PopupFilter.AddItem
"All company"
PopupFilter.AddItem
"To do list"
PopupFilter.AddItem
"Delivered"
'lFrmMainLastFilter is set to 1 as the application opens, so
the 2nd Item,
'which is "To Do List" is selected
PopupFilter.ListIndex
= lFrmMainLastFilter
Set
mrsLocation = Nothing 'Set the Table to
Nothing
Call RefreshGrid() 'Call the
RefreshGrid function
mTimerAutoSelect.Interval=200 'Set a 0.2 second
delay
mTimerAutoSelect.Enabled=True 'Start the Timer
end sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub Form_Unload()
mrsLocation.Close 'Close
the Recordset
Set
mrsLocation = Nothing 'Set it to Nothing
Set mTimerAutoSelect
= Nothing 'Set Timer to
Nothing
end sub
'=========================================================================
' POPUP FILTER EVENTS
'=========================================================================
Private Sub PopupFilter_Change() 'Occurs with each
change
lFrmMainLastFilter = PopupFilter.ListIndex 'Set the global variable
Call RefreshGrid() 'Refresh the Grid
mTimerAutoSelect.Enabled=True 'Set the Timer
with no delay
End Sub
'=========================================================================
' GRID EVENTS
' With three records, the events as the form opens occur in the
following order:
' RefreshGrid, RefreshGrid, RefreshGrid, Load, Load,
Load, Draw, Draw, Draw, Click
'=========================================================================
Private Sub GridLocation_DrawItem(ByVal iRow As Integer, ByVal
iCol As Integer, ByVal lItemData As Long, ByVal iLeft As Integer, ByVal iTop As
Integer, ByVal iWidth As Integer, ByVal iHeight As Integer)
'The DrawItem event is raised when a cell in a 'User Draw' column
has to be drawn.
'Cells are drawn one at a time, so this is initially called three
times.
'Public Event DrawItem(ByVal iRow As Integer, ByVal iCol As Integer,
'ByVal
lItemData As Long, ByVal iLeft As Integer, ByVal iTop As Integer,
'ByVal
iWidth As Integer, ByVal iHeight As Integer)
'Parameter
Description
'iRow: Row
index
'iCol: Column index
'lItemData: The value associated with the row.
'iLeft: Distance between the left edge of the form and the
left edge of the area to draw.
'iTop: Distance between the top edge of the form and the top
edge of the area to draw.
'iWidth: Width of the area to draw.
'iHeight: Height of the area to draw.
'The
LookupUniqueID method positions the cursor on a record,
'designated by its primary key UniqueID, within a database.
if mrsLocation.UniqueId <> lItemData then
mrsLocation.LookupUniqueID(lItemData)
'DELIVERED is a boolean field
in the table
If
mrsLocation.DELIVERED then
Me.CopyArea
iLeft,iTop,10,10,Validate,0,0 'Draw the Validate (checkmark) Image
Else
Me.CopyArea
iLeft,iTop,10,10,Box,0,0 'Draw the Box Image
End if
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub GridLocation_LoadItem(ByVal
iRow As Integer, ByVal lItemData As Long, ByVal vValue() As Variant)
'Called after GridLocation.Redraw=True
'Redraw --> LoadItem
--> DrawItem (if there is a
UserDraw column)
'This event is raised everytime the content of a row must be fetched
before being displayed.
'The iRow parameter represent the row index
that the Grid control needs to display.
'This parameter is in the range 0 to Rows -1.
if mrsLocation.UniqueId <> lItemData then
mrsLocation.LookupUniqueID(lItemData)
'Add text
values to the second column of the grid
vValue(1) = mrsLocation.COMPANY & " / " &
mrsLocation.CONTACT
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub GridLocation_Click(ByVal iRow As Integer, ByVal iCol
As Integer, ByVal lItemData As Long, ByVal bNote As Boolean)
'Called by mTimerAutoSelect_Timer()
Me.TxtCompany.Text
= ""
lFrmMainLastRow=iRow 'Save in global
variable
if mrsLocation.UniqueId <> lItemData then
mrsLocation.LookupUniqueID(lItemData)
'Fill the Field
if mrsLocation.DELIVERED then Me.TxtCompany.Text =
Me.TxtCompany.Text & "Delivered : " &
mrsLocation.DATEDELIV & Chr(10)
if
mrsLocation.COMPANY>"" then Me.TxtCompany.Text
= Me.TxtCompany.Text & mrsLocation.COMPANY & Chr(10)
if
mrsLocation.CONTACT>"" then Me.TxtCompany.Text
= Me.TxtCompany.Text & mrsLocation.CONTACT & Chr(10)
if
mrsLocation.PHONE>"" then Me.TxtCompany.Text
= Me.TxtCompany.Text & mrsLocation.PHONE & Chr(10)
if
mrsLocation.ADDRESS1>"" then Me.TxtCompany.Text
= Me.TxtCompany.Text & mrsLocation.ADDRESS1 & Chr(10)
if
mrsLocation.ADDRESS2>"" then Me.TxtCompany.Text
= Me.TxtCompany.Text & mrsLocation.ADDRESS2 & Chr(10)
'Show the
signature button if the DELIVERED column is True.
Me.BtSignature.Visible=mrsLocation.DELIVERED
End Sub
'=========================================================================
' PRIVATE SUBS AND FUNCTIONS
'=========================================================================
private sub RefreshGrid()
'Set the field to
""
Me.TxtCompany.Text
= ""
if Not
mrsLocation Is Nothing then 'If the TLocation
Table <> Nothing
mrsLocation.Close 'Close the
TLocation Table ??
else 'Else TLocation
Table = Nothing
Set
mrsLocation = New TLocation 'Create a new
TLocation Table
End if
GridLocation.Redraw=False 'Set redraw to
False to prevent flickering
GridLocation.Rows
= 0 'Set the number of
rows in the grid to 0
'Create a
Recordset
Select Case
PopupFilter.ListIndex 'Select the Case
from the PopupFilter
'
To do list
Case
1
mrsLocation.OpenRecordset
"DELIVERED = FALSE", hbModeOpenAlways+hbModeReadWrite
'
Delived
Case
2
mrsLocation.OpenRecordset
"DELIVERED = TRUE", hbModeOpenAlways+hbModeReadWrite
'
All company
Case
else 'include 0
mrsLocation.OpenTable hbModeOpenAlways+hbModeReadWrite
End select
'Scroll through
the Recordset, adding Items to the Grid
mrsLocation.MoveFirst
While Not mrsLocation.Eof
Call
Me.GridLocation.AddItem(mrsLocation.UniqueID)
mrsLocation.MoveNext
Wend
GridLocation.Redraw=True 'Redraw the grid
after fully loaded
'Not sure what
this section was all about... ??
'If
GridLocation.Rows>0 then
' call
GridLocation.Highlight(0,0)
' Call GridLocation.Highlight(0,1)
' Call GridLocation_Click(0,0,GridLocation.ItemData(0),False)
'End if
'Note that the
Recordset is still open.
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub mTimerAutoSelect_Timer() 'Starts after 0.2
second delay
mTimerAutoSelect.Enabled=False 'Turn off the Timer
If
GridLocation.Rows>0 then 'If at least one
row
If
Not ((0<=lFrmMainLastRow) and (lFrmMainLastRow<GridLocation.Rows)) then
lFrmMainLastRow = 0
'Select the row.
Call
Me.GridLocation.SelectItem(lFrmMainLastRow,1,True)
'Click the row.
Call
GridLocation_Click(lFrmMainLastRow,1,GridLocation.ItemData(lFrmMainLastRow),False)
End if
End Sub
Now we will add FrmInfo in a similar fashion. Right-click on Forms > Add Files…, navigate to your Delivery directory, and select FrmInfo. Save All and Compile the program. It may come as a surprise that if you now look in your MyDelivery directory, you will not see frmInfo. It is still in the original directory. To save it in your current directory, select frmInfo and then SaveAs… While you are at it
Examine all the controls in FrmInfo. No surprises. Try creating another control similar to PicLocked so you can see how this is done, then delete your extra control.
Add FrmList and FrmSignature the same way, remembering to do the SaveAs… into the correct folder for each form. Examine the controls, and again no surprises. In FrmSignature, we see a ucDraw control, also seen in the the Autograph sample.
Add the User Control ucDraw.hbu and SaveAs…
Append the following code to FrmMain. We will add codes for the menu items and for the ItemList button.
'=========================================================================
' Location MENU EVENTS
'=========================================================================
'MenuItem jumps to FrmInfo, creating a new record.
Private Sub MnuLocationAdd_Click()
Dim fInfo as
FrmInfo
'Create a new form
Set fInfo =
New FrmInfo
'Set the ID to 0
(key step)
fInfo.UniqueId
= 0
'Show the newly
created form.
fInfo.Show hbFormModeless+hbFormGoto
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'MenuItem jumps to FrmInfo, displaying the selected record.
Private Sub MnuLocationEdit_Click()
Dim fInfo as
FrmInfo
'Exit if no Row
selected.
If
Me.GridLocation.Row = -1 then exit sub
'Verify that
selected item is the selected record of recordset.
if mrsLocation.UniqueId <>
Me.GridLocation.ItemData(Me.GridLocation.Row) then
mrsLocation.LookupUniqueID(Me.GridLocation.ItemData(Me.GridLocation.Row))
'Create new form.
Set fInfo = New
FrmInfo
'Fill the
information for each control from selected record (key step).
fInfo.TxtContact.Text =
mrsLocation.CONTACT
fInfo.TxtCompany.Text =
mrsLocation.COMPANY
fInfo.TxtAddress1.Text =
mrsLocation.ADDRESS1
fInfo.TxtAddress2.Text =
mrsLocation.ADDRESS2
fInfo.TxtPhone.Text
= mrsLocation.PHONE
fInfo.UniqueId
= mrsLocation.UniqueId
fInfo.PicLocked.Visible=mrsLocation.DELIVERED
fInfo.LblLocked.Visible=mrsLocation.DELIVERED
fInfo.BtOk.Visible=Not
mrsLocation.DELIVERED
'Show the newly
created form
fInfo.Show hbFormModeless+hbFormGoto
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'MenuItem deletes selected record.
Private Sub MnuLocationDelete_Click()
Dim rsItem as
TItem
If mrsLocation.DELIVERED then
MsgBox
"Cannot delete an element when the delivery was carried out"
Else
'Straightforward
syntax.
If
MsgBox("Realy want to delete item
?",hbMsgBoxConfirmation+hbMsgBoxYesNo,"Delete")=hbMsgBoxYes then
'error message
'delete related records
While
Not rsItem.Eof
rsItem.Delete hbRecordRemove
rsItem.MoveNext
Wend
rsItem.Close
'delete current record
mrsLocation.Delete hbRecordRemove
Call
RefreshGrid
mTimerAutoSelect.Enabled=True
End
if
End if
End sub
'=========================================================================
' BUTTONS EVENTS
'=========================================================================
'Button "Item List" This shows FrmList, displaying the
information in
'the associated records.
Private Sub BtItemList_Click()
Dim fList as
FrmList
'If Row is not
selected, exit the Sub
If
Me.GridLocation.Row = -1 then exit sub
if mrsLocation.UniqueId <>
Me.GridLocation.ItemData(Me.GridLocation.Row) then
mrsLocation.LookupUniqueID(Me.GridLocation.ItemData(Me.GridLocation.Row))
'Create a new
FrmList
Set fList =
New FrmList
'LocationId is a
variable delared in FrmList
fList.LocationId
= mrsLocation.UniqueId
'Set the
properties of the control before jumping to the form
'Save button is
visible if item is not delivered
fList.BtSaveItem.Visible=Not
mrsLocation.Delivered
'Picture and label
are visible if item is delivered
fList.PicLocked.Visible=mrsLocation.Delivered
fList.LblLocked.Visible=mrsLocation.Delivered
fList.Delivered
= mrsLocation.Delivered
fList.Show hbFormModeless+hbFormGoto
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub BtSignature_Click()
Dim fForm as
FrmSignature
Set fForm =
New FrmSignature
'LocationId is a
variable delared in FrmSignature
fForm.LocationId
= mrsLocation.UniqueId
fForm.Show hbFormModeless+hbFormGoto
End Sub
Compile and Run the app. We are now done with FrmMain and the application is fully functional. Now examine the code for the rest of the Forms, which should be self-explanatory. Note that the code for ucDraw is taken from the Autograph sample.
The Samples Help section tells us the following:
Conduits
This sample
is provided with two conduit definition files, from which you can generate
conduits. These files are located in the same directory as the HB++ project:
Desktop application
Three
examples of desktop application are provided. They share the same interface and
behaviour:
However, they
differ in the language in which they were developed, and in the data access
methods they make use of.
However, there are still some things you need to do to get this to function. Let’s work with the VB_MsDAO application, assuming that you have VB 6.0. Copy and paste VB_MsDAO from the Delivery sample into your MyDelivery directory.
With VB6, open VBDAODelivery.vbp. In FrmMain,
Private Sub
Form_Load()
Set gDataBase = OpenDatabase(App.Path
& "\Delivery.MDB")
Change “Delivery” to “MyDelivery”. Go to File > Make VBDAODelivery.exe. Copy and paste VBDAODelivery.exe into the MyDelivery directory.
In HB++, run the Conduit Generator, as noted below. If you have a prior conduit which uses ZZZZ, then delete it first using the Conduit Installer.


For the Data Source, you will want to specify the same directory as the VB app. On my computer it is as follows:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\My Project\HB++\Tutorials\MyDelivery\MyDelivery.mdb;
For the Path to linked files, use a similar path (for the TLocation table only). On my computer it is as follows:
C:\My Project\HB++\Tutorials\MyDelivery
The Sync options for
the SIGNATURE field are defined to external file. Then, when you add a
Synchronize action in the conduit generator, you can specify a path for the
'linked files': it's the last field in the 'Synchronize table' dialog of the
conduit generator (step 3/3). This path
can contain special tags. See also Home > Tools User's Guide > Conduits
>Appendices >Tags in the help file.
In the DeliverySimple.hbh sample file, this path is set to "C:\Program
Files\HB++\Samples\Delivery". If this path is not specified, C:\ is the
default path.
Run the Conduit Installer and HotSync. This will create the MyDelivery.mdb in the appropriate directory.
Run \MyDelivery\VBDAODelivery.exe. You may need to tap on the second record and then tap the first record for the signature to become visible.

Make a few changes on the Palm and PC. HotSync and you can see that the changes have been synchonized on both applications. The VB app is a bit buggy, but it demonstates the functionality.
You are done.
If you find any errors in this tutorial or if you have suggestions for improvement, please drop me a note.
Jon Blackman
Updated July 5, 2004