Chapter 34

Building the FaxBack Application


CONTENTS


Introduction

In this chapter you'll build a Visual Basic 4.0 project that combines TAPI and MAPI services to create a dial-up FAX server. With this application running on a workstation, users could dial into the workstation, receive prompts for entering their own FAX telephone number, and select a document number. Then, when the user hangs up, the workstation will format and send the selected FAX document to the user's FAX address.

This example application will be a bit Spartan in construction. The caller prompts are simple and the error handling is very basic. This was done to focus on the details of putting together the larger pieces of the project. If you plan to implement a production version of this program, you'll need to spend a bit more time polishing it up. However, when you are done with this project, you'll have a working FAX server that you can install on any 32-bit Windows workstation.

Note
The evaluation version of VBVoice is not fully functional. You'll be able to complete a demonstration version of the project, but you will not be able to install a production version unless you purchase a licensed copy of VBVoice.

Project Resources

The VBVoice controls answer the incoming call and prompt the caller to enter a FAX number and the selected document number. Once this is done, the VBVoice controls turn the collected data over to the MAPI system for delivery of the selected FAX.

The following resources must be available on your workstation in order to build and run the FaxBack project:

The next few sections go into a bit more detail on the VBVoice controls and how they are used. You'll also get a quick review of the SMAPI interface and the support files you'll need to load in order to complete this project.

The VBVoice Controls

To gain access to the TAPI services, you'll use an evaluation version of the VBVoice control set from Pronexus, Inc. An evaluation version of the controls can be found on the CD-ROM that ships with this book. With this evaluation set, you'll be able to build and compile your Visual Basic 4.0 application and run it in test mode using your sound card and speakers.

Note
The VBVoice controls were briefly reviewed in Chapter 31, "Third-Party TAPI Tools." Refer to that chapter for more information on the VBVoice controls and how they are used to build telephony applications.

If you haven't already done so, install the evaluation copy of VBVoice32 from the CD-ROM that ships with this book.

Warning
If you already own a working copy of VBVoice do not install the evaluation version because this may trash your working copy.

When you install VBVoice, you'll have a rich set of controls available for creating telephony applications. Be sure to add these controls to your FaxBack project before you begin coding (select Tools | Custom Controls).

The FAX.VAP Voice Prompt File

The FaxBack project is based on a FAX demonstration project available from the Pronexus FTP site (ftp.pronexus.com). The demonstration program includes a voice prompt file (VAP) that has all the basic prompts you need to complete this project. Instead of going through the process of recording your own prompts for the FaxBack example, you'll use the FAX.VAP file that is provided by Pronexus. You'll find this on the CD-ROM that comes with this book, too.

Note
For those who are curious, the voice you'll hear in the VAP file is not mine (sorry!).

If you plan on putting a version of this application into production, you'll want to use the Pronexus voice recording tools to create your own set of prompts.

The SMAPI Support Modules

In this project you'll use the SMAPI interface to provide access to the message services of Windows. The SMAPI interface was chosen because it has a very small "footprint" in your project. While the MAPI.OCX controls and the OLE Messaging library would also work fine, the SMAPI provides all the MAPI access that is needed for this project.

Tip
The SMAPI interface was covered in depth in Chapter 6, "Creating MAPI-Aware Applications." You can refer to that chapter for more information on the SMAPI interface and how it works.

There are two support modules that you can add to your Visual Basic project to provide access to the SMAPI level of messaging services.

Note
All four files discussed here were covered in greater detail in Chapter 6, "Creating MAPI-Aware Applications." Refer to that chapter for more information on SMAPI services.

When you begin this project, you can add these BAS files (select File | Add Files) instead of typing them in again.

Starting the FaxBack Project

So, here's a quick review-you'll need the following resources for this project:

Once you've assembled all these resources, you're ready to start your project. Start Visual Basic 4.0 and add the VBVoice controls to your toolbox (select Tools | Custom Controls). Next add the two SMAPI support files (MAPIERR.BAS and VBAMAP32.BAS) to your project (select Files | Add Files). It's a good idea to copy the support files to the sample directory that you'll be using to build the FaxBack project.

At this point your Visual Basic 4.0 design-mode environment should look something like the one in Figure 34.1.

Figure 34.1 : Visual Basic design-mode environment for the FaxBack project.

Notice the VBVoice controls in the toolbox and the two SMAPI support files in the project window. Now you're ready to start coding!

Coding the FaxBack Support Module

The FaxBack support module has five routines and several project-level variables. Add a new module to the project (Insert | Module) and set its Name property to modFaxBack. Save the empty module as FAXBACK.BAS.

Now add the project-level variables. These will be used throughout the application. Listing 34.1 shows the code that you should place in the general declaration section of the module.


Listing 34.1. Adding the project-level variables.
Option Explicit
'
' fax variables
Public cFAXPrefix As String ' file prefix
Public cFAXSuffix As String ' file tail
Public cTestFAXAddr As String ' local FAX machine
Public cFAXFolder As String ' document folder
'
' SMAPI variables
Public lReturn As Long ' return flag
Public lSession As Long ' session handle
Public udtMessage As MapiMessage ' message object
Public udtRecip As MapiRecip ' recipient object
Public udtRecips() As MapiRecip ' recipient collection
Public udtFile As MapiFile ' attachment object
Public udtFiles() As MapiFile ' attachment collection

You can see there are two sets of variables. The first set will be used to keep track of FAX related values. The second set of variables will be used to handle MAPI service requests.

The next routine you'll add to the project is a function to verify the existence of a file. Add a new function called FileExists to your project (Insert | Procedure | Function), then add the code shown in Listing 34.2.


Listing 34.2. Adding the FileExists function to the module.
Public Function FileExists(cFile As String) As Integer
    '
    ' return TRUE if found, FALSE if not
    '
    Dim x  As Integer
    x = FreeFile
    '
    On Error Resume Next
    Open cFile For Input As x
    If Err = 0 Then
        FileExists = True
    Else
        FileExists = False
    End If
    Close x
    '
End Function

This routine attempts to open a filename passed into the function. If the open is successful, the routine returns TRUE. If the open fails, it is assumed the file does not exist and the routine returns FALSE.

Now add a new subroutine called CenterForm. This will be used to center forms on the display. Listing 34.3 has the code you need to fill out this routine.


Listing 34.3. Adding the CenterForm routine.
Public Sub CenterForm(frm As Form)
    '
    ' place form in center of display
    '
    frm.Left = (Screen.Width - frm.Width) / 2
    frm.Top = (Screen.Height - frm.Height) / 2
    '
End Sub

The next two routines handle logging in and out of MAPI services. The first routine (SMAPIStart) initializes the workstation for MAPI services. Add the code shown in Listing 34.4 to your project.


Listing 34.4. Adding the SMAPIStart routine.
Public Sub SMAPIStart(lhWnd As Long, cLogID As String)
    '
    ' start an SMAPI session
    '
    lReturn = MAPILogon(lhWnd, cLogID, "", MAPI_LOGON_UI And MAPI_NEW_SESSION, 0, ÂlSession)
    If lReturn <> SUccESS_SUccESS Then
        MsgBox MAPIErr(lReturn)
        End
    End If
    '
End Sub

The SMAPIStart routine attempts to log in with the profile name passed into the routine. If the profile name is invalid, a dialog box will appear to prompt you for a valid logon ID. The logon will result in a new MAPI session for this workstation. This way, any other open MAPI session you have on your station will not be affected by the FaxBack application.

Now add the SMAPIEnd routine to your project and enter the code from Listing 34.5.


Listing 34.5. Adding the SMAPIEnd routine.
Public Sub SMAPIEnd(lhWnd As Long)
    '
    ' end an SMAPI session
    '
    lReturn = MAPILogoff(lSession, lhWnd, 0, 0)
    '
End Sub

This routine simply logs off the current active MAPI session. You'll call this at the end of your program.

The only other support routine left is the routine that will actually compose and send the FAX by way of MAPI services. Add a new subroutine called SendSMAPIFax to the module and enter the code from listing 34.6.


Listing 34.6. Adding the SendSMAPIFax routine.
Public Sub SendSMAPIFax(lhWnd As Long, cFile As String, cRecipient As String)
    '
    ' queue up an smapi fax message
    '

    '
    ' get simple file name
    Dim cName As String
    cName = Mid(cFile, Len(cFAXFolder) + 2, 255)
    '
    ' make message
    udtMessage.Subject = "Requested FAX From FaxBack(tm)"
    udtMessage.NoteText = "Here's the FAX document you requested from FaxBack(tm)." Â& Chr(13) & Chr(13) & " #"
    '
    ' make attachment
    ReDim udtFiles(1)
    udtFiles(0).Position = Len(udtMessage.NoteText) - 1
    udtFiles(0).PathName = cFile
    udtFiles(0).FileName = cName
    udtFiles(0).FileType = 0
    '
    ' make recipient
    udtRecip.Reserved = 0
    udtRecip.RecipClass = 1
    udtRecip.Name = "FAX:FaxBack_Request@" & cRecipient
    udtRecip.Address = "FAX:FAXBack_Request@" & cRecipient
    udtRecip.EIDSize = 100
    udtRecip.EntryID = ""
    '
    ' update message
    udtMessage.RecipCount = 1
    udtMessage.FileCount = 1
    '
    ' now call sendmail w/o dialog
    lReturn = MAPISendMail(lSession, lhWnd, udtMessage, udtRecip, udtFiles(0), &H0, Â0)
    '
End Sub

There's a lot going on in this routine. First, the routine accepts three parameters as input. The first parameter is the window handle used in all SMAPI calls. The second parameter is the file to be faxed. The third parameter is the phone number to use as the address for the MAPI fax. Once the routine has all the parameters, it's time to go to work.

The first step is to create a "simple" filename by stripping the folder name from the second parameter. This will be used as part of the attachment. Next, the routine builds a simple subject and message body for the MAPI message. The "#" at the end of the message marks the position where the attachment will be placed.

After building the message body, the attachment is created. Most of this should make sense. Setting the FileType property to "0" tells MAPI that this is an embedded data file instead of some type of OLE attachment.

Next comes the fun part-creating the recipient. Remember "one-off" addressing? That's where you use the actual MAPI transport name as part of the message. In this routine the .Name and .Address properties are both set to the internal complete MAPI address required for FAX messages. The FAX: tells MAPI to handle this message using the FAX transport provider. The stuff between the ":" and the "@" is just filler-MAPI ignores it. The last part of the address is the telephone number the FAX transport will use to deliver the message. The other property settings are default values used in all SMAPI recipient types.

Finally, after building the message, attaching the file, and creating the FAX address, the routine updates the recipient and file count and then calls the MAPISendMail function to place the message into the MAPI outbox.

What happens next depends on how your FAX transport is configured. If you have your FAX transport set to deliver faxes immediately, you'll see the FAX transport kick in, format the attachment, and send it out over the modem line. If you have your transport set to delay delivery for off-peak hours, you'll see the formatting, but the FAX will sit in a queue until later. Also, the cover sheet used for your FAX messages is established by settings for the FAX transport provider.

Tip
You can review your FAX transport settings from the Windows Messaging client by pressing the alternate mouse button on the Exchange inbox icon and selecting Properties from the context menu. Then select the FAX transport from the Services list and click the Properties button. You can even edit or invent new cover pages from this dialog box.

That's the end of the support routines. Save this module (FAXBACK.BAS) and the project (FAXBACK.VBP) before continuing with the next section.

The FaxBack Form

The FaxBack form is the main form of the project. Although there is not much code in the project, setting up the form takes quite a bit of doing. This is because most of the logic of the program is kept in the properties of the VBVoice controls on the form.

There are really three steps to building the FaxBack form:

The next three sections cover these three steps in greater detail.

Laying Out the FaxBack Form

Laying out the controls on the FaxBack form is more involved than doing the same for standard Visual Basic forms. This is because most of the controls on the form are VBVoice telephony controls. These controls require additional property settings and must be linked to one another to complete the call-flow diagram that will control each incoming call. You'll actually diagram the call progress and set the program properties at the same time. By the time you've diagrammed the call, you will have built almost all the logic needed to handle incoming fax requests.

First you need to lay out the controls on the form. Refer to Figure 34.2 and Table 34.1 for details on laying out the FaxBack form.

Figure 34.2 : Laying out the FaxBack form.

Warning
Be sure to add the VBVFrame control to the form first. Then draw the VBVoice controls onto the VBVFrame control. If you do not draw them on (instead of double-clicking the control in the toolbox), you'll get error messages while you are trying to build your form.

Table 34.1. The FaxBack form controls.
ControlProperty Setting
VB.Form Name frmFaxBack
  Caption "Form1"
  Font name="MS Sans Serif"
    charset=0
    weight=700
    size=8.25
  ForeColor &H80000008&
  Height 4665
  Left 1470
  LinkTopic "Form1"
  ScaleHeight 4260
  ScaleWidth 7290
  Top 1830
  Width 7410
VB.CommandButton Name cmdFax
  appearance 0 'Flat
  BackColor &H80000005&
  Caption "&About"
  Height 300
  Index 4
  Left 6000
  TabIndex 11
  Top 3780
  Width 1200
VB.CommandButton Name cmdFax
  appearance 0 'Flat
  BackColor &H80000005&
  Caption "E&xit"
  Height 300
  Index 3
  Left 6000
  TabIndex 9
  Top 3360
  Width 1200
VB.CommandButton Name cmdFax
  appearance 0 'Flat
  BackColor &H80000005&
  Caption "&Test Fax"
  Height 300
  Index 0
  Left 6000
  TabIndex 8
  Top 2100
  Width 1200
VB.CommandButton Name cmdFax
  appearance 0 'Flat
  BackColor &H80000005&
  Caption "Start"
  Height 300
  Index 1
  Left 6000
  TabIndex 7
  Top 2520
  Width 1200
VB.CommandButton Name cmdFax
  appearance 0 'Flat
  BackColor &H80000005&
  Caption "Stop"
  Height 300
  Index 2
  Left 6000
  TabIndex 6
  Top 2940
  Width 1200
VBVoiceLibCtl.VBVFrame Name VBVFrame1
  Height 3675
  Left 135
  TabIndex 0
  Top 435
  Width 5760
  CurrPage 0
  NumFields 0
  Playformat 3
  VoiceDir "d:\sams\CDG\Chap34\"
  TimeFormat 0
  DateOrder 0
  LanguageId 0
  NumControls 5
VBVoiceLibCtl.User Name VerifyFile
  Height 900
  Left 4140
  TabIndex 1
  Top 2100
  Width 945
  ClearDigits 0 'False
  NumConditions 2
  Condition0.Name "0"
  Condition0.Data ""
  Condition0.UseVB= 'True
  Condition1.Name "1"
  Condition1.Data ""
  Condition1.UseVB= 'True
  FramePage 0
  NumNodes 2
VBVoiceLibCtl.Onhook Name HangUp
  Height 600
  Left 3960
  TabIndex 2
  Top 540
  Width 855
  EntryGreeting. message has been sent"
  Phrase0.Data=  
  EntryGreeting.  
  Phrase0.Type=  
  FramePage 0
  NumNodes 0
  Comment ""
VBVoiceLibCtl.GetDigits Name GetFaxFile
  Height 975
  Left 2340
  TabIndex 3
  Top 2160
  Width 1140
  maxRetries 2
  EntryGreeting. enter the number of the
  Phrase0.Data= document you require."
  ClearDigits 0 'False
  NumConditions 1
  Condition0.Name "DocNbr"
  Condition0.Data "nnn"
  Condition0.UseVB= 'False
  FramePage 0
  NumNodes 3
  Dest2.Conn -1 'True
  Comment ""
  MaxKeys 0
  MaxSil 5
  TermDtmf 4096
  RetryOnSilence 0 'False
  useDefaultError 0 'False
  DisableHelp -1 'True
VBVoiceLibCtl.GetDigits Name GetFaxAddress
  Height 975
  Left 240
  TabIndex 4
  Top 2400
  Width 1440
  maxRetries 2
  EntryGreeting. enter the number of your
  Phrase0.Data= fax machine followed by a pound sign"
  EntryGreeting.  
  Phrase0.Type=  
  NumConditions 1
  Condition0.Name "FAXAddr"
  Condition0.Data "$"
  Condition0.UseVB= 'False
  FramePage 0
  NumNodes 3
  Dest2.Conn -1 'True
  Comment ""
  MaxKeys 0
  MaxSil 5
  TermDtmf 4096
  RetryOnSilence 0 'False
  useDefaultError 0 'False
  DisableHelp -1 'True
VBVoiceLibCtl.LineGroup Name AcceptCall
  Height 1425
  Left 420
  TabIndex 5
  Top 480
  Width 1080
  FramePage 0
  NumNodes 5
  Comment ""
  DelayTime 5
  LineType 0
  Mode 2
  LinesInGroup ""
  Mode 2
VB.Image Name Image1
  Height 1815
  Left 6120
  Stretch -1 'True
  Top 120
  Width 1155
VB.Label Name Label1
  BorderStyle 1 'Fixed Single
  Caption "FaxBack Call Flow
  Diagram"  
  Height 315
  Left 120
  TabIndex 10
  Top 60
  Width 5775

After you've placed the controls on the form, save it as FAXBACK.FRM and update the project (FAXBACK.VBP). Now you're ready to fine-tune the properties of the VBVoice controls.

Setting the VBVoice Control Properties

Setting the VBVoice controls is really the process of creating a telephony program. In this section you'll go through the process step by step. Two things must be accomplished in this part of the project. First, you must set the basic properties of each VBVoice control. This will determine the possible actions that can occur during a phone call. Next, you'll link each of the five controls together to form the call-flow diagram. This will complete the process by establishing a clear set of steps that each call can follow as it progresses through the conversation.

Tip
As you work through this part of the project, refer to Figure 34.2 to get an idea of what the finished product should look like.

The Frame Control

There is one property that must be set on the VBVFrame control. This property will tell all the other controls where to find the recorded prompts. Locate a blank spot on the frame and click the alternate mouse button to bring up the context menu, then select Properties to call up the custom properties box (see Figure 34.3).

Figure 34.3 : Editing the VBVFrame Properties.

Make sure the Project Voice Files property is set to the folder that contains the FAX.VAP voice prompt file. All the other properties on this control can be left to their default values.

The AcceptCall LineGroup Control

The AcceptCall LineGroup control is where the incoming call will enter the program. You do not need to set any properties for this control. However, you need to connect the "Ring" node of the AcceptCall control to the input node of the GetFaxAddr GatherDigits control (see Figure 34.2).

The GetFaxAddress GatherDigits Control

The GetFaxAddress GatherDigits control will be used to get the destination FAX telephone address from the caller. You need to add a custom node to the control by adding an entry on the Routing page of the custom properties box. First, remove all the numerical entries from the routing page by highlighting each one and pressing the Delete button. Then press the New button on the Routing page and enter "$" for the digits and "FaxAddr" for the condition name (see Figure 34.4).

Figure 34.4 : Adding a new node to the GetFaxAddress control.

Next, you need to set the properties on the Terminations page. First, clear the Use Default Error Handler check box and make sure the Clear digits on entry and Disable global help boxes are checked. Next, set the Maximum Silence to "5," the retries on error to "2," and the Always terminate on to "#" (see Figure 34.5).

Figure 34.5 : Setting the termination properties of the GetFaxAddress control.

You also need to add a greeting to this control. Select the Greetings page in the custom properties dialog box and press Add Phrase to bring up the Select Phrase dialog box. Then find the FAX.VAP file in the VAP combo box. Select the first phrase in the file-"Enter the number of your fax machine followed by a pound sign" (see Figure 34.6).

Figure 34.6 : Adding a new phrase to the GetFaxAddress control.

Finally, connect the FaxAddr node of the GetFaxAddress control to the input node of the GetFaxFile control.

The GetFaxFile GatherDigits control

This second GatherDigits control will be used to collect the three-digit document number that the user wishes to receive. Erase the default routine options and add a custom node to the control by pressing the New button on the controls Routing page. Enter "nnn" in the Digits field (you'll accept three, and only three, digits) and enter DocNbr in the condition name field.

Set the termination values for the GetFaxFile control the same as you did for the GetFaxAddress control. The only difference is that you should leave the Clear Digits on Entry check box empty (unchecked). The rest of the termination settings are identical to those you used in the GetFaxAddress control.

Next, add a greeting for this control to tell the user to enter a document number. Press the Add Phrase button on the Greetings page, select the FAX.VAP prompt file, and pick the second prompt in the file-"Enter the number of the document you require."

Lastly, connect the DocNbr node of the GetFaxFile control to the input node of the VerifyFile control.

The VerifyFile User Control

The VerifyFile control is a VBVoice User control. The exact actions taken by this control are determined by the user, usually through the results of Visual Basic code. For this project, make sure there are only two possible options: "0" and "1" (press the Delete button to remove the rest). Next, click off the Clear digits on Entry check box.

Now connect the "0" node of the VerifyFile control to the input node of the HangUp control. Then connect the "1" node of the VerifyFile control to the back of the Err node of the GetFaxFile control.

The HangUp OnHook Control

The last control in the call-flow diagram is the HangUp OnHook control. This control's job is to hang up the phone to terminate the call. The only property you need to add to this control is a parting salutation. Call up the custom properties box and press the Add Phrase button to bring up the Select Phrase dialog box. Locate the RECORD.VAP prompt file (it was installed with VBVoice) and pick the last phrase in the list-"Your message has been sent."

That is the last of the property settings for the VBVoice controls. You now have defined the call-flow diagram for your FaxBack application. Be sure to save this form (FAXBACK.FRM) and update the project (FAXBACK.VBP) before you continue.

Coding the FaxBack Form

Since most of the logic is kept in the VBVoice controls, you only need to add a few code routines to the form itself. You'll add code to the Form_Load and Form_Unload events, code for the command button array, and code for the VerifyFile_Enter and AcceptCall_Disconnect events.

First, you need to declare three form-level variables. Enter the code from Listing 34.7 into the general declarations section of the form.


Listing 34.7. Declaring the form-level variables.
Option Explicit
'
Dim bFaxNbrCollected As Boolean
Dim bRunMode As Boolean
Dim cLogID As String

Next, add the code from Listing 34.8 to the Form_Load event of the form.


Listing 34.8. Coding the Form_Load event.
Private Sub Form_Load()
    '
    ' startup inits for system
    bRunMode = False
    bFaxNbrCollected = False
    cFAXFolder = App.Path
    cFAXPrefix = "\FAX"
    cFAXSuffix = ".DOC"
    '
    ' local values
    cLogID = "MCA" ' a valid MAPI ID for your system
    cTestFAXAddr = "999-9999" ' a valid target FAX machine
    '
    ' setup the form
    Me.Caption = "FaxBack SMAPI/TAPI Fax Handler"
    Image1.Stretch = True
    Image1.Picture = LoadPicture(App.Path & "\copymach.wmf")
    CenterForm Me
    '
    ' start up MAPI services
    SMAPIStart Me.hWnd, cLogID
    '
End Sub

This routine sets several variables for the fax handler, initializes form properties, and logs into MAPI services. Notice that this version of the program will be looking for FAX documents stored in the same directory as the application (App.Path) that have "FAX" as the first three letters of the filename and that have ".DOC" as the file tail. If you decide to put this project into production use, you may need to create a more flexible naming convention for your documents.

Also note that you need to set the cLogID variable to a valid MAPI profile name (one that has access to FAX services). You should also set the cTestFAXAddr variable to point to a FAX you can use to test the application.

The Form_Unload code is quite short. Listing 34.9 shows the line you need to add to log off the MAPI services before exiting the program.


Listing 34.9. Coding the Form_Unload event.
Private Sub Form_Unload(Cancel As Integer)
    '
    SMAPIEnd Me.hWnd
    '
End Sub

Now add the code to handle the user selections on the command button array. Add the code in Listing 34.10 to the cmdFax_Click event.


Listing 34.10. Coding the cmdFax_Click event.
Private Sub cmdFax_Click(Index As Integer)
    '
    ' handle user selections
    '
    Dim i As Integer
    Dim cFile As String
    '
    Select Case Index
        Case 0 ' test fax
            cFile = cFAXFolder & cFAXPrefix & "000" & cFAXSuffix
            SendSMAPIFax Me.hWnd, cFile, cTestFAXAddr
        Case 1 ' start run mode
            VBVFrame1.StartSystem True
            VBVFrame1.ShowLogWindow 1, True
            bRunMode = True
        Case 2 ' stop run mode
            i = VBVFrame1.StopSystem(False)
        Case 3 ' exit program
            Unload Me
            End
        Case 4 ' about box
            frmFBAbout.Show vbModal
    End Select
    '
End Sub

There's not much that's special in the code in Listing 34.10. The first command button sends a test fax, the second and third start and stop VBVoice in run mode, the fourth button ends the program, and the last button calls the About box.

Note
The evaluation copy of VBVoice will operate only in test mode. If you wish to be able to use VBVoice in run mode, you'll need to purchase a licensed copy of VBVoice from Pronexus.

There are only two remaining code events for this form. The first is the Disconnect event of the AcceptCall control. This event fires each time the HangUp control ends a call. This is where the program attempts to send the requested FAX document to the recipient's FAX number. Add the code from Listing 34.11 to the AcceptCall_Disconnect event.


Listing 34.11. Coding the AcceptCall_Disconnect event.
Private Sub AcceptCall_Disconnect(ByVal Channel As Integer, ByVal Reason As Integer)
    '
    ' when the user hangs up, send the fax
    '
    ' NOTE --------------------------------------
    '       This routine does not run under
    '       TEST MODE - Only in RUN MODE.
    '       See the code in the VerifyFile_Enter
    '       event for details on TEST MODE
    '       behavior.
    ' --------------------------------------------
    '
    Dim cFile As String
    '
    If Not bFaxNbrCollected Then
        Exit Sub
    Else
        cFile = cFAXFolder & cFAXPrefix & CStr(GetFaxFile.Digits(Channel)) & ÂcFAXSuffix
        If FileExists(cFile) Then
            SendSMAPIFax Me.hWnd, cFile, GetFaxAddress.Digits(Channel)
        End If
    End If
    '
    bFaxNbrCollected = False ' for next time!
    '
End Sub

This routine first checks to make sure a document was selected, then confirms that it is on file, and then sends it out with a call to the SendSMAPIFax routine you coded at the start of this chapter. Once this is done, the program will wait for the next incoming call.

Note
You'll see from the comments, that this routine never executes in test mode. But if you have a licensed copy of VBVoice, you'll be able to run the code in this event.

The final code routine is the code for the VerifyFile_Enter event. This is the event tied to the User control. Under run mode, after a caller selects a document, this routine verifies it is on file and then passes the information on to the AcceptCall_Disconnect event. Under test mode, this routine verifies the file and then sends it out and exits the program. This exit is required in test mode since the program can never execute a disconnect in test mode.

Enter the code from Listing 34.12 into the VerifyFile_Enter event.


Listing 34.12. Coding the VerifyFile_Enter event.
Private Sub VerifyFile_Enter(ByVal Channel As Integer, ByVal Greeting As Object)
    '
    ' confirm valid fax selected
    '
    ' NOTE --------------------------------------
    '       Under TEST MODE, this routine verifies
    '       the file name then sends it via the FAX
    '       transport and QUITS.
    '
    '       Under RUN MODE, this routine verfies
    '       the file name and then fires off the
    '       the HangUp control. At disconnect the
    '       the AcceptCall control ships the FAX
    '       document.
    ' --------------------------------------------
    '
    Dim cFile As String
    '
    cFile = cFAXFolder & cFAXPrefix & GetFaxFile.Digits(Channel) & cFAXSuffix
    '
    If FileExists(cFile) Then
        bFaxNbrCollected = True
        If bRunMode = True Then
            VerifyFile.GotoNode(Channel) = 0
        Else
            SendSMAPIFax Me.hWnd, cFile, GetFaxAddress.Digits(Channel)
            End ' have to do this in test mode
        End If
    Else
        bFaxNbrCollected = False
        If bRunMode = False Then
            MsgBox "File Is Missing!"
        Else
            VerifyFile.GotoNode(Channel) = 1 ' exit Error
        End If
    End If
    '
End Sub

Now that you've completed all the code for the FaxBack form, save the form (FAXBACK.FRM) and the project (FAXBACK.VBP) before moving on to the last coding section.

The About Dialog Box

The About dialog box is very simple. It displays a graphic, a label control that shows some basic information about the project, and an OK command button. Refer to Figure 34.7 and Table 34.2 for details on laying out the About dialog box.

Figure 34.7 : Laying out the About dialog box.

Table 34.2. The About box form controls.
ControlProperty Setting
VB.Form Name frmFBAbout
 BorderStyle 3 'Fixed Dialog
 Caption "Form1"
 Height 2610
 Left 2685
 MaxButton 0 'False
 MinButton 0 'False
 ShowInTaskbar 0 'False
 Top 1890
 Width 4980
VB.CommandButton Name Command1
 Caption "&OK"
 Height 300
 Left 3540
 TabIndex 1
 Top 1800
 Width 1200
VB.Image Name Image1
 Height 1455
 Left 120
 Top 180
 Width 1395
VB.Label Name Label1
 Caption "Label1"
 Height 1455
 Left 1800
 TabIndex 0
 Top 180
 Width 2895

After laying out the form, you're ready to add code to the About box. You only need to add code to the Form_Load event and the Command1_Click event. Listing 34.13 shows all the code you need for the About form.


Listing 34.13. All the code for the About form.
Private Sub Command1_Click()
    Unload Me
End Sub

Private Sub Form_Load()
    '
    ' set up about dialog
    '
    Dim cVersion As String
    Me.Caption = "About " & App.ProductName
    Image1.Stretch = True
    Image1.Picture = LoadPicture(App.Path & "\copymach.wmf")
    '
    cVersion = "Version: " & CStr(App.Major) & "." & CStr(App.Minor) & "." & ÂCStr(App.Revision)
    Label1 = App.ProductName & Chr(13) & Chr(13)
    Label1 = Label1 & App.LegalCopyright & Chr(13) & Chr(13)
    Label1 = Label1 & App.FileDescription & Chr(13) & Chr(13)
    Label1 = Label1 & cVersion
    '
    CenterForm Me
    '
End Sub

Notice that most of the information displayed in the About box is drawn from the App object properties. You can set these properties using the File | Make EXE File | Options screen. Call up that screen now and enter the values from Table 34.3 into the dialog box.

Table 34.3. Setting the App object properties.
PropertySetting
Auto IncrementChecked ON
File DescriptionDemonstrates TAPI and SMAPI FAX
Legal Copyright(c)1996 MCA/SAMS Publishing
Product NameFaxBack FAX Server

That's the last code for this project. Save the form as FBABOUT.FRM and the project (FAXBACK.VBP). Now is a good time to compile your project and check for bugs. Once you're sure you have all the bugs worked out, you're ready to test your Visual Basic fax handler.

Testing the FaxBack Application

Testing the FaxBack application with the evaluation copy of VBVoice is a bit tricky, but not impossible. First, start the program in design mode (not compiled). Your first screen should look like the one in Figure 34.8.

Figure 34.8 : Starting the FaxBack Application.

For a simple test, press the Test FAX button. This will test the SMAPI side of the program without using any TAPI features. You should see the program locate the test document on your local drive, format it for FAX transport, and, if you have immediate delivery turned on, the workstation will dial the address and send the FAX (see Figure 34.9).

Figure 34.9 : FaxBack sending a FAX.

Tip
If you are getting error messages telling you that Microsoft Exchange could not find a transport provider for your fax message, try moving the FAX service to the first service in the list of transports for your machine. You can do this from the Properties window of Microsoft Exchange.

Once you have the FAX portion of the system working, you're ready to add the TAPI side of the application. You'll test the telephony services using the test mode of VBVoice. Test mode uses your workstation's sound card and speakers to simulate an incoming call.

To start test mode, move your pointer over the AcceptCalls control, press the alternate mouse button, and select Start Test from the context menu. You'll then see a test dialog box appear. This dialog box will act as a caller's telephone handset. When you press the Start button, you'll see a debug screen and a "Ring or Call" dialog box appear. Now VBVoice is ready to start testing your application (see Figure 34.10).

Figure 34.10 : Starting VBVoice in test mode.

Press the Ring button to start the test. This simulates a ringing phone for your application. You should see the debug window fill with tracking information and hear the prompts as they walk you through the process of entering a FAX address and selecting a document. Valid document numbers are "000," "100," and "200." These three Microsoft Word documents have been included in the same folder on the CD-ROM that has the FAX.VAP file and the other support files for this project. You can add other files if you wish.

Once the FAX document has been sent, the program exits to Visual Basic design mode. This is only true in test mode. If you were running a licensed copy of VBVoice in run mode, after sending the FAX, the program would wait for the next caller and start the process all over again.

Summary

In this chapter, you learned how to combine telephony and e-mail services to build a fax-on-demand server in Visual Basic 4.0, using VBVoice controls from Pronexus, and with the simple MAPI API declarations from Microsoft Exchange running the FAX transport.

This sample application does not contain all the bells and whistles needed to operate a production FAX server, but all the basics are here. If you wish, you can expand on this program by adding customized prompts and providing better error handling within the program and call flow. You should also consider writing a transaction log to keep track of all the calls you get and see what documents are being requested. With just a bit more work, you could have your very own FAX server up and running in no time!