Internet Newsgroups: comp.lang.basic.visual,comp.answers,news.answers
Subject: comp.lang.basic.visual VB/Win Frequently Asked Questions
X-Content-Currency: This FAQ changes regularly.  When a saved or printed copy
                    is over 6 months old, please obtain a new one.
Expires: Sun, 8 May 1994 05:30:35 GMT
Organization: Visual Basic FAQ Maintainers
Date: Thu, 21 Apr 1994 05:30:42 GMT
X-Posting-Frequency: Posted on the 5th and 20th of each month.
Summary: Frequently asked questions concerning Visual Basic for Windows.
Keywords: FAQ VISUAL BASIC WINDOWS

                    VISUAL BASIC FOR WINDOWS (VB/Win)
                   Commonly asked Questions & Answers
                             Section IX - B
                  ------------------------------------

TABLE OF CONTENTS:
------------------

PREFACE

A - GENERAL VISUAL BASIC QUESTIONS
   1   Does VB/Win make standalone .EXE files?
   2   What is the current version of the Visual Basic?
   3   Where can I get updated VB and other Microsoft files?
   4   Where can I get good up-to-date information about VB?
   5   Are there any examples of commercial applications
       built using Visual Basic?

B - COMMON VISUAL BASIC PROGRAMMING QUESTIONS
   
   1   What's the difference between MODAL and MODELESS
       forms?
   2   When/Why should I use Option Explicit?
   3   Is the Variant type slower than using other variable
       types?
   4   How do I make a text box not beep when I hit the enter
       key?
   5   How do I get the Tab key to be treated like a normal
       character?
   6   What is passing by reference?
   7   Is there any way to pass a variable to a form apart
       from using global variables?
   8   How should dates be implemented so they work with
       other languages/countries formats?
   9   Can a VB application be an OLE server?
   10  How do I dial a phone number using the MSCOMM VBX in
       VB Pro?
   11  I have [several] megabytes of memory. Why do I get an
       out of memory error?
   12  How do I mimic a toggle button?
   13  How do I get my application on top?

C - ADVANCED VISUAL BASIC PROGRAMMING ISSUES
   1   How do I tell when an application executed using the
       SHELL command is finished?
   2   How do I access C style strings?
   3   How can I change the printer Windows is using in code
       without using the print common dialog?
   4   I'm adding lots of features to a LISTBOX, but it's
       sloooooow. What can I do to speed it up?
   5   How do you make a TEXTBOX read only?. Or, how do I
       prevent the user from changing the text in a TEXTBOX?
   6   How much gain in performance will I gain if I write my
       number crunching routines in C instead of in basic?
   7   How can I create a VBX?
   8   How do you change the system menu (on the Control-Menu
       Box)?
   9   How do I play MID, WAV or other multimedia files?
   10  How can I call a 'hidden' DOS program from VB?
   11  How do I do drag & drop between applications?
   12  How do I use GetPrivateProfileString to read from INI
       files?
   13  How do I speed up control property access?
   14  How do I implement Undo?
   15  How do I create a window with a small title bar as in
       a floating toolbar?

D - CALLING THE WINDOWS API AND DLLs IN GENERAL
   1   What is the Windows API?
   2   How do I call a DLL?
   3   What about DLL calls that require callbacks?
   4   Tips for calling DLLs (such as the Windows API)

E - VISUAL BASIC AND DATABASES
   1   Why can't I use an index with my VB accessed database?
   2   Why does my compiled VB database app generate an error
       when it ran just fine in the design environment?
   3   Is the Access Engine and Visual Basic Pro good enough
       for database work?
   4   How do you avoid the "Invalid use of null" error when
       reading null values from a database?

F - DISTRIBUTING VISUAL BASIC APPLICATIONS
   1   What are some tips for using Setup Wizard?
   2   Are there restrictions on what I can distribute with
       my VB program?

G - MISCELLANEOUS TIPS AND INFORMATION
   1   "Clean up" your project before compiling.
   2   Multiple END statements can be dangerous.
   3   What are the latest versions of the various files used
       by VB?



PREFACE
-------

This document is a compilation of frequently asked questions and
their answers about Visual Basic for Windows which have been
gathered from posts to the comp.lang.basic.visual newsgroup.  
Although some efforts have been made to find obvious errors,
there is no guarantee that the information in this document is
error-free.  The FAQ maintainer, or anyone else associated with
this document, assume NO liability for the content or use of this
document.  If you find any errors, please report them to the
address given below.

In this document, whenever a long line of code must be split into
two or more lines of text in the code examples, a | symbol will
precede each line which should be appended to the line above it.

Most FAQs (including this one) are available at the anonymous ftp
archive site "rtfm.mit.edu".  All four parts of the VB FAQ may be
found in the directory "pub/usenet/comp.lang.basic.visual".
You can also have the VB FAQs e-mailed to you by sending a
message to "mail-server@rtfm.mit.edu" with ONLY the text "send
usenet/comp.lang.basic.visual/*" in the body of the message.

A - GENERAL VISUAL BASIC QUESTIONS
----------------------------------

1  Does VB/Win make standalone .EXE files?
       VB/Win produces .exe files, but they are not standalone.
       All VB/Win programs distributed must be with the
       VBRUNx00.DLL file. This DLL must accompany all VB/Win
       programs.

2  What is the current version of the Visual Basic?
       VB/Win is currently at version 3.0

3  Where can I get updated VB and other Microsoft files?
       Microsoft Software Library (MSL) is accessible from the
       following services:

       - CompuServe
           GO MSL
           Search for <filename.EXE>
 
       - Microsoft Download Service (MSDL)
           Dial (206) 936-6735 to connect to MSDL
 
       - Internet (anonymous FTP)
           ftp ftp.microsoft.com
           Change to the \softlib\mslfiles directory
           (There are a LOT of files in this directory!  It is
           not advisable to list all the files.)

4  Where can I get good up-to-date information about VB?
       If you do any VB programming at all, you really should
       get the latest copy of the Microsoft Knowledge Base from
       one of the sources listed above!  The filename is
       VBKB.EXE or VBKB_FT.EXE for the version with full text
       searching.  The Knowledge Base is a Windows help
       formatted document that is updated almost monthly.
       This FAQ is a pretty good source as a digest of many of
       the VB issues that are discussed in the
       comp.lang.basic.visual newsgroup, but as such the
       information contained in this FAQ has not been thoroughly
       tested or verified.
       Dave McCarter puts out a nice Windows help formatted
       document called "Visual Basic Tips and Tricks".  A good
 that isn't found in the
       Knowledge Base.  It can be found at ftp.cica.indiana.edu
       /pub/pc/win3/programr/vbasic/ as VBTIPS??.ZIP, where '??'
       is the version number (yes, get the one with the highest
       number).
       There is presently an effort to put together a VB code
       library so that VB users can share their best - and
       trickiest - programming work.  The code library project
       is being spear headed by Hein Ragas who has managed to
       get a directory on CICA for code snippets to be
       deposited.  Stayed tuned to comp.lang.basic.visual for
       more information.

5  Are there any examples of commercial applications built using
   Visual Basic?
       Profit by Microsoft was written mostly in Visual Basic. 
       In fact, Profit was one of three programs recently
       selected as PC Magazine's Editor's Choice among Windows
       small business accounting packages.



B - COMMON VISUAL BASIC PROGRAMMING QUESTIONS
---------------------------------------------

1  What's the difference between MODAL and MODELESS forms?
   a   MODAL forms are forms which require user input before any
       other actions can be taken place. In other words, a modal
       form has exclusive focus until it is dismissed. When
       showing a modal form, the program pauses at the SHOW
       command until the modal form is either hidden or
       unloaded. The internal MSGBOX and INPUTBOX$ forms are
       examples of modal forms. To show a form modally, use the
       syntax: MyForm.SHOW 1

   b   MODELESS forms are those which are shown but do not
       require immediate user input. Most child forms (in a MDI
       application) are typically modeless. To show a form
       modeless, use the syntax: MyForm.SHOW

2  When/Why should I use Option Explicit?
       Option Explicit forces you to declare all variables
       before using them.  Opinions vary greatly on this
       subject. The main reason to use the OPTION EXPLICIT
       statement at the top of all modules is to minimize the
       amount of bugs introduced into your code by misspelling a
       variable name. Most variants of BASIC (including VB) have
       the capability to create variables 'on the fly' (without
       any declarations). This capability can be a double edged
       sword.

       At the minimum, it is suggested to use the DEFINT A-Z
       statement in leu of OPTION EXPLICIT. This statement will
       cause any variables which are created on the fly to be
       created as integers as opposed to single precision.
       (Integers take up less memory). 

       The OPTION EXPLICIT statement causes VB to 'disable' it's
       ability to create variables on the fly. Thus, all
       variables must be declared using a DIM or REDIM
       statement. All variables not declared will cause an error
       when the OPTION EXPLICIT statement is used. This will
       eliminate any bugs when a variable is misspelled.

3  Is the Variant type slower than using other variable types?
       Generally, yes.  The Variant variable type also increases
       memory overhead.  To test the speed difference, try the
       following piece of code in something like a button_click
       event:

       Dim Va As Variant
       Dim In As Integer
       T1! = Timer
       For i% = 1 To 32766
         Va = i%
       Next i%
       T2! = Timer
       Debug.Print "With variant:  "; Format$((T2! - T1!),
       |"0.0000")
       T1! = Timer
       For i% = 1 To 32766
         In = i%
       Next i%
       T2! = Timer
       Debug.Print "With integer:  "; Format$((T2! - T1!),
       |"0.0000")

       This test shows (on our test system) that integers are
       ~60% faster!  However, for strings there where no real
       difference, or in some instances, variants were faster
       than strings for routines with heavy conversion usage. 
       For the best result in your application, test your
       routines directly.

4  How do I make a text box not beep when I hit the enter key?
       Put "something else" in your _KeyPress event, depending
       on what you really want. This code example makes
       *nothing* happen, for an extended period of time:

       Sub Text1_KeyPress (KeyAscii As Integer)
           If KeyAscii = 13 Then   '13 is Key_Return              
           KeyAscii = 0  '0 (zero) is nothing
           End If
       End Sub

       This might not be a very nice thing to do, since your
       users usually have some intention when they press Enter.
       Usually they will want to jump to the next control, like
       the Tab key does. To have the enter key emulate the Tab
       key action, you will need to change the line 'KeyAscii=0'
       to 'SendKeys "{tab}"' in the example above. 
 
       By the way, you'll also find this in the Microsoft VB
       Knowledge Base (see KB Q85562 ?).  You also be sure to
       set the MultiLine property to False, of course.

5  How do I get the Tab key to be treated like a normal
   character?
       You must set TabStop = False for ALL controls on the
       active form.  Then you will be able to insert "tab"
       characters in controls like the  text box.
       If you feel you need the Tab key to behave "normal"
       outside one specific control, it is trivial to emulate
       its functionality in code:

       Sub Command1_KeyDown (KeyCode As Integer, Shift As
         Integer)
           If KeyCode = 9 Then
               If Shift = 0 Then
                  Command2.SetFocus 'Tab=Next control
               ElseIf Shift = 1 Then
                  Command3.SetFocus 'Shift-Tab=Previous
                  |control
               End If
           End If
       End Sub

6  What is passing by reference?
       Arguments are either passed by reference or by value. 
       When they are passed by value, they cannot be changed by
       the procedure/function they are passed to.  They *can* be
       altered when passed by reference, since passing by
       reference is just passing the address.
       Also note the following nasty trap:  Arguments are passed
       by reference unless enclosed by parentheses or declared
       using the ByVal keyword.  [VBWin Language Ref., p. 55]
 
7  Is there any way to pass a variable to a form apart from
   using global variables?
       While we wait for Microsoft to correct this annoying
       shortcoming, here's a nice "quick & dirty" method:

       The standard workaround is to put an invisible text box
       (or caption or any other control that suits your use.) on
       the target form and access it by Form.textbox = "value". 
       Then you can use the Change event of that control to do
       anything you want in that form.  Also, check out the .Tag
       property which is a "what-you-want" property where you
       can hook any string you want onto a control.  This
       property can also be accessed from other modules.
       [Dave Mitton (mitton@dave.enet.dec.com)]

8  How should dates be implemented so they work with other
   languages/countries formats?
       If you use MM/DD/YY format dates in a program, you will
       get either a runtime-error (ie. month>12) or the wrong
       date (ie. March 12 instead of December 3) when your
       program is used in Europe.  And vice versa, of course. 
       Even Microsoft's own example programs (like the MAPI
       sample) make this stupid mistake.  Use the Format command
       to make sure you get the date you want.  For example:  

       strTodaysDate = Format[$](Now, "Short Date")

       As a side note, Microsoft has taken much heat on the
       newsgroup for VB's bad support for Internationalization!

9  Can a VB application be an OLE server?
       No.  You'll have to use an external DLL/VBX.  If you see
       any examples, please tell the newsgroup.

10 How do I dial a phone number using the MSCOMM VBX in VB Pro?
       The MSCOMM VBX is great for creating communication
       programs, but it's overkill for dialing a phone number. 
       Try the following code:

       PhoneNumber$ = "(123) 456-7890"
       Open "COM2" For Output As #1   'or COM1
umber$ & Chr$(13)
       Close #1

11 I have [several] megabytes of memory. Why do I get an out of
   memory error?
       Unfortunately, Microsoft is more famous for memory
       barriers than anything else.  This is a late descendant
       of the infamous 640K barrier that has been plaguing us
       for years.  Although Windows allows the user to access
       several megabytes of memory, it uses two limited (64K)
       memory areas called User Heap and GDI Heap.  Go to the
       Help|About box in Program Manager to see the percentage
       of free resources in the *most* exhausted heap.  If these
       areas are exhausted, you are out of luck.  VB programs
       are unfortunately rather greedy on these structures. 
       Windows 4 is supposed to free us from this limitation...

12 How do I mimic a toggle button?
       The only "fix" we know for this problem is to use a
       picture or image control to mimic the action of a button
       or button3d control.  You need two bitmaps, one for
       buttonup and one for buttondown.  This is a kludge, we
       know.  Look at the button bar used in the MDINOTE sample
       program supplied with VB for an example of this.

13 How do I get my application on top?
       Set "MyForm.ZOrder = 0".
       Warning: It is consider bad behavior for applications to
       elbow to the top without allowing the user to turn this
       option off.  An appropriate use would be for a "splash
       screen" that comes up to pacify the user while the
       program is loading.



C - ADVANCED VISUAL BASIC PROGRAMMING ISSUES
--------------------------------------------

1  How do I tell when an application executed using the SHELL
   command is finished?

       Shell() doesn't really return a task handle, it returns
       an instance handle.  Any documentation that says
       otherwise is wrong.  But never mind that; the answer to
       your question is to use the API call GetModuleUsage.
 
       'Put this in the general declarations of your form/module
       Declare Function GetModuleUsage Lib "Kernel" (ByVal
       |hModule As Integer) As Integer
 
       'Here's where you shell out to the other program
       intHandle = Shell("PROGRAM.EXE")
       Do While GetModuleUsage(intHandle) > 0
           DoEvents
       Loop

       [Kenn Nesbitt, Microsoft Consulting Services
       (kennn@netcom.com)]

2  How do I access C style strings?
       Use the 'lstrlen' and 'lstrcpy' calls found in the Kernel
       DLL.

3  How can I change the printer Windows is using in code without
   using the print common dialog?
       You can change the printer the VB 3.0 Printer object is
       pointing to programmatically (without using the common
       dialogs).  Just use the WriteProfileString API call and
       rewrite the [WINDOWS],  DEVICE entry in the WIN.INI file! 
       VB will instantly use the new printer, when the next
       Printer.Print command is issued. If you get the old
       printer string before you rewrite it (GetProfileString
       API call), you can set it back after using a specific
       printer.  This technique is especially useful, when you
       want to use a FAX printer driver: Select the FAX driver,
       send your fax by printing to it and switch back to the
       normal default printer.
       [Hajo Schmidt (hajo@bwl.bwl.th-darmstadt.de)]

       It is recommended (and polite, as we're multitasking) to
       send a WM_WININCHANGE (&H1A) to all windows to tell them
       of the change.  Also, under some circumstances the
       printer object won't notice that you have changed the
       default printer unless you do this.
 
       Declare Function SendMessage(ByVal hWnd As Integer,
       |ByVal wMsg As Integer, ByVal wParam As Integer,
       |lParam As Any) As Long
       Global Const WM_WININICHANGE = &H1A
       Global Const HWND_BROADCAST = &HFFFF
       ' Dummy means send to all top windows.
 
       ' Send name of changed section as lParam.
       lRes = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0,
       |ByVal "Windows")

       [Nic Gibson (nic@skin.demon.co.uk)]

 
4  I'm adding lots of features to a LISTBOX, but it's sloooooow.
   What can I do to speed it up?
       The basic problem with listboxes is that VB forces a
       repaint every time you call AddItem. You can get around
       this by switching off painting and then using
       LB_ADDSTRING messages to add items. If you want a code
       sample mail me and I'll get one from one of our apps. 
       [Nic Gibson (nic@skin.demon.co.uk)]

5  How do you make a TEXTBOX read only?. Or, how do I prevent
   the user from changing the text in a TEXTBOX?
       There's a lot of ideas on this one. You can grab the
       _KeyPress and _KeyDown events and set them to zero.
       However, the best idea is to use the Windows API
       SendMessage function to tell the control to become
       read-only:

       'After making the following declarations...
       Global Const WM_USER = &H400
       Global Const EM_SETREADONLY = (WM_USER + 31)
       Declare Function SendMessage Lib "User" (ByVal hWnd As
       |Integer ByVal wMsg As Integer, ByVal wParam As
       |Integer, lParam As Any) As Long 
       'Then Try:
       SendMessage(Text1.hWnd, EM_SETREADONLY, 1, 0)
       [Pete Jones (pjones@csi.compuserve.com)]

6  How much gain in performance will I gain if I write my number
   crunching routines in C instead of in basic?
       Probably the best solution to the number crunching
       problem is to write the number crunching routines as a
       custom control or a DLL, and plug it into a VB app.  VB
       interface handling is not significantly slower than, say
       C++, and most of the wait is associated with Windows. 
       Some real world experience speaks volumes about this one:

       I wrote some time consuming code in VB to solve a
       combinatorical (does this word exist in English?)
       problem. The code consists of one main recursive
       function, which calls itself very often. It took a night
       to compute a certain problem. I was rather disappointed
       and then decided to write the central routine in C++. It
       was a 1:1 transcription.  The routine was compiled with
       the MS C++-Compiler.  It took only 22 Minutes for the
       same problem.  Amazing, isn't it? The routine doesn't do
       any floating point arithmetic, only integer, and handles
       some arrays.  The PC was a 33MHz 486.  And the second
       amazing thing is, that a IBM RS6000 (560)-Risc-machine
       needed 17 Min for the same code. I was the only one on
       the machine.  I though, it should be much faster. The MS
       C++ seems to make very fast, optimized code. The
       optimization was configured to make fast code.  
       [Christoph Steinbeck (steinbeck@uni-bonn.de)]

7  How can I create a VBX?
       VBXs are usually written is C (Borland, VC++).  You
       should refer to the _Control Development Guide_ (in VB
       Professional Features Vol. I) and any relevant
       documentation for your compiler.  Followup questions
       should be directed to comp.lang.c.*.

8  How do you change the system menu (on the Control-Menu Box)?
       You can turn off the minimize and maximize menu options
       by changing properties, but what if you're doing
       something critical in your VB program that should not be
       interrupted and you need to remove the "close" option?

       'Make the following declares.
       Declare Function GetSystemMenu Lib "User" (ByVal hWnd
       |As Integer, ByVal bRevert As Integer) As Integer
       Declare Function RemoveMenu Lib "User" (ByVal hMenu
       |As Integer, ByVal nPosition As Integer, ByVal wFlags As
       |Integer) As Integer
       Global Const MF_BYPOSITION=&H400

       'Use the following code to remove the "close" option.
       SystemMenu% = GetSystemMenu (hWnd, 0)
       Res% = RemoveMenu(SystemMenu%,6, MF_BYPOSITION)
       Res% = RemoveMenu(SystemMenu%,6, MF_BYPOSITION)
       'also remove the separator line

       Check out the GetMenuID and InsertMenu API functions to
 

9  How do I play MID, WAV or other multimedia files?
       Use the MSMCI.VBX, provided with VB/Win Pro 3.0.  You can
       also declare and call the MM-functions manually:

       Declare Function mciExecute Lib "MMSystem"
       |(ByVal FileName as String) As Integer

       Sub Form1_Click ()
           iResult = mciExecute("Play c:\windows\mkmyday.wav")
       End Sub

10 How can I call a 'hidden' DOS program from VB?
       If you run a DOS program minimized using the SHELL
       command, it will never return control to your VB program. 
       This is because DOS tasks by default are NOT setup to run
       in the background.  The easiest way to get around this is
       to make a PIF file for the program you need to run with
       the "Background" option checked.  Then SHELL to the PIF
       file to run the DOS program and it will return control to
       your VB application when it terminates.

11 How do I do drag & drop between applications?
       Get the file FMDROP10.ZIP from ftp.cica.indiana.edu in
       the vbasic directory.  It is a good VB example of drag &
       drop.  You may also want to get the MSGBLAST VBX (3-
       64.ZIP at ftp.microsoft.com in the MSDN directory) since
       you will need to have access to Windows messages in order
       to do drag & drop - unless you get a VBX to do it for
       you.
       Also, the D&DSERVE example from Windows Tech Journal Aug
       92 includes a DLL for this purpose. This is available
       from some ftp sites.
       Drag & Drop Client: the form you drop objects to/on
       Drag & Drop Server: the form you drag object(s) from

12 How do I use GetPrivateProfileString to read from INI files?
       There's a good example of accessing *.INI files in the
       Knowledge Base, but here's the basic idea:

       'You declare these API function as usual:
       Declare Function GetPrivateProfileString Lib "Kernel"
       |(ByVal lpApplicationName As String, ByVal lpKeyName
       |As Any, ByVal lpDefault As String, ByVal
       |lpReturnedString As String, ByVal nSize As Integer,
       |ByVal lpFileName As String) As Integer

       'Then in your code you do like below:
       strIniFile = "WIN.INI"
       strSection = "MyProgram"
       strKey = "Language"
       strDefault = "English"
       iLength = 70
       strReturn = String$(iLength, " ")  'Pad the string first!
       iResult = GetPrivateProfileString(strSection, strKey,
       |strDefault, strReturn, iLength, strIniFile)

       Also, be aware that there was an error in the Windows 3.1
       API documentation that came with VB.  Here's the scoop:

       Knowledge Base article q110826 (DOCERR:
       GetPrivateProfileString Declaration Incorrect in API
       corrects a documentation error for the
       GetPrivateProfileString function call as described in the
       Windows version 3.1 API Reference help file that shipped
       with Microsoft Visual Basic version 3.0 for Windows. The
       correct declaration is as follows:
 
       Declare Function GetPrivateProfileString Lib "Kernel"
       |(ByVal lpApplicationName As String, ByVal lpKeyName
       |As Any, ByVal lpDefault As String, ByVal
       |lpReturnedString As String, ByVal nSize As Integer,
       |ByVal lpFileName As String) As Integer
 
       Note that the "ByVal" keyword was omitted from the second
       parameter in the online reference. This means that the
       function is passing the second parameter (lpKeyName) by
       reference. It needs to be passed by value.
 
       The most common problem that occurs when using the
       incorrect declaration is that when the function is
       called, it returns a copy of "lpdefault" in the
       "lpReturnedString" parameter instead of the actual value
       referenced by KeyName.

13 How do I speed up control property access?
       Instead of using a property in a loop, you will be better
       off using a normal variable in the loop and then assign
       the variable once to the property afterwards.  Also, when
       reading a property, you should read it once into a
       variable instead of using it in a loop.
       Sometimes it is not possible to simply put contents of a
       property into a variable.  For example, if you are using
       a list box or you need to conserve memory.  In these
       cases you can send the WM_SetRedraw message to the
       control to prevent redrawing.  You can typically increase
       the speed 6-10 times - or even more.

       'Add the following declares:
       Declare Function SendMessage Lib "User" (ByVal hWnd As
       |Integer, ByVal wMsg As Integer, ByVal wParam As
       |Integer, lParam As Any) As Long
       Const WM_SetRedraw = &HB

       'Add this to your code:
       Result% = SendMessage(Text1.hWnd, WM_SetRedraw, 0, 0)
       'redraw off
       'Do your stuff here!
       Result% = SendMessage(Text1.hWnd, WM_SetRedraw, 1, 0)
       'redraw on

   This same method applies to list boxes and other controls.

14 How do I implement Undo?
       For most controls, you will have to keep track of changes
       yourself. However, if you use the standard Text box or
       Combo box, Windows provides a "free" undo function for
       you!

       'Do the following declares:
       Declare Function SendMessage Lib "User" (ByVal hWnd As
       |Integer, ByVal wMsg As Integer, ByVal wParam As
       |Integer, lParam As Any) As Long
       Global Const WM_USER = &h400
       Global Const EM_UNDO = WM_USER + 23

       'And in your Undo Sub do the following:
       UndoResult = SendMessage(myControl.hWnd, EM_UNDO,
       |0, 0)
       'UndoResult = -1 indicates an error.

15 How do I create a window with a small title bar as in a
   floating toolbar?
       Download the MSGBLAST VBX from ftp.microsoft.com
       (filename "8-3.ZIP") or TBOX100.ZIP from
       ftp.cica.indiana.edu.  These files provide an example of
       a form with a small title.  When you see it, you'll
       understand why we haven't include a full explanation
       here!



D - CALLING THE WINDOWS API AND DLLs IN GENERAL
-----------------------------------------------

1  What is the Windows API?
       The Windows API is a collection of Dynamic-Link Libraries
       (DLLs) that do most of the common things in Windows. 
       Calls to the Windows API gives you access to routines
       that do things like drawing menu bars, manipulating
       bitmaps, playing sound files, and pretty much every other
       function of Windows.

2  How do I call a DLL?
       Basically, you declare a DLL procedure which you can call
       in your VB program which in turn passes data to and/or
       retrieves data from the DLL.  You should read the section
       of the VB manual that talks about calling DLLs ("Chapter
       24  Calling Procedures in DLLs" in the VB 3.0
       Programmer's Guide).  This chapter covers the basics of
       using the Windows API DLLs and calling DLLs in general. 
       Beyond that you may want to find a good book on this
       subject since it is too large to cover here (see the Book
       Listing in the Appendix of the General FAQ - Part 1). 
       Don't be too intimidated!  Using DLLs (especially many of
       the Windows API functions) is quite easy, once you learn
       how to call them.  In fact, many of the newer DLLs
       include VB-compatible modules!

3  What about DLL calls that require callbacks?
       Dan Appleman's "Visual Basic Programmer's Guide to the
       Windows API" comes with a floppy disk which code samples
       and tools.  It also includes a VBX which supports the
       callbacks which many API calls require.  Dan is also
       founder and president of Desaware which sells more
       extensive tools, including SpyWorks, for VB developers.
       [Walter Hill (whill@netcom.com)]

4  Tips for calling DLLs (such as the Windows API)
   a   Using the BYVAL keyword is critical. Using it when you're
       supposed to call by reference and (more common) not using
       it when you are to give a value to the external function
       are the single most common mistakes. Wrong calling
lt in a General Protection Fault
       (GPF) or, even worse, corruption of another applications
       data.
   b   Check return and parameter types. For return types, a C
       function declared as "void" means you use a Sub not a
       Function.
   c   Initialize strings! If you pass a string that is too
       short to the API it will happily write past the end of
       the string and possibly corrupt data.
   d   Use Option Explicit. A typing error that results in a bug
       in the VB source will occasionally cause a GPF when you
       call external code.
   e   It's a jungle out there. Check parameter values as there
       is no type checking outside VB. If you make a mistake,
       you'll often get a GPF.
   f   Save before you run. You may even need to restart Windows
       after a GPF, since DLL's often aren't unloaded properly.


E - VISUAL BASIC AND DATABASES
------------------------------

1  Why can't I use an index with my VB accessed database?
       There is a mistake in the docs which says you can set the
       active index for a recordset.  You can't.  The data
       control uses the primay key for tables and physical order
       (I think) for dynasets.
       [Nic Gibson (nic@skin.demon.co.uk)]
 
2  Why does my compiled VB database app generate an error when
   it ran just fine in the design environment?
       You can thank Microsoft for documenting this topic so
       poorly.  When you compile your VB database application,
       you must also have an INI file for it which provides the
       correct pointers to the appropriate database drivers.
       Therefore, if your application is named "INVOICE.EXE",
       you will need to have a properly configured "INVOICE.INI"
       file in your Windows directory.  The file, EXTERNAL.TXT,
       that came with VB should explain all about it.

3  Is the Access Engine and Visual Basic Pro good enough for
   database work?
       That, of course, depends.  Generally the answer is "yes",
       but you may need some third-party add-on products.

       These are the major weaknesses of VBPro's database
       functions:
        -  Limited data controls: No add, delete or search
           button; no bound list box or masked edit control and -
           the worst - no bound grid!
        -  No run-time query builder ("how good is your user in
           SQL?") or report builder.
        -  No direct advanced control of the Access 1.1 Database
           Engine.

       The good news is that lots of companies are willing to
       sell you products which address one or more of the above
       weaknesses.
       Also, if you build a database application with advanced
       database relations, it can be a good idea to build the
       database with Access and the front-end with VB.

4  How do you avoid the "Invalid use of null" error when reading
   null values from a database?
       If you try to retrieve a null value (empty field) from a
       database, you will get the error: "Invalid use of Null". 
       Here is one way to get around this problem:

       I've worked around this problem with the following code:
       TextBox.Text = MyTest.Fields("TestFld") & ""
       This code converts the Null-Value into an empty string.
       [Ralf Metzing (rmm@dragon.stgt.sub.org)]


 
F - DISTRIBUTING VISUAL BASIC APPLICATIONS
------------------------------------------

1  What are some tips for using Setup Wizard?
   a   There were some bugs in the setup utilities supplied with
       VB.  Be sure to get the newest version of SETUPKIT
       (usually called SETUPK.EXE or ZIP).  It is available from
       the sources listed in Section VIII of the General FAQ
       (Part 1).  Alternatively, if you have the older versions,
       you may have to manually remove the line referring to
       OLE2UI.DLL in the file SETUPWIZ.INI.  Here is the latest
       information on the Setup Wizard files as of 4/94:

           File        Current Size/Date     Orginal Size/Date
       ------------    -----------------     -----------------
       SETUP    EXE     19,056  08-23-93      15,312  04-28-93
       SETUP1   BAS     27,268  10-14-93      26,452  04-28-93
       SETUP1   FRM     15,341  01-21-94      16,331  04-28-93
       SETUP1   FRX        770  01-21-94         770  04-28-93
       SETUPK   TXT     16,933  03-07-94                n/a
       SETUPWIZ EXE    153,486  02-01-94     150,670  04-28-93
       SETUPWIZ INI      3,844  02-18-94       3,638  04-28-93
 
       Follow the instructions in SETUPK.TXT exactly.  The files
       actually belong in two separate directories.  Not placing
       them correctly can create strange and unusual side
       effects -- none of them good(!)

   b   Set all involved EXE, DLL and CVX files to Read-Only so
       that the setup program doesn't modify them.
       [Charles F. Mulks (21667cfm@msu.edu)]
   
2  Are there restrictions on what I can distribute with my VB
   program?
       The documentation tells what parts of the Visual Basic
       kit you can freely distribute: the VBX files, some DLL's
       and what the SetupKit includes on your distribution
       diskettes.  Reading software license agreements may be
       more boring than asking the newsgroup, but is
       nevertheless a good idea. 8^)
       There have been some rumors on the newsgroup that you
       can't redistribute programs written with VB freely.  This
       is nonsense.  All applications created with VB can be
       redistributed freely without royalties (as long as you
       don't distribute proprietary external files).
       The rumors probably originated when Microsoft announced
       that they will not sell kits allowing third-party
       software to include the Visual Basic for Applications
       (VBA) system.



G - MISCELLANEOUS TIPS AND INFORMATION
-------------------------------------

1  "Clean up" your project before compiling.
       When you are ready to compile your VB project into your
       'finished' EXE, be sure to save the project files, exit
       VB, run VB, load your project and go straight to
       compiling.  Otherwise, your EXE will be larger in file
       size than necessary due to 'garbage' getting included in
       the EXE.  For some reason, VB does not fully clean up all
       of the previously used variables or objects that you may
       have been playing with while developing your program so
       these get included in your EXE even though they aren't
       used.  Other VB users have even advocated saving all the
       project files as ASCII, then loading the ASCII files
       before compiling to further "clean up" the resulting EXE
       file.

2  Multiple END statements can be dangerous.
       Suggestion: put the end statement used to exit your
       program *only* in the Form_Unload event of the main form. 
       Whenever you want to end the program, just tell the main
       form to unload.

3  What are the latest versions of the various files used by VB?

         File to        Updated
Date     Download       Files             Description
---------------------------------------------------------------
3/7/94   BTR110.EXE    BTRV110.DLL   Btrieve IISAM Driver
3/7/94   DATAINDX.EXE  DATAINDX.DOC       Index for the "Data
                                          Access Guide"
3/7/94   GENRIC.EXE    \VB\CDK\GENERIC    Sample custom control
                                          source code
3/7/94   VBGRID.EXE    GRID.VBX           Grid control
3/7/94   VBHC505.EXE   HC.EXE and         Standard and Protected
                       HCP.EXE            mode WinHelp Compiler
3/7/94   MSAJT.EXE     MSAJT110.DLL       Microsoft Access
                                          Database Engine
3/8/94   MSCOMM.EXE    MSCOMM.VBX         Serial Communications\
                                          control
3/7/94   ORA110.EXE    ORACLE.TXT         Updated ORACLE.TXT file
3/7/94   SETUPK.EXE    SETUP.EXE          Setup Toolkit
3/7/94   VBRUN300.EXE  VBRUN300.DLL       Visual Basic Runtime
                                          Library
3/7/94   XBS110.EXE    XBS110.DLL         XBase IISAM Driver
 
       There is an article in the Microsoft Knowledge Base that
       points to each of these files and provides more detailed
       information about the update.  To find these articles,
       query the Microsoft Knowledge Base using the file name
       and the word "update3.00".
