Mircosoft Visual Basic


Don't write that declare!

When you use the Windows API, you should never need to write your own Declare statement. The API Text Viewer utility loads in a text file (WIN31API.TXT for 16-bit, and WIN32API.TXT for 32-bit) and lets you copy declares, global constants, and user-defined types. You can also convert the text file to an Access database for faster searching.


Dragging items from one list to another

Here's a way that you can let users drag items from one list and drop them in another one.

Create two lists (lstDraggedItems, lstDroppedItems) and a text box (txtItem) in a form (frmTip).

Put the following code in the load event of your form.


Private Sub Form_Load()
    ' Set the visible property of txtItem to false
    txtItem.Visible = False
    'Add items to list1 (lstDraggedItems)
    lstDraggedItems.AddItem "Apple"
    lstDraggedItems.AddItem "Orange"
    lstDraggedItems.AddItem "Grape"
    lstDraggedItems.AddItem "Banana"
    lstDraggedItems.AddItem "Lemon"
    '
End Sub

In the mouseDown event of  the list lstDraggedItems put the following code:


Private Sub lstDraggedItems_MouseDown(Button As Integer, Shift As Integer,
X As Single, Y As Single)
    '
    txtItem.Text = lstDraggedItems.Text
    txtItem.Top = Y + lstDraggedItems.Top
    txtItem.Left = X + lstDraggedItems.Left
    txtItem.Drag
    '
End Sub

In the dragDrop event of the list lstDroppedItems put the following code:


Private Sub lstDroppedItems_DragDrop(Source As Control, X As Single, Y As
Single)
    '
    If lstDraggedItems.ItemData(lstDraggedItems.ListIndex) = 9 Then
        Exit Sub
    End If
    ' To make sure that this item will not be selected again
    lstDraggedItems.ItemData(lstDraggedItems.ListIndex) = 9
    lstDroppedItems.AddItem txtItem.Text
    '
End Sub

Now you can drag items from lstDraggedItems and drop them in LstDroppedItems.

Note that you cannot drag from the second list to the first. Also, the dragged item remains in the first list. You'll have to address those limitations yourself.


Quick Custom Dialogs for DBGrid Cells

It's easy to add custom input dialogs to al the cells in the Microsoft Data Bound Grid control.

First, add a DBGrid control and Data control to your form. Next, set the DatabaseName and RecordSource properties of the data control to a valid database and table ("biblio.mdb" and "Publishers" for example). Then set the DataSource property of the DBGrid control to Data1 (the data control).

Now add the following code to your form.


' general declaration area
Dim strDBGridCell As String


Private Sub DBGrid1_AfterColEdit(ByVal ColIndex As Integer)
    '
    DBGrid1.Columns(ColIndex) = strDBGridCell
    '
End Sub

Private Sub DBGrid1_BeforeColEdit(ByVal ColIndex As Integer, ByVal KeyAscii
As Integer, Cancel As Integer)
    '
    strDBGridCell = InputBox("Edit DBGrid Cell:", , DBGrid1.Columns(ColIndex))
    '
End Sub

Now whenever you attempt to edit any cell in the DBGrid, you'll see the InputBox prompt you for input. You can replace the InputBox with any other custom dialog you wish to build.


Using the Alias Option to Prevent API Crashes

A number of Windows APIs have parameters that can be more than one data type. For example, the WinHelp API call can accept the last parameter as a Long or String data type depending on the service requested.

Visual Basic allows you to declare this data type as "Any" in the API call, but this can lead to type mismatch errors or even system crashes if the value is not the proper form.

You can prevent the errors and improve the run-time type checking by declaring multiple versions of the same API function in your program. By adding a function declaration for each possible parameter type, you can continue to use strong data type checking.

To illustrate this technique, add the following APIs and constants to a Visual Basic form. Notice that the two API declarations differ only in their initial name ("WinHelp" and "WinHelpSearch") and the type declaration of the last parameter ("dwData as Long" and "dwData as String").


' WinHelp APIs
Private Declare Function WinHelp Lib "user32" Alias "WinHelpA" (ByVal hwnd
As Long, ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal dwData
As Long) As Long
Private Declare Function WinHelpSearch Lib "user32" Alias "WinHelpA" (ByVal
hwnd As Long, ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal
dwData As String) As Long
'
Private Const HELP_PARTIALKEY = &H105&
Private Const HELP_HELPONHELP = &H4
Private Const HelpFile = "c:\program files\devstudio\vb5\help\vb5.hlp"

Now add two command buttons to your form (cmdHelpAbout and cmdHelpSearch) and place the following code behind the buttons. Be sure to edit the location of the help file to match your installation of Visual Basic.


Private Sub cmdHelpAbout_Click()
    '
    WinHelp Me.hwnd, HelpFile, HELP_HELPONHELP, &H0
    '
End Sub

Private Sub cmdHelpSearch_Click()
    '
    WinHelpSearch Me.hwnd, HelpFile, HELP_PARTIALKEY, "option"
    '
End Sub

When you press on the HelpAbout button, you'll see help about using the help system. When you press on the HelpSearch button, you'll see a list of help entries on the "option" topic.


Add Dithered Backgrounds to your VB Forms

Ever wonder how the SETUP.EXE screen gets its cool shaded background coloring? This color shading is called dithering, and you can easily incorporate it into your forms. Add the following routine to a form:


     Sub Dither(vForm As Form)
     Dim intLoop As Integer
         vForm.DrawStyle = vbInsideSolid
         vForm.DrawMode = vbCopyPen
         vForm.ScaleMode = vbPixels
         vForm.DrawWidth = 2
         vForm.ScaleHeight = 256
         For intLoop = 0 To 255
           vForm.Line (0, intLoop)-(Screen.Width, intLoop - 1), RGB(0, 0,
255 -intLoop), B
         Next intLoop
     End Sub

Now, add to the Form_Activate event the line:


     Dither ME

This version creates a fading blue background by adjusting the blue value in the RGB function. (RGB stands for Red-Green-Blue.) You can create a fading red background by changing the RGB call to:


     RGB(255 - intLoop, 0, 0).


Use FreeFile to Prevent File Open Conflicts

Both Access and VB let you hard code the file numbers when using the File Open statement. For example:


     Open "myfile.txt" for Append as #1
     Print #1,"a line of text"
     Close #1

The problem with this method of coding is that you never know which file numbers may be in use somewhere else in your program. If you attempt to use a file number already occupied, you'll get a file error. To prevent this problem, you should always use the FreeFile function. This function will return the next available file number for your use. For example:


     IntFile=FreeFile()
     Open "myfile.txt" for Append as #intFile
     Print #intFile,"a line of text"
     Close #intFile


Confirm Screen Resolution

Here's a great way to stop the user from running your application in the wrong screen resolution. First, create a function called CheckRez:


Public Function CheckRez(pixelWidth As Long, pixelHeight As Long) As Boolean
    '
    Dim lngTwipsX As Long
    Dim lngTwipsY As Long
    '
    ' convert pixels to twips
    lngTwipsX = pixelWidth * 15
    lngTwipsY = pixelHeight * 15
    '
    ' check against current settings
    If lngTwipsX <> Screen.Width Then
        CheckRez = False
    Else
        If lngTwipsY <> Screen.Height Then
            CheckRez = False
        Else
            CheckRez = True
        End If
    End If
    '
End Function

Next, run the following code at the start of the program:


    If CheckRez(640, 480) = False Then
        MsgBox "Incorrect screen size!"
    Else
        MsgBox "Screen Resolution Matches!"
    End If


Quick Text Select On GotFocus

When working with data entry controls, the current value in the control often needs to be selected when the control received focus. This allows the user to immediately begin typing over any previous value. Here's a quick subroutine to do just that:


Public Sub FocusMe(ctlName As Control)
    '
    With ctlName
        .SelStart = 0
        .SelLength = Len(ctlName)
    End With
    '
End Sub

Now add a call to this subroutine in the GotFocus event of the input controls:


Private Sub txtFocusMe_GotFocus()
    Call FocusMe(txtFocusMe)
End Sub