HB++ Tutorial:  MyDelivery

 

Introduction

 

This continues the step-by-step tutorial for HB++.  This uses the Delivery sample found in your HB++\Samples directory. 

Preparation

 

Create the MyDelivery application

FrmMain

 

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 Conduit and Backend

 

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

jab@easystreet.com

 

Updated July 5, 2004