Dialog Boxes    
      Formatting Functions     
      Formatting Date and Time
      Procedures
      Code which runs in response to a click or other event is  an event procedure, or sometimes called a routine. If you have code  segments, which you want to run in more than one event, it's a good idea to  store them in general procedures. You can then run these procedures when  needed with one line of code. 
        General procedures will... 
      
        - ...save keystroke time. 
 
        - ...reduce the size of your program. 
 
      
      ...make debugging easier.
      Most programmers create their own library of general procedures, which can be used in any of their applications. 
The only difference between event procedures and general  procedures is the way they are called. Codes in event procedures are called by  internal Windows messages; codes in general procedures are called specifically  by you, the programmer. 
      Private and Public Subs
              You may have noticed that event procedures always start  with Private Sub. Private means that code in other modules cannot call the  procedure. On the other hand, a Public Sub can be called from anywhere in the  project. When creating procedures, Public is the default and the actual Public  keyword is not required. 
        Tip: If needed, you can convert your event procedures to  Public and call them from other Forms or Modules. 
      Public Sub cmdOK_Click()
           'Code segment
      End Sub
      Call the event procedure:
      cmdOK_Click
      Add Procedure Window
              Open the module where the procedure will be located, then  select Tools/Add Procedure to bring up the Add Procedure window,  where you can name your new procedure, decide between Public and Private, Sub  or Function, and whether to use all Static variables. Two more choices  (Property and Event procedures) are advanced procedures used with Class Modules. 
        If you have a procedure which would only be associated  with one Form, then writing it in the form (.FRM file) would be OK, but most of  the time you'll write it in a .BAS file (code module) which is part of your  project. You never know when you might want to reuse the procedure. 
        Follow the variable naming rules when naming procedures. 
        Once you click OK, you are whisked to the code window for  your new procedure where End Sub (or Function) and some empty parentheses have  been added automatically. 
        So what are the empty parentheses for? You can optionally  send data to the procedure in the form of arguments. Arguments are the  additional information that a procedure needs to complete itself. Like  variables, arguments are of a certain data type and must be written into the  procedure as such. 
      Public Sub FindReplace(ByRef sSearchString$, _ByVal sFindWhat$, ByVal sReplaceWith$)
      Dim iPos As Integer, iStart As Integer
      iStart% = 1
      Do
          'Find beginning position 
          iPos% = InStr(iStart%, sSearchString$, sFindWhat$)
          'If not there, then get out 
          If iPos% = 0 Then Exit Do
          'Combine left portion, new string, and right portion 
          sSearchString$ = Left(sSearchString, iPos% - 1) & sReplaceWith$ & _
             Right(sSearchString$, Len(sSearchString$) - iPos% - Len(sFindWhat$) + 1)
          'Calculate where to begin next search 
          iStart% = iPos% + Len(sReplaceWith$)
      Loop
      End Sub
      This Find and Replace procedure requires three  strings to be sent to it in order to run properly. This is called passing  arguments. You then use the arguments in the code just like variables. 
      ByVal and ByRef
              Arguments are passed "by value", or "by  reference". ByRef is the default and can be omitted. 
        It's popular opinion that ByVal should be the default  because most of the time you just want to use the value of the variable in the procedure, rather than the actual variable. If you specifically  want the procedure to change the value of an argument (as the above procedure  did), then use ByRef, otherwise stick the ByVal keyword in front of your  arguments. 
        Call the procedure by simply writing its name and its  arguments in the correct order. Separate the arguments with commas. Parentheses  are not required with a Sub procedure. 
      FindReplace myOriginalString$, myStringToReplace$, myNewString$ 
      
Be sure to send the right data types for the arguments.  Once the procedure has run, program execution is returned to the very next line  in the procedure that called it. 
      Call statement
              The Call statement is optional and is used less and less  all the time. If you want a visual clue to indicate that this line of code is  calling a separate procedure, then by all means include it. If you do use Call,  you must enclose the arguments in parentheses. 
      Call FindReplace(myOriginalString$, myStringToReplace$, myNewString$) 
      
By now, you know that Visual Basic has many built-in  methods such as the AddItem method of a ListBox. A VB method simply performs an  action by running a built-in code segment. Sub procedures are methods which you  define, thereby expanding VB's capability. Hold on, don't methods have to be  associated with an object? Yes, the Sub procedures you write are methods of the  object you place them in, whether a Form or Module. 
        Assuming you've written the above Sub procedure in a Form  named frmMain, you could actually call the procedure like this: 
      frmMain.FindReplace myOriginalString$, myStringToReplace$, myNewString$
      
On the other hand, VB has  many built-in numeric, string and boolean functions. You can further expand  this collection of functions by writing your own Function procedures, which are  also considered to be Methods.
      Function Procedures
              You know that a function produces a result and when using  one of VB's functions you put the result in a variable or property of an  object. The same is true of Function procedures. 
        Create your Function procedure in the Add Procedure  Window, write in any arguments and then declare what data type the result of  the function will be. 
      Public Function GetERA(ByVal iIP As Single, ByVal iER As Integer) As Single
          GetERA = Format(iER% * 9 / iIP!, "##.00")
      End Function
      This is a simple function which takes two arguments to  produce a baseball pitcher's Earned Run Average and returns the result to the  procedure that called it. Somewhere in the code (usually the last line) you  have to assign a value to your function. This function could be called like  this: 
      Dim sinERA As Single
      sinERA! = GetERA(123.333, 54)
      You may decide to use a Function even if the only value  you need returned is whether the function was successful or not. 
      Public Function FolderToFloppy(sFolder As String) As Boolean
          On Error GoTo FunctionFailed
          Dim sFile As String
          If Right(sFolder$, 1) <> "\" Then sFolder$ = sFolder$ & "\"
          sFile$ = Dir(sFolder$ & "*.*")
          Do While sFile$ <> ""
      FileCopy sFolder & sFile$, "A:\" & sFile$
      sFile = Dir
          Loop
          FolderToFloppy = True
          Exit Function
          FunctionFailed:
        End Function
        'Note: some computers may not use A: 
            as the floppy drive letter. Look into 
        the GetDriveType API 'function. 
                  This function takes a folder as an argument and copies all  it's files to the floppy drive. The argument is passed by reference because we  check for a trailing backslash. If an error occurs, the function terminates. 
        Calling this function might be done like this: 
      If Not FolderToFloppy(App.Path) Then
           MsgBox "Error copying files to floppy"
      End If
      Note: Creating a new general procedure can also be done by  going to the general declarations section of the form or code module and typing Sub (procedure name) and pressing enter. End Sub and some empty  parentheses are added automatically. This new procedure doesn't actually exist in general declarations, it can just be initially written there. 
      Passing arrays to procedures
              Note: VB 6.0 can now return an array from a function.  Personally, I haven't found a use for this new trick yet 
        A Function procedure returns just one value, it cannot  return an array of values. The work-around to this is to pass an entire array  to a procedure as an argument. An array is passed with empty parentheses and  always ByRef. 
      'A simple procedure which doubles 
      'the arguments passed to it 
      Public Sub DoubleThem(myArray() As Integer)
          Dim i As Integer
          For i% = LBound(myArray) To UBound(myArray)
              myArray(i%) = myArray(i%) * 2
          Next i%
      End Sub
      'Passing an array to this procedure 
      Dim myArray(1 To 3) As Integer
      myArray(1) = 34
      myArray(2) = 57
      myArray(3) = 123
      DoubleThem myArray()
      The values in the variable array change to 68, 114, and 246. 
      Passing objects to procedures
              Forms, controls, and other objects can also be passed to  procedures as arguments. The type of the object is written into the procedure  rather than a standard data type. The following Sub procedure adds an item to a  ListBox only if the item doesn't already exist. 
      Public Sub AddItemNoDuplicates(ByVal lst As ListBox, ByVal sItem As String)
      Dim i As Integer
      For i% = 1 To lst.ListCount - 1
          If sItem$ = lst.List(i%) Then
              MsgBox "This item already exists in the list", _
                    vbInformation, "Duplicate found"
              Exit Sub
          End If
      Next i%
      lst.AddItem sItem$
      End Sub
      'Using the procedure 
      AddItemNoDuplicates lstItems, "New Item"
      You could make this procedure work with both ListBoxes and  ComboBoxes by specifying the generic type Control instead of a specific control  type. 
      Public Sub AddItemNoDuplicates(ByVal ctl As Control, ByVal sItem As String)
      
Parent and Container properties
              When passing a control as an argument, you can access that  control's Form or Container with these properties. The procedure below frames a  control when it gets the focus. 
      Public Sub FrameOnFocus(ctl As Control)
      Dim l As Integer, t As Integer, w As Integer, h As Integer
      l% = ctl.Left - 4
      t% = ctl.Top - 4
      w% = ctl.Left + ctl.Width + 8
      h% = ctl.Top + ctl.Height + 8
      With ctl.Parent
          .DrawWidth = 4
          .Cls
      End With
      'Can't use Line method in a With block 
      ctl.Parent.Line (l%, t%)-(w%, h%), 0&, B
      End Sub
      'Call FrameOnFocus in each control's GotFocus event 
      Private Sub txtCity_GotFocus()
          FrameOnFocus txtCity
      End Sub
      The Container property would be used to access the control's  PictureBox or Frame container. If the control is not contained by a container  control, this property returns the Form. 
        Here's a goofy little procedure which takes a Form as an  argument and shrinks it just before unloading. 
      Public Sub DissolveForm(ByVal frm As Form)
        With frm
        Do Until .ScaleHeight < 2
      .Height = .Height - 100
      .Width = .Width - 100
      .Left = .Left + 50
      .Top = .Top + 50
      DoEvents
        Loop
        End With
        End Sub
        'Best called from QueryUnload
        DissolveForm Me
      The Me keyword is a  built-in global variable which is used to pass the current instance of a Form  to a procedure. Me is intended to be used when you have multiple Form  instances, but you will see programmers using it as shortcut to writing a  Form's name.
    
      Dialog Boxes    
      Formatting Functions     
      Formatting Date and Time