Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
XML RSS Feed
Tips & Tricks
These are brief tips and tricks that can make Visual Basic programming easier.
New Control Usage Numerical Stuff
Starting & Stopping I/O Bug Alerts
Software Engineering Printing System Issues
Graphics Coding Techniques Other Programs
Databases Misc Forms
Web

Coding Techniques

Enhancing the Editor
(By Gregory Hampton)
I don't know if this will be as much use but one thing that I find difficult to see are VB Comments. VB defaults the comment lines to a pale green. I have found a preference to have the comments scream at me telling me what is going to happen or what should happen. The way that I do this is to change the comment text format to black text on a yellow background. It really makes the comments stand out in the code window. It also has the ability to make it immediately obvious that you don't have enough comments in the code. For those who are not aware, you can change the text properties by selecting Tools/Options, then click the Editor Format tab, and change the text format for several options.
ByVal Arrays
Visual Basic only lets you pass arrays ByRef not ByVal. The reason is performance. When you pass a parameter ByVal, the system makes a copy of the parameter and passes the copy to the new routine (sort of). Then if the routine modifies the copy, the change is not seen in the original parameter.

That's no big deal for integers, doubles, and other "small" types. It can be a bit of an issue for really big strings. If the string is really huge, copying it will take a little while.

It can be an even bigger problem with arrays. If the array is big enough, making a copy could take a relatively long time and use up a lot of memory.

If you really want to work with a copy, make your own. If the_array is an array of Integer, you can do this:

    Dim array_copy() As Integer

        array_copy = the_array
        TheRoutine array_copy
Of course, you'll pay a small price in speed and memory if the array is big.
Compressing Spaces
(By Bill Matthews)
This routine replaces multiple occurrances of spaces with single spaces.
    ' Replaces sequential spaces with single spaces.
    ' Spaces on either end are removed.
    Private Function PreventDuplicateSpaces(Word)
        Dim i, WordLength, Character, LastCharacter, NewWord

        On Error GoTo ErrorHandler
        WordLength = Len(Word)
        For i = 1 To WordLength
            Character = Mid(Word, i, 1)
            If LastCharacter = " " And Character = " " Then
            Else
                NewWord = NewWord & Character
                LastCharacter = Character
            End If
        Next i

        PreventDuplicateSpaces = Trim(NewWord)
        Exit Function

    ErrorHandler:
        ' Insert your favorite error handler here.
    End Function

Steve Okonski offers this version which is about 50 times faster.

    Function fastremoveduplicatespaces$ (txt$)
    Dim localtxt$, pt%
        localtxt$ = Trim$(txt$)
        Do
            pt% = InStr(localtxt$, " ") ' 2 blank spaces
            If pt% = 0 Then Exit Do
            localtxt$ = Left$(localtxt$, pt%) + Trim$(Mid$(localtxt$, pt%))
        Loop
        fastremoveduplicatespaces$ = localtxt$
    End Function

In Visual Basic 6, the following function is about the same speed as Steve's version and is a bit simpler.

    Private Function CompressSpaces(ByVal txt As String) As String
        Do While InStr(txt, "  ") > 0
            txt = Replace(txt, "  ", " ")
        Loop
        CompressSpaces = txt
    End Function

Click here to download a program that compares these routines.


Save Numeric Options
(By Trevor Finch)
As a programme develops more user options are often needed. This is a method for saving lots of numeric options in a record without having to create new integer or logical fields in a table.

The string 'ms_Options' is saved in a field in a table, and is initialised to String(255, "G"). The reason for "G" is that it gives a range of -6 -> 250 that is all printable ascii, so you can debug easily. In practice Asc("G") is a constant, and there are other error checks.

    Public Property Get Options(ai_Which as integer) as Integer
        Options = Asc(Mid(ms_Options, ai_Which, 1)) - Asc("G")
    End Property

    Public Property Let Options(ai_Which as integer, ai_Value as integer)
        Mid$(ms_Options, ai_Which, 1) = Chr$(ai_Value + Asc("G"))
    End Property

List Available Symbols
(By Dario)
If you press Ctrl-J, the development environment shows a dropdown list of the symbols that are appropriate at that point. For example, if you type "Me.Show", click on Show, and press Ctrl-J, the dropdown list shows symbols available after "Me."

If you move to a blank line and press Ctrl-J, you'll see a list of constants, functions, and properties appropriate at that point.


Larry Northcutt adds, " If you press Ctrl-Spacebar it does the same thing and is much easier on the fingers as there is no stretch involved with the J character."
Use LSet
By Trevor Finch

I have been using Basic for some years, but VB for only a few, but I have only just found out that LSet will copy a user data structure !!!

This will delete a record, and move all records up...

    For i = iCurrent To iCount - 1
        LSet Structure(i) = Structure(i + 1)
    Next i
Help also says LSet can be used reading Binary files Perhaps it can be used to read unsigned integers ?

[I think you can do this if you just want to carry the unsigned value around. If you want to understand the value or modify it, you need to examine the pixels more closely to see what they mean. -- Rod]


Learn Object Types
(By Rod Stephens)
If you want to know whether it is a particular type, do something like:
    If TypeOf obj Is ListItem Then ...

If you want the name of the object's type, use:

    MsgBox "The item is a " & TypeName(obj)

Control Infinite Loops
By Michael Vlastos

When you have trapped inside a non-ending loop, as you cannot press any command buton or key, the only sulution is placing the command "DoEvents" at the first line inside the loop:

Dim i As Long

    For i = 1 To 1000000
        DoEvents
        ...
    Next i
[Actually DoEvents doesn't need to be the first line. Wherever you put it, it gives other parts of your program like a button that ends the loop a chance to receive events. -- Rod]
Faster Infinite Loops
By Cesare Cogliandro

Well, I have found that generally it's better to use the API function GetInputState to check the presence of events in the app's input queue. I don't know why the addiction of an "If" statement improves the code speed, but it works very fine.

So you could replace the row

    DoEvents
with
    If GetInputState() Then DoEvents
Try to believe.

[The reason this makes things faster is that DoEvents allows all applications to process events, not just yours. This test allows DoEvents to run only when your program has events. -- Rod]


Dean Maynard points out that this method makes the program hog the system resources, prevents it from repainting (GetInputState only returns True when a mouse or keyboard event is pending, not when the form needs refreshing), etc. Dean found that the following code reduces the program's resource usage to practically nothing.

    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

    Do While 
        DoEvents
        Sleep 1
    Loop

This allows the rest of the system to take action while your program sleeps.

Note that these two styles of program are in loops for different reasons. In the original program, we assume the program is performing some sort of important calculation and you might want to stop it. The loop lets the program continue computing.

Dean's program is a winsock application and it was waiting in a loop for something to happen. It wasn't trying to perform any calculations and hogging the CPU was bad. In Dean's words:

As far as I can tell, with the sleep call in there, your app stays just as responsive, but does not hog nearly the resources. To me, writing an app which hogs 90%+ resources is just bad programming "manners." unless there's absolutely no other way around it.


Make Select Case Easier
By Richard Sheridan

Let us say that you are creating a string, by letting the user click on various combinations of labels...

    lbl(0) = "Hello "
    lbl(1) = " I'm "
    lbl(2) = " Happy"
    lbl(3) = " Sad"
    ...

    sub lbl_click (index as integer)
        string$ = string$+lbl(index).caption
You would have a series of select case statements to evaluate the string...
    select case string$
        case "Hello I'm Happy"
            do something
        case "Hello I'm"
            this would be an error...
        case else
            do something else
    end select
I realised that this could get very complicated, especially if you had loads of labels and valid / invalid combinations.

So I created an array as large as the number of labels:

    arraylbl(n) as integer
Starting with the value of 1, each cell was (value*2) of previous cell: 1 2 4 8 16 32 64... This would give a unique code to every combination of labels:
    lbl(0) and lbl(1) = 1 + 2 = 3
    lbl(0) and lbl(1) and lbl(4) = 1 + 2 + 16 = 19
Now, when a label is clicked, add its lblarray() code to a variable, say IsLegal (as integer). Obviously, if the label is un-selected by the user, you would have to ensure it had previously been selected, before subtracting the value from IsLegal.

You can easily set up a select case, based upon just a few valid numbers:

    select case IsLegal
        case 3
            ' the string was valid
            call goodstuff
        case 19
            'the string was valid
            call goodstuff
        case  else
            'invalid
            call nogood
    end select

Send your Tips and Tricks to feedback@vb-helper.com.

 
Subscribe to the VB Helper newsletter
Copyright © 1997-2003 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
www.vb-helper.com/tips10.htm Updated