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. |
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.
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 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.
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.
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!
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 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 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. |
Control | Property | 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 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. |
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 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 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.
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 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 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.
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 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.
Control | Property | 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.
Property | Setting |
Auto Increment | Checked ON |
File Description | Demonstrates TAPI and SMAPI FAX |
Legal Copyright | (c)1996 MCA/SAMS Publishing |
Product Name | FaxBack 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 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.
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!