Chapter 29
Distributing Integrated Applications
After you finish building and testing your integrated application, you're
ready to distribute it—right? Wrong. Before distributing any integrated
application, there are several things that you must know. This chapter
guides you through the distribution process.
In this chapter, you learn more about the following:
- Preventing distribution embarrassments
- Distributing your applications
- Handling performance considerations
- Understanding the importance of documentation and online Help
- Planning development and handling errors
Preventing Distribution Embarrassments
You've just completed your program and tested it for several hours (or
days) on your system. You're convinced that you have a "bug-free"
application, so you copy your executable to a floppy and take it to your
friend's computer. You spend 20 minutes telling him how awesome your program
is, just to arouse his curiosity. After he is so excited that he has declared
you a "Computer Genius," you copy your program to his hard disk.
You double-click on your program in File Manager, and a big error message
comes up on the screen.
Your face turns red, and you begin to sweat. You try to handle the situation
by reading the message to yourself and trying to run your program again.
Nothing happens. After trying everything you know, with no success, you
look to your friend and say, "What the heck is wrong with your stinking
computer?"
Has this happened to you? If not, then you better read this chapter
to prevent it from happening. If it has, you already know the importance
of this chapter.
This chapter discusses some of the important distribution-related issues
that will help you to maintain your status as a computer genius, and keep
you from jumping off a bridge in embarrassment. Read this chapter carefully
and refer to it often, or else you'll be the next victim of a poor distribution
attempt.
Distributing Your Applications
The first and most important part of a successful distribution is to
ensure that you have the correct files in the correct place. If you forget
one file, or if you put it in the wrong directory, your application will
not run. Forgetting distribution files also shows sloppiness on the part
your company, so it's something that you should avoid at all costs. See
Chapter 30, "Distributing Your Applications,"
in the Visual Basic Programmers Guide for a complete listing of
the supporting files that Visual Basic and its custom controls require.
Even if you write your own setup program, you should use the Setup Wizard.
The Setup Wizard searches your application for all the required distribution
files and copies them to a floppy disk. After Setup Wizard finishes, you
can look on the disk to see which files your application requires (ignore
the SETUP*.* files) and copy them to your setup disk.
Licensing Considerations
When making your distribution disk, you should copy only those files
that you have a license to distribute. Distributing unlicensed files can
lead to severe legal action against you and your company, as well as extreme
embarrassment. Even if you don't realize that you are illegally distributing
a file, you can still get into big trouble.
Play it safe and distribute only those files that you have a legal right
to distribute. When in doubt, contact the company that wrote the software
or contact Microsoft.
Even if a file comes with a program that you own (for example, clip
art from Corel Draw or certain Visual Basic files), you don't necessarily
have the legal right to distribute the file.
Handling Missing Files That Can't Be Licensed
If you can't purchase a license to distribute a file, you have to require
that your users own the program or file on which your application depends.
Because you are likely to write an application that depends on one or more
Microsoft Office applications (which you can't distribute), you
will have to notify the user of which Office applications (and versions)
that he or she must have installed before running your program.
Ensuring Proper Installations—Setup Programs
Copying all the proper files to your disk doesn't mean that they will
get copied to the correct directory on the user's system. If your application
doesn't have a setup program that does everything necessary to run
your application, the odds of it working on another computer are very poor.
You should always write a good setup and uninstall program.
The advantages of a good setup and uninstall program are many, because
it does the following:
- Provides a more professional appearance for your product
- Ensures that your application will be successfully installed on your
customers computer
- Saves you the expense of support calls regarding setup and removal
of your product
- Protects you and your company from embarrassment
Because you purchased Visual Basic 4.0, you have no excuse not to have
a setup program, because VB4 includes the Setup Wizard. The Setup Wizard
is a great utility that creates a setup/uninstall disk for your Visual
Basic application and makes sure that all the files that your application
requires are on it.
If your application requires a more robust setup program, you can always
modify the source code that Setup Wizard creates and add your application-specific
features. If you need even more advanced features and you don't know how
to code them, you can always purchase one of the many prewritten setup
programs on the market.
A good setup program pays for itself after you sell your first five
to ten applications (depending on the product cost), so you have no excuse
not to write one (no matter how small your application is).
All Windows 95 certified applications will be required to have a setup
program that installs and uninstalls all of its files, so now is the time
to learn how to write a good setup program. If you have the Windows 95
SDK, you also can consider using the InstallShield 95 setup and uninstall
program that comes with the SDK.
If possible, set up a single system with only your target operating
system installed. If your application can run on a system that has only
the operating system installed, the odds are that your setup disk is good.
Handling Missing Components—Gracefully
When creating integrated applications that depend on multiple programs
being present, you must ensure that your program is prepared to handle
a missing component. For example, suppose that you want to create an About
box that has a System Info button like the ones in the Office applications,
as shown in figure 29.1.
Fig. 29.1
You can add Microsoft's System Info button to your applications.
You can't legally distribute the System Information program, so your
program can show or hide that button depending on whether that component
is present. Listing 29.1 demonstrates how to accomplish this task.
Listing 29.1 This Example Shows How Your Application Can Handle Missing
Components Gracefully
'****************************************************************
' FRMABOUT.FRM - Demonstrates how to handle a missing component.
'****************************************************************
Option Explicit
Private WinDir As String
#If Win32 Then
Const SYSINFO = "msapps\msinfo\msinfo32.exe"
Private Declare Function GetWindowsDirectory& Lib "Kernel32"
_
Alias "GetWindowsDirectoryA" (ByVal buffer$, ByVal bufLen&)
#Else
Const SYSINFO = "msapps\msinfo\msinfo.exe"
Private Declare Function GetWindowsDirectory% Lib "Kernel"
_
(ByVal buffer$, ByVal bufLen%)
#End If
'****************************************************************
' Unload the form.
'****************************************************************
Private Sub cmdOk_Click()
Unload Me
End Sub
'****************************************************************
' Start the Microsoft System Information program.
'****************************************************************
Private Sub cmdSysInfo_Click()
Shell WinDir & SYSINFO, vbNormalFocus
End Sub
'****************************************************************
' Load the form and determine if the System Info button should
' be visible.
'****************************************************************
Private Sub Form_Load()
'************************************************************
' Always use system colors.
'************************************************************
Lines(0).BorderColor = vb3DHighlight
Lines(1).BorderColor = vb3DShadow
Lines(2).BorderColor = vb3DHighlight
Lines(3).BorderColor = vb3DShadow
BackColor = vb3DFace
'************************************************************
' Change the picture displayed in the image control.
'************************************************************
img.picture = Me.Icon
'************************************************************
' Center the form.
'************************************************************
Move (Screen.Width - Width) \ 2, (Screen.Height - Height) \ 2
'************************************************************
' Get the path to the Windows directory.
'************************************************************
WinDir = Space(2048)
WinDir = Left(WinDir, GetWindowsDirectory(WinDir, _
Len(WinDir))) & "\"
'************************************************************
'Set visible status depending on the existence of the file.
'************************************************************
cmdSysInfo.Visible = FileExists(WinDir & SYSINFO)
End Sub
'****************************************************************
' Determine if the file exists, and return the result.
'****************************************************************
Private Function FileExists(sFileName As String) As Boolean
On Error Resume Next
FileExists = IIf(Dir(sFileName) <> "", True, False)
End Function
The key element of this program is determining whether the file exists.
If MSINFO.EXE is present, the button's Visible property changes to True.
Otherwise, the program sets its Visible property to False and hides the
button. Figure 29.2 shows how the sample program looks when MSINFO.EXE
exists.
Fig. 29.2
The System Info button displays only if MSINFO.EXE exists.
You might think that it is much more difficult to handle a missing Office
application, but it really isn't. Listing 29.2 shows how easy it is to
determine whether an Office application is present.
Listing 29.2 Checking for An Application's Existence Is Easy
'*****************************************************************
' FRMEXISTS.FRM - Lists the existence of several Office apps.
'*****************************************************************
Option Explicit
#If Win16 Then
Private Declare Function GetProfileString% Lib "Kernel"
(ByVal _
sSection$, ByVal sKey$, ByVal sDef$, ByVal sRetStr$, _
ByVal iSize%)
#End If
'*****************************************************************
' Checks to see if a file exists.
'*****************************************************************
Function FileExists(sFileName$) As Boolean
On Error Resume Next
FileExists = IIf(Dir(Trim(sFileName)) <> "", True,
False)
End Function
#If Win32 Then
'*****************************************************************
' This function determines if an application is present by seeing
' if there is any text in the Registry for the provided SubKey.
'*****************************************************************
Public Function IsAppPresent(strSubKey$, strValueName$) As Boolean
IsAppPresent = CBool(Len(GetRegString(HKEY_CLASSES_ROOT, _
strSubKey, strValueName)))
End Function
#Else
'*****************************************************************
' This function determines if an application is present.
' The sExtension arg is the 3-letter extension of its data files.
' The sDefaultPath is where you think the app might be installed.
'*****************************************************************
Public Function IsAppPresent(sExtension$, sDefaultPath$) _
As Boolean
Dim sAppPath As String
'*************************************************************
' Check the [Extensions] section of the WIN.INI to see where
' the app is located. If the extension is not found, then
' the default EXE path (sDefaultPath) is checked.
'*************************************************************
sAppPath = Space(4098)
GetProfileString "Extensions", sExtension, sDefaultPath
__
& " ^" & sExtension, sAppPath, Len(sAppPath)
'*************************************************************
' [Extensions] section stores info in the following format:
' <extension>=<application path> ^<extension>
' To get the application path, you'll need to take everything
' to the left of the caret (^).
'*************************************************************
sAppPath = Left(sAppPath, InStr(sAppPath, "^") - 1)
'*************************************************************
' Return whether or not the application is present.
'*************************************************************
IsAppPresent = FileExists(sAppPath)
End Function
#End If
'*****************************************************************
' Unloads the form.
'*****************************************************************
Private Sub cmdExit_Click()
Unload Me
End Sub
'*****************************************************************
' Performs some initialization steps, and list the existence of
' certain Office apps.
'*****************************************************************
Private Sub Form_Load()
Move (Screen.Width - Width) / 2, (Screen.Height - Height) / 2
Print 'Print blank line
'*************************************************************
' Call the appropriate version of IsAppPresent, depending on
' the current platform.
'*************************************************************
#If Win32 Then
Print " Access", IsAppPresent("Access.Database\CurVer",
"")
Print " Excel", IsAppPresent("Excel.Sheet\CurVer",
"")
Print " PowerPoint", IsAppPresent("PowerPoint.Slide\CurVer",
_
"")
Print " Word", IsAppPresent("Word.Document\CurVer",
"")
#Else
Print " Access", IsAppPresent("mdb", "c:\access\msaccess.exe")
Print " Excel", IsAppPresent("xls", "c:\excel\excel.exe")
Print " PowerPoint", IsAppPresent("ppt", _
"c:\powerpnt\powerpnt.exe")
Print " Word", IsAppPresent("doc", "c:\winword\winword.exe")
#End If
End Sub
The key feature in this application is the IsAppPresent function. In
the 16-bit version of Windows, all you need to do to find out whether an
application exists is to check whether its executable is present. Because
the WIN.INI file contains the location of most executables in the [Extensions]
section, locating the application is easy. Figure 29.3 shows the program
in listing 29.2 running.
Fig. 29.3
The APPEXIST.VBP project determines which Office applications exist.
In the 32-bit version of Windows, you will want to search the Registry
to make sure that an application is present. The following module, REGISTRY.BAS,
retrieves a string from anywhere in the Registry (unlike VB4's GetSetting
function):
'*****************************************************************
' REGSITRY.BAS - Contains the code necessary to access the Windows
' registration datbase.
'*****************************************************************
#If Win32 Then
Option Explicit
'*****************************************************************
' The minimal API calls required to read from the Registry.
'*****************************************************************
Private Declare Function RegOpenKey Lib "advapi32" Alias
_
"RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String,
_
phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32"
Alias _
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName
As _
String, lpReserved As Long, lptype As Long, lpData As Any, _
lpcbData As Long) As Long
Private Declare Function RegCloseKey& Lib "advapi32"
(ByVal hKey&)
'*****************************************************************
' The constants used in this module for the regsitry API calls.
'*****************************************************************
Private Const REG_SZ = 1 ' Unicode null terminated string
Private Const REG_EXPAND_SZ = 2 ' Unicode null terminated string
' with environment variable
' references.
Private Const ERROR_SUCCESS = 0
'*****************************************************************
' The numeric constants for the major keys in the regsitry.
'*****************************************************************
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003
Public Const HKEY_PERFORMANCE_DATA = &H80000004
'*****************************************************************
' GetRegString takes three arguments. A HKEY constant
' (listed above), a subkey, and a value in that subkey.
' This function returns the string stored in the strValueName
' value in the Registry.
'*****************************************************************
Public Function GetRegString(hKey As Long, strSubKey As String,
_
strValueName As String) As String
Dim strSetting As String
Dim lngDataLen As Long
Dim lngRes As Long
'*************************************************************
' Open the key. If success, then get the data from the key.
'*************************************************************
If RegOpenKey(hKey, strSubKey, lngRes) = ERROR_SUCCESS Then
strSetting = Space(255)
lngDataLen = Len(strSetting)
'*********************************************************
' Query the key for the current setting. If this call
' succeeds, then return the string.
'*********************************************************
If RegQueryValueEx(lngRes, strValueName, ByVal 0, _
REG_EXPAND_SZ, ByVal strSetting, lngDataLen) = _
ERROR_SUCCESS Then
If lngDataLen > 1 Then
GetRegString = Left(strSetting, lngDataLen - 1)
End If
End If
'*********************************************************
' ALWAYS close any keys that you open.
'*********************************************************
If RegCloseKey(lngRes) <> ERROR_SUCCESS Then
MsgBox "RegCloseKey Failed: " & strSubKey, vbCritical
End If
End If
End Function
#End If
Application Performance Considerations
Another major pitfall that you face when distributing an integrated
application is performance considerations. If the target system doesn't
have enough random access memory (RAM) or is low on system resources, your
application can fail. In this section, you learn how to ensure that your
application thrives on its targeted system.
System Requirements
After you create your integrated application, you need to gather the
system requirements of all products that your applications use. Using these
system requirements, you can take the highest requirements from each to
determine what your application requires.
Next, you should take the following steps to determine what minimum
free system resources your application requires:
- Exit and restart Windows.
- From Notepad's About box, check the available amount of system resources.
Write this number down.
- Close Notepad's About box and run your application.
- Test every feature of your application (except any that terminate
it).
- While your application is still running, return to Notepad's About
box to see what the System Resources line reads now.
- Subtract amount in step 5 from the amount in step 2. This is the
amount of system resources your application consumes.
Now you're ready to build your system requirements list. Your system
requirements should include the following information:
- Operating system requirements (for example, Windows 3.1 or greater)
- Minimum and recommended random-access memory (RAM) requirements
- Disk space required (which you calculate from the uncompressed size
of all your files on your setup disk)
- Monitor requirements (usually VGA or higher)
- Pointing device requirements (for example, whether the application
requires a mouse or pen tablet)
- Office applications (with version) required (for example, Excel 5.0,
Word 6.0, and so on)
- Networking software required, if any (for example, whether Windows
for Workgroups is required)
Most integrated applications have the following system requirements:
- Windows 3.1, Windows for Workgroups 3.11, or Windows NT 3.51 or greater
- 8M RAM required, 12M or more recommended
- 2M of free disk space or more
- VGA (640X480X16) or higher
- A mouse is optional but strongly recommended
- Microsoft Office Professional 4.3c or greater
After establishing your user requirements, you should put them in the
front of your product manual, in your README.TXT file, and on your product
packaging (if any). This is important because the customer must know what
your product requires before purchasing it.
Hardware Performance Considerations
Because you're reading this book, you're probably a real "power
user." You probably have at least a 486–50 or greater system with
16M or more RAM. This means that your application really flies when you
use it, but what happens when you install it on a wimpy machine (for example,
a 486-25 with 8M of RAM)? If your answer is that "it croaks,"
you must reconsider how you have written your application.
Handling Wimpy Machines
Writing a program for a system that is less powerful than your own is
difficult, but important if you want your program to succeed. Because most
institutions (businesses, government, schools, and so on) are usually two
or more years behind in technology, you neglect a big market by writing
applications that run only on systems that are as fast (or faster) than
your own.
Of course, you can't target systems that don't meet your system requirements,
but your program should run (at least partially) on any 486 (or higher)
system with at least 8M of RAM.
The most important thing about handling a wimpy machine is to ensure
that your program doesn't perform unexpectedly during any of the following
stressful situations:
- Low memory or system resources
- Low or insufficient disk space
- Printing to dot-matrix printers
- Video resolution is set to 640x480x16
Each of these situations can cause your program to fail miserably, so
you must prepare to handle them.
If possible, you should always try to test your application on a 386-33
with 4M of RAM that is running its video at 640X480X16 and prints
to a dot matrix printer. This test will indicate how your program responds
to wimpy machines.
Handling Low Memory Situations
No matter how much RAM a system has, your application will eventually
face a low memory or low system resource situation. By handling the situation
gracefully, you show your customer that you thought of everything when
you developed your application, and keep the technical support calls to
a minimum.
When a Visual Basic application gets low on memory, the value of Err
is either 7 (a standard out-of-memory error) or 31001 (an OLE out-of-memory
error). Therefore, your application should always watch for these error
messages. It's also useful if your application can do something internally
to try to free up some more memory. Listing 29.3 demonstrates some of the
steps that your application can take to handle low memory situations.
Listing 29.3 Every Application Should Be Prepared to Handle Low
Memory Situations
'************************************************************
' FRMLOMEM.FRM - Demonstrates good error-handling techniques.
'************************************************************
Option Explicit
'************************************************************
' Centers the form
'************************************************************
Private Sub Form_Load()
'********************************************************
' Tell your app where to go when an error occurs.
'********************************************************
On Error GoTo Form_Load_Err
'********************************************************
' Center the form and the label.
'********************************************************
Move (Screen.Width - Width) / 2, (Screen.Height - Height) / 2
lblMsg.Move (ScaleWidth - lblMsg.Width) / 2, _
(ScaleHeight - lblMsg.Height) / 2
'********************************************************
' Raise an error to simulate a low memory situation.
'********************************************************
Err.Raise InputBox("Enter a error number:", Default:=7)
Exit Sub
Form_Load_Err:
'********************************************************
' When an error is triggered, jump to the error handler.
'********************************************************
ErrHandler Err.Number, "Form_Load"
End
End Sub
This program prompts the user for an error number and passes that number
to Err.Raise to simulate an error. After the error is triggered, the program
transfers control to the following error-handling routine:
'************************************************************
' A generic error handler.
'************************************************************
Sub ErrHandler(iErr%, sCallingProc$)
Dim msg$, res%
'********************************************************
' Prevent crashes in your error handler with Resume Next
'********************************************************
On Error Resume Next
'********************************************************
' If out of memory error, then tell use to free memory
'********************************************************
If iErr = 7 Or iErr = 31001 Then
'****************************************************
' Here is a good place to unload any picture boxes,
' hide unnecessary controls, close DDE links or OLE
' objects, erase arrays, and set object variables
' = Nothing.
'****************************************************
msg = "Your system is extremely low on memory, so "
msg = msg & "please close any applications "
msg = msg & "that you (or this application) are "
msg = msg & "not using."
'********************************************************
' Otherwise tell the user what error occurred, and where
' it was triggered. (This is useful during tech support
' calls).
'********************************************************
Else
msg = "A """ & Error(iErr) & """
error has occurred "
msg = msg & "in this applications " & sCallingProc
msg = msg & " procedure. " & vbLf & vbLf &
"Please "
msg = msg & "consult ""Appendix E: Error Messages""
"
msg = msg & "for instructions on how to correct "
msg = msg & "this error."
End If
'********************************************************
' Display the appropriate error message.
'********************************************************
MsgBox msg, vbExclamation
End Sub
After the error has been triggered, the error handler displays an appropriate
error message for the user. If the error was an out-of-memory error, the
message says to close any unnecessary applications to free up some more
memory. Figure 29.4 shows the error message.
Fig. 29.4
A good error message tells the user what to do to fix the error.
Low or Insufficient Disk Space
Because they usually have large hard disks, programmers can easily forget
that others aren't so fortunate. You must prepare your application (especially
your setup program) for the dreaded Err 61 (Disk Full) error.
Whenever you create or copy a file, you should always check whether
the available disk space is greater than the size of the file that you
want to copy or create. If there isn't enough room, you should notify the
user to free up some disk space and provide the option of either aborting
or trying again. If there is enough room, you should copy your file, but
still include an error handler for Err 61. Listing 29.4 is an example of
a function that returns the available disk space.
Listing 29.4 The GetDiskSpaceFree Function Returns the Available
Disk Space
Option Explicit
#If Win32 Then
Private Declare Function DiskSpaceFree Lib "STKIT432.DLL"
Alias _
"DISKSPACEFREE" () As Long
#Else
Private Declare Function DiskSpaceFree Lib "STKIT416.DLL"
() _
As Long
#End If
'*************************************************************
' Get the disk space free for a specific drive
'*************************************************************
Public Function GetDiskSpaceFree(sDrive As String)
Dim res As Long
On Error Resume Next
'*********************************************************
' Change to the drive that you wish to check.
'*********************************************************
ChDrive sDrive
res = DiskSpaceFree()
'*********************************************************
' If STKIT4*.DLL or drive can't be found, then return -1.
'*********************************************************
GetDiskSpaceFree = IIf(Err, -1, Format(res, _
"###,###,###,##0"))
End Function
'*************************************************************
' Get the disk space free for the current drive
'*************************************************************
Private Sub Command1_Click()
Caption = GetDiskSpaceFree(Left(CurDir, 1))
End Sub
If you use the GetDiskSpaceFree function, you must make sure that you
install STKIT416.DLL or STKIT432.DLL. You can find this file on any disk
created by Setup Wizard.
Handling Different Resolution Printers
Beginning programmers often forget that not every user prints to printers
that have the same resolution as theirs. Such a mistake can render your
program's printing feature useless to some of your customers, and cause
you to lose business.
The only good way to handle printing to different printers is to test
your printing features on the following printers:
- A 9- and 24-pin dot-matrix printer at draft and proof quality resolutions
- A 300-dpi and 600-dpi laser printer
- A 600-dpi postscript printer
When your program can successfully print to each of these types of printers,
your printing feature is ready to ship. The new printer object in Visual
Basic 4.0 provides a wealth of new methods and properties to help take
advantage of almost any printer that you can install on Windows. Before
calling the Windows API printing functions, make sure that you look closely
at the new Printer object in VB4.
Developing the UI in 640X480X16
One of the biggest mistakes that a Windows programmer can make is to
neglect developing your user interface in 640X480X16 resolution.
You might spend over a week developing the perfect user interface, only
to discover that your interface is useless on anything less than 800X600X256.
Some of the problems that you face by not developing user interface in
640X480X16 are the following:
- Your nonsizable forms are either too tall or too wide.
- If Paintbrush saves its bitmaps in the highest resolution that your
video can display, your toolbar bitmaps are accidentally saved as 256-color
bitmaps. This causes systems that run in 16 colors either to display the
bitmaps in black or generate a General Protection Fault in the video driver.
- Some of your message boxes might contain so much text that the OK
button isn't visible to users running at 640X480.
To make matters worse, if you then try to fix your forms, you might
discover that there isn't enough room on your existing forms to hold all
of your controls. You could wind up spending another two weeks fixing your
user interface because you have to double the number of forms in your application.
You might have to delay your perfectly debugged product just because you
forgot to plan for a lower resolution.
Before you decide to require your users to run your application in 800X600X256,
remember that an estimated 90 percent of all Windows users have their video
resolution set to 640X480X16. Because most users don't know how to
change their video resolution, it is vital that your application support
this common video resolution. Windows 95 might alleviate this problem,
but you should still consider 640X480X16 as a target resolution.
As you can see in listing 29.5, you don't even have to call the API
to get the video resolution. However, if you want to find out how many
colors the screen supports, you have to make a few API calls.
Listing 29.5 A Demonstration of How to Retrieve the Current Video
Resolution
'*****************************************************************
' VIDEORES.BAS - Displays the current video resolution.
'*****************************************************************
Option Explicit
#If Win32 Then
Private Declare Function GetDC& Lib "User32" (ByVal
hWnd As Long)
Private Declare Function GetDeviceCaps% Lib "GDI32" (ByVal
hDC&, _
ByVal iCapability&)
#Else
Private Declare Function GetDC% Lib "User" (ByVal hWnd
As Integer)
Private Declare Function GetDeviceCaps% Lib "GDI" (ByVal
hDC%, _
ByVal iCapability%)
#End If
'*****************************************************************
' Displays the video resolution in a message box.
'*****************************************************************
Sub Main()
MsgBox GetResolution(True), vbInformation, "Video Resolution"
End Sub
'*****************************************************************
' Determines the width, and height of the screen in pixels,
' and the number of colors the screen can display at one time.
'*****************************************************************
Function GetResolution(bReturnColors As Boolean) As String
Dim iWidth, iHeight, iColors, ScreenHDC
Const BITSPIXEL = 12
Const PLANES = 14
'*************************************************************
' Get the resolution using standard VB methods.
'*************************************************************
iWidth = Screen.Width \ Screen.TwipsPerPixelX
iHeight = Screen.Height \ Screen.TwipsPerPixelY
'*************************************************************
' Get the device context of the screen, and use GetDeviceCaps
' to find out how many colors the screen supports.
'*************************************************************
ScreenHDC = GetDC(0)
iColors = GetDeviceCaps(ScreenHDC, PLANES) * 2 _
^ GetDeviceCaps(ScreenHDC, BITSPIXEL)
'*************************************************************
' Only display the color resolution if the caller wants it.
'*************************************************************
If bReturnColors Then
GetResolution = iWidth & "x" & iHeight & "x"
& iColors
Else
GetResolution = iWidth & "x" & iHeight
End If
End Function
The Importance of Documentation and Help
No matter how user-friendly you think your program is, plenty of users
still won't be able to figure it out. That's why you must provide a well-written
user's manual and online Help file.
The best online Help is a copy of your manual. You can save yourself
a lot of time if you first create your Help file, then save it under a
different name, and use it to create your manual.
Before shipping any application, you should make sure that your documentation
and online Help discuss every element of your program and its output (printout,
files, and so on). After completing both, you can link every control in
your project to its corresponding topic in your Help file by using the
HelpContextID property. After your product is ready to ship, test what
happens when you press the F1 key on every control.
A good manual and Help file separates good applications from bad ones.
Even if your product is shareware, you'll benefit greatly from spending
time on these valuable accessories to your product. You'll also find that
you increase your chances to get free magazine reviews when you take the
time to document your product well.
Planning and Error Handling
This chapter has saved the most important two aspects of the development
process for last: planning and error handling. If you neglect either one
of these elements during the development process, your application is destined
to fail (or at least require a quick maintenance release).
The Planning and Development Process
Planning should be the first step in your entire development process.
A discussion of all the aspects of the development life cycle is beyond
the scope of this book, but you can use the following list a guide for
every development project:
- Talk to your customers or intended audience and find out what features
they want to see in the program you are about to develop. Any project built
around user feedback is destined for success.
- Create several user-interface prototypes (don't include any feature-specific
code) and give them to your intended audience. After you find out what
they like and dislike, you can scrap the prototype and build your user
interface.
- Never use the prototype as your final user interface. If you
do so, you'll pay dearly later in the development life cycle (especially
during upgrades).
- After deciding which features you want to implement, code them as
functions (or subroutines) and make sure that they are application-independent.
A good function can be copied, pasted into another project, and used without
modification. The best way to ensure that you write good functions is to
code them in temporary projects rather than in your user-interface project.
- Comment every line of code. Although doing so might seem ridiculous
as you are coding, you'll be glad that you add the comments when it comes
time to upgrade your product several months (or years) later.
- Consider putting similar code in modules or classes to make them reusable
with other projects.
- After you have a solid (and fully debugged) code base, add the code
to your user-interface project. After linking the code to your user interface,
debug it again to ensure that no new bugs have appeared.
- Make sure that every function (and sub) in all your forms has
an error handler. You should also ensure that your error handler provides
a useful error message for the user and your technical support staff.
- Make sure that your application gives the user something to look at
during long processing times. An hourglass is appropriate only if the processing
takes less than a minute. If the processing takes longer, consider using
a splash screen or a progress bar.
- Begin writing your Help file and manual as soon as you have completed
your user interface. Documentation usually takes two to three times longer
than development (if you do it properly), so you should get started early.
During the beta tests, you also should solicit feedback to find out what
users think of the preliminary draft of your documentation.
- Beta test your product. If possible, let at least 25 users at different
locations test your product for a month or two. If your product can go
two weeks without any of the 25 beta sites reporting a single bug, you're
usually ready to ship your product.
If you like to code but hate commenting, you might try the following
technique. Code first, then comment every line of code last. You then must
reread every line of code, which often can uncover fuzzy logic and dead
code that you can change or eliminate.
This book could go on for pages citing things that you should do during
the planning and development stage, but the preceding list should give
you a starting point. See the "From Here" section at the end
of this chapter for more information about where you can go to learn more
about this important process.
Error Handling
Unless you're some sort of programming god, your application is destined
to have run-time bugs that you never expected. The key to handling such
bugs is a good error-handling mechanism in your project. The following
list describes some of valuable tips:
- Create good generic error handling, that shown in listing 29.3. In
addition, you might want to add a few lines that perform such tasks as
closing all open files and restoring the mouse pointer.
- Add an error handler to every function (or subroutine) in your forms.
A good practice is to use the name of the function, followed by _Err (for
example, Form_Load_Err, as shown in listing 29.3).
- Present very descriptive error messages so that your application's
user and technical support staff have a good idea about what caused your
application to fail.
From Here...
An entire book could be written on the topics covered in this chapter,
but this chapter is a good start on successfully distributing your integrated
application. If you are interested in obtaining additional information
on the topics mentioned in this section, you should do the following:
- Read programming-related magazines (for example, Visual Basic Programmer's
Journal) and attend programming-related conferences (for example, Microsoft's
TechEd Conference in the Spring). Many of the articles in programming magazines
and seminars at programming conferences can save you months (or even years)
of trial-and-error experiences.
- See Chapter 30, "Distributing Your Applications,"
in the Visual Basic Programmers Guide for a complete listing of
the supporting files that Visual Basic and its custom controls require.
- See this book's Chapter 28, "Integration with
Multiple Office Applications," for more information about writing
a large-scale application in Visual Basic.
- See Chapter 32, "Advanced Code Techniques,"
in this book for more information about optimizing your code.
© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a
Simon and Schuster Company.