November 15, 2007
@ 03:01 PM

Visual Basic Beer? Well not really, but we can only hope. Don't look for this in your local store unless you are in Australia.

VB Beer


 
Categories: Geek Humor | VB | VB.NET

April 15, 2004
@ 11:15 PM

You can keep your window on top by using the code listed below.

Declare

Declare Sub SetWindowPos Lib "User" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, 
ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer,
ByVal wFlags As Integer)
Const SWP_NOMOVE = 2
Const SWP_NOSIZE = 1
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2

Code

Sub KeepOnTop (frmIn As Form, bOnTop As Integer)
     Dim iTopFlag As Integer
     Const wFlags = SWP_NOMOVE Or SWP_NOSIZE
 
     If bOnTop = True Then
           iTopFlag = HWND_TOPMOST
     Else
           iTopFlag = HWND_NOTOPMOST
     End If
     SetWindowPos frmIn.hWnd, iTopFlag, 0, 0, 0, 0, wFlags
     DoEvents
End Sub

Usage

To put a Form on top of all windows, then call:

KeepOnTop Me, True

To remove the Form from being on top, call:

KeepOnTop Me, False

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: Henk Hakvoort
Compatible With  Visual Basic 3.0, Visual Basic 4.0 16-bit


 
Categories: VB

Instead of SetWindowPos, it uses SetWindowWord. This lets you create a floating toolbar that stays above its app's window without staying on top of ALL windows. Very handy for that professional look.

Declare Sub SetWindowWord Lib "USER" (ByVal hWnd, ByVal nCmd, ByVal nVal) 
Const SWW_hParent = (-8)

Form_Load of the form that you want to keep on top. Set it about form1.

Sub Form_Load () 
     SetWindowWord hWnd, SWW_hParent, form1.hWnd
End Sub

Form_Unload of the from you want to keep on top this is for cleaning up.

Sub Form_Unload (Cancel As Integer) 
     SetWindowWord hWnd, SWW_hParent, 0
End Sub

 

Tip Submitted By: Jonathon Twigg


 
Categories: VB

Background

I was almost finished with an app I was writing. Twice in this app I did some time consuming formatting and I thought it would be nice to have a status bar in these loops. My program had Modal windows so the problem begun. I could not show a non modal window on to of a modal window and if I loaded a Modal window I could not execute the code in the current module. I did not want to put the code in the status window because there were 2 big loops that had to be in the modules they were. So this is what I found. You can show a window non-modal with the SetWindowPos call from windows. By showing the window with this call I had two windows that could get the focus so I had to disable the first form and I just did that with Me.Enabled = False. When the loop was finished I just Enabled my for again and unloaded the status form.

Code

Global Declare:

Declare Function SetWindowPos Lib "User" (ByVal hWnd As Integer, ByVal hWndInsertAfter As Integer,
ByVal X As Integer, ByVal Y As Integer, ByVal cX As Integer, ByVal cY As Integer,
ByVal wFlags As Integer) As Integer
 
Global Const SWP_NOMOVE = &H2
Global Const SWP_NOSIZE = &H1
Global Const SWP_SHOWWINDOW = &H40
Global Const HWND_TOP = 0

The loop:

Sub DoAnyThing ()
     ' Show the status window
     i = SetWindowPos(frm_Status.hWnd, HWND_TOP, 0, 0, 0, 0, 
SWP_NOSIZE Or SWP_NOMOVE Or SWP_SHOWWINDOW)
     ' Disable Me
     Me.Enabled = False
     DoEvents
 
     ' Do the loop
     For I = 1 To 200
           ' do stuff
           ' set the status
           frm_Status.pic_Status.Line (0, 0)-(I, 100), QBColor(1), BF
           frm_Status.pic_Status.Refresh
           DoEvents
     Next I
 
     'Unload the status window
     Unload frm_Status
     ' Enable Me ...
     Me.Enabled = True
     ' and give me the focus
     Me.SetFocus
End Sub

 

Tip Submitted By: Olafur Orn Jonsson


 
Categories: VB

April 15, 2004
@ 11:05 PM

You could move the cursor off the screen, but there is an easy way to make the cursor invisible with an API call:

Declare

Declare Function ShowCursor Lib "User" (ByVal bShow As Integer) As Integer

Usage

To use the API, simply call:

R = ShowCursor(True)

or

R = ShowCursor(False)

There is one thing you should know about this API call. Whenever a program calls ShowCursor, Windows keeps an internal count of how many times ShowCursor was called. The problem is that there is no way to retrieve this counter. So just calling ShowCursor(False) might not work because it just decreases the counter by one. Unless the counter is zero, the cursor will not disappear. Use this routine instead.

Sub EnableCursor (iSetting As Integer)
     Select Case iSetting
           Case True
                 Do While ShowCursor(True) <= 0
                 Loop
           Case False
                 Do While ShowCursor(False) >= 0
                 Loop
     End Select
End Sub

To use this Sub, call it with the iSetting parameter set to either True or False. The cool thing about this API call is that it makes the cursor invisible but MouseMove, etc., events still work. This technique also works in Windows 95.

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: David McCarter

Compatible with: Visual Basic 3.0, Visual Basic 4.0 16-bit


 
Categories: VB

April 15, 2004
@ 11:02 PM

To do effective error handling, you must write them into each and every routine. What a pain! There are many ways to do error handling, from coding it yourself to purchasing add-on tools that will do most of the code writing for you.

This tip is for those who prefer to do it themselves. This is a good idea, because you have much more control over it. Also, another important part of error handling is writing the error to a file. This will save you tons of time in development and also help with technical support problems. Instead of trying to get information on the error message from the user, they can simply send the error log. This tip incorporates that philosophy.

Declare

Global Const errExit = 0
Global Const errResume = 1
Global Const errNext = 2
Global Const errSelect = 3

Code

Public Function ErrorHandler(iErrorNumber As Integer, sErrText As String, 
iErrOption As Integer) As Integer
Dim sMessage As String
Dim iReturn As Integer
     'Create message string
     sMessage = "Error #:" & Str(iErrorNumber) & " - "
     sMessage = sMessage & sErrText
     'Save to error log file
     ErrWriteLogFile sMessage
 
     Select Case iErrOption
           Case errExit
                 MsgBox sMessage, vbCritical, _
                       "Exiting program..."
                 GoTo errHandlerEnd
           Case errResume
                 MsgBox sMessage, vbCritical, "Error"
                 ErrorHandler = errResume
           Case errNext
                 MsgBox sMessage, vbCritical, "Error"
                 ErrorHandler = errNext
           Case errSelect
                 iReturn = MsgBox(sMessage, vbCritical + _
                       vbAbortRetryIgnore, "Error")
                 Select Case iReturn
                       Case Is = vbAbort
                             GoTo errHandlerEnd
                       Case Is = vbRetry
                             ErrorHandler = errResume
                       Case Is = vbIgnore
                             ErrorHandler = errNext
                 End Select
     End Select
     Exit Function
errHandlerEnd:
     MsgBox "Click OK to Exit Program"
     End
End Function
 
Public Sub ErrWriteLogFile(sLogMsg As String)
     Dim sFile As String
     Dim lFile As Long
     Dim sErrDir As String
 
     On Error GoTo errWriteLogFileErr
     sErrDir = App.Path
     lFile = FreeFile
     sFile = sErrDir & "\" & App.EXEName & ".err"
     Open sFile For Append As lFile
     Print #lFile, Format$(Now, "General Date") & ": " _
           & sLogMsg
     Close #lFile
     GoTo errWriteLogFileExit
errWriteLogFileErr:
     MsgBox Str(Err) + "-" + Error$, vbCritical, _
           "Unable to Write Error Log"
     Exit Sub
errWriteLogFileExit:
End Sub

Example

This is a sample of how you could use this tip:

Dim R As Long
Dim I As Integer
On Error GoTo ErrorHandler1
     For I = 3000 To 100000
           DoEvents
     Next I
ErrorHandler1:
     R = ErrorHandler(iErrorNumber:=Err.Number, sErrText:=Err.Description, iErrOption:=errNext)

Even though this tip was written in Visual Basic 4.0, it can be easily modified for any other version of Visual Basic. It’s also easy to modify for your particular needs.

 

This tips is reprinted from the VB Tips & Tricks Volume 1 book.
Some parts of this tips was submitted by: George Graff


 
Categories: VB

April 15, 2004
@ 10:57 PM

Declare

Private Declare Function MakeSureDirectoryPathExists Lib "IMAGEHLP.DLL" 
(ByVal DirPath As String) As Long

Code

Public Sub CreatePath(ByVal DestPath As String)
    If Right(DestPath, 1) <> "\" Then
        DestPath = DestPath & "\"
    End If
    If MakeSureDirectoryPathExists(DestPath) = 0 Then
        MsgBox "Error creating path: " & DestPath
    End If
End Sub

 

Tip Submitted By: Kevin Buchan


 
Categories: VB

This is a multi-part download of Service Pack 6 for Visual Basic 6.0. Customers with broadband connections are encouraged to download the one-file version. See the Related Resources link.

Service Pack 6 for Visual Basic 6.0 provides the latest updates to Visual Basic 6.0. It is recommended for all users of Visual Basic 6.0.

 

http://www.microsoft.com/downloads/details.aspx?familyid=83bf08e6-012d-4db2-8109-20c8d7d5c1fc&displaylang=en


 
Categories: VB

vbrun60sp6.exe is a self-extracting executable file that installs versions of the Microsoft Visual Basic run-time files required by all applications created with Visual Basic 6.0. The files include the fixes shipped with Service Pack 6 for Visual Basic 6.0.

 

http://www.microsoft.com/downloads/details.aspx?familyid=7b9ba261-7a9c-43e7-9117-f673077ffb3c&displaylang=en


 
Categories: VB

Positioning the cursor over the button they will are likely to make the action quicker and easier.

The following code will center the mouse cursor over any control that has an hWnd property.

Declare

#If Win32 Then
     Type RECT
           left As Long
           top As Long
           right As Long
           bottom As Long
     End Type
     Declare Sub GetWindowRect Lib "User32" (ByVal hWnd As _
           Long, lpRect As RECT)
     Declare Sub SetCursorPos Lib "User32" (ByVal X As _
           Long, ByVal Y As Long)
#Else
     Type RECT
           left As Integer
           top As Integer
           right As Integer
           bottom As Integer
     End Type
 
     Declare Sub GetWindowRect Lib "User" (ByVal hWnd _
           As Integer, lpRect As RECT)
     Declare Sub SetCursorPos Lib "User" (ByVal X As _
           Integer, ByVal Y As Integer)
#End If
Code
Sub CenterCursor(hWnd As Long)
Dim rPosition As RECT
#If Win32 Then
     Dim X As Long
     Dim Y As Long
#Else
     Dim X As Integer
     Dim Y As Integer
#End If
 
     GetWindowRect hWnd, rPosition
     X = (rPosition.right + rPosition.left) / 2
     Y = (rPosition.bottom + rPosition.top) / 2
     SetCursorPos X, Y
End Sub

Usage

CenterCursor hWnd:=Command1.hWnd

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip were submitted by: Donovan Olivier
Compatible With Visual Basic 4.0
Applies To Controls


 
Categories: VB

March 11, 2004
@ 12:25 AM

This is not an easy task because the TAB does NOT generate the Key_Press event. So, you need to use the GetKeyState windows API function for this.

Declare

Private Declare Function GetKeyState Lib "User32" (ByVal nVirtKey As Long) As Integer
' Virtual key values
Const VK_TAB = &H9
Const VK_SHIFT = &H10

Code

Sub txtAreaCode_LostFocus()
Dim iRetVal As Integer
 
    ' Check for a tab out of this control
    ' Skip the state field
    iRetVal = GetKeyState(VK_SHIFT)
    ' If the shift was NOT on, check the tab
    If iRetVal <> -128 And iRetVal <> -127 Then
        iRetVal = GetKeyState(VK_TAB)
        If iRetVal = -128 Or iRetVal = -127 Then ' tab key pressed
            txtPhone.SetFocus
        End If
    End If
End Sub

 

Tip Submitted By: Deborah Kurata

 


 
Categories: VB

March 9, 2004
@ 11:16 PM

Even though this code is relatively simple, it's surprising to see the number of major applications on the shelves that fail to correctly handle this scenario.

The code shown below consists of two functions. The bValDIR function is needed because in Visual Basic, if you try to create a directory using the MkDir function that already exists, MkDir will generate an error.

Code

Sub MakeDir (sDirName As String)
Dim iMouseState As Integer
Dim iNewLen As Integer
Dim iDirLen As Integer
    'Get Mouse State
     iMouseState = Screen.MousePointer
     'Change Mouse To Hour Glass
     Screen.MousePointer = 11
     'Set Start Length To Search For [\]
     iNewLen = 4
     'Add [\] To Directory Name If Not There
     If Right$(sDirName, 1) <> "\" Then
           sDirName = sDirName + "\"
     End If
     'Create Nested Directory
     Do While Not bValDir(sDirName)
           iDirLen = InStr$(iNewLen, sDirName, "\")
           If Not bValDir(Left$(sDirName, iDirLen)) Then
                 MkDir Left$(sDirName, iDirLen - 1)
           End If
           iNewLen = iDirLen + 1
     Loop
     'Leave The Mouse The Way You Found It
     Screen.MousePointer = iMouseState
End Sub
Function bValDir (sIncoming As String) As Integer
Dim iCheck As String
Dim iErrResult As Integer

    On Local Error GoTo ValDirError
     If Right$(sIncoming, 1) <> "\" Then
           sIncoming = sIncoming + "\"
     End If
     iCheck = Dir$(sIncoming)
     If iErrResult = 76 Then
           bValDir = False
     Else
           bValDir = True
     End If 
Exit Function
ValDirError:
     Select Case Err
           Case Is = 76
                 iErrResult = Err
                 Resume Next
           Case Else
     End Select
End Function

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: David McCarter

Compatible With All Versions of Visual Basic
Applies To Disk Directory


 
Categories: VB

March 9, 2004
@ 11:12 PM

Well Visual Basic 5.0 comes with a program that create them for you, but what a pain. Wouldn't it be nice to just do it via code? Well now you can with the sample code below.

Declare

Type GUID Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type
 
Private Declare Function CoCreateGuid Lib "ole32.dll" (pguid As GUID) As Long
Private Declare Function StringFromGUID2 Lib "ole32.dll" 
(rguid As Any, ByVal lpstrClsId As Long, ByVal cbMax As Long) As Long

Code

Public Function GetGUID() As String
Dim pudtGUID As GUID
Dim pstrGUID As String
Dim pbytGUID() As Byte
Dim plngRet As Long
Dim plngLen As Long
    plngLen = 40
    pbytGUID = String(plngLen, 0)
    CoCreateGuid pudtGUID
    plngRet = StringFromGUID2(pudtGUID, VarPtr(pbytGUID(0)), plngLen)
    pstrGUID = pbytGUID
    If (Asc(Mid$(pstrGUID, plngRet, 1)) = 0) Then plngRet = plngRet - 1
    GetGUID = Left(pstrGUID, plngRet)
End Function

 

Tip Submitted By: David McCarter/Woody Pewitt


 
Categories: VB

This is really easy to do.

Declare

Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" 
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String,
ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Code

Dim X
    X = ShellExecute(hwnd, "Open", "http://www.microsoft.com/vbasic", &O0, &O0, SW_NORMAL)

 

Tip Submitted By: Ryan Martinsen


 
Categories: VB

March 9, 2004
@ 11:07 PM

The 32-bit API has a call that will create a unique file for you in the Windows temporary directory.

Declare

Declare Function OSGetTempPath& Lib "kernel32" Alias "GetTempPathA" 
(ByVal BufferLength&, ByVal Result$)
Declare Function OSGetTempFilename& Lib "kernel32" Alias "GetTempFileNameA" 
(ByVal FilePath$, ByVal Prefix$, ByVal wUnique&, ByVal TempFileName$)
Code
Function sGetTempFile(ByRef sPrefix As String)
Dim sFilePath As String
Dim sTempResult As String
Dim lCharCount As Long
Const MAX_RETURN = 3000
     sTempResult = Space$(MAX_RETURN)
     lCharCount = OSGetTempPath&(MAX_RETURN, sTempResult)
     sFilePath = Left$(sTempResult, lCharCount)
 
     sTempResult = Space$(MAX_RETURN)
     lCharCount = OSGetTempFilename&(sFilePath, sPrefix, 0, sTempResult)
     sGetTempFile = Left$(sTempResult, lCharCount)
End Function

Usage

sTempFile = sGetTempFile(sPrefix:="VBT")

This API call will tag a prefix (up to 3 characters) to the file. This makes it easier for you find, use, or delete your temporary files.

NOTE: Windows will NOT automatically delete these temporary files. So be kind to your user, keep track of them and delete them when the application closes.

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: David McCarter
Compatible With Visual Basic 4.0 32-bit
Applies To Files


 
Categories: VB

 The code below can be easily added to a module and even includes code to make a backup (Access is notorious for corrupting databases at a drop of a pin). Compacting large databases can take a long time, so provide your user with a "Please wait..." type message.

NOTE: Remember, you cannot compact a database while it's open. Be sure to run this code before any code is run that opens the database, or any form with a data control is loaded. You could also run this at the end of your program.

Function bCompactMDB (sDatabase As String, bBackup As Integer) As Integer
Dim sNewFile As String
Dim sBakFile As String
     bCompactMDB = False
     MousePointer = 11
     sNewFile = Left$(sDatabase, Len(sDatabase) - 3) & "NEW"
     sBakFile = Left$(sDatabase, Len(sDatabase) - 3) & "BAK"
     On Error GoTo CompactError
     If Dir(sNewFile) <> "" Then
        Kill sNewFile
     End If
     CompactDatabase sDatabase, sNewFile
     If Dir(sBakFile) <> "" Then
       Kill sBakFile
     End If
     If bBackup = True Then
       Name sDatabase As sBakFile
     End If
     If Dir(sDatabase) <> "" Then
       Kill sDatabase
     End If
     Name sNewFile As sDatabase
     bCompactMDB = True
     MousePointer = 0
     Exit Function
CompactError:
     bCompactMDB = False
     MousePointer = True
End Function

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: David McCarter

Compatible With Visual Basic
Applies To Access 2.x Database File


 
Categories: VB

March 9, 2004
@ 11:01 PM

You can use the following function to defragment memory, making the maximum available to your program, before beginning any operation that will require a lot of memory.

Declare

Declare Function GlobalCompact Lib "Kernel" (ByVal dwMinFree&) As Long

Code

Sub CompactMemory ()
     Dim R As Long
     R = GlobalCompact(&HFFFFFFFF)
End Sub

Usage

Call CompactMemory

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.

Compatible With Visual Basic 3.0, Visual Basic 4.0 16-bit
Applies To Windows 3


 
Categories: VB

During the development of your project, the types and number of settings can grow and grow. With these routines, you can write the code once, then you usually won't need to update this code even when you add new controls.

For each setting that you save, whether to the Registry or an INI, you'll need to define "section" and "key" strings. See the help on GetSetting and/ or SaveSetting for examples.

For each control that you'll use to maintain a setting, put the name of the "key" in the control's TAG property. Put the default value of that key in the control itself at design time. For the section name, you must put your control into a container control with the desired "section" string in its own .TAG field. Often, this is actually very convenient, as controls get grouped into frames and other logical containers. When that isn't fully effective, use any kind of invisible container which supports a .TAG property, or use the TAG of the form itself. I usually reserve that last tactic for the most general of settings.

Call GetOptions before showing the form to the user (I usually call it from form_load) and call PutOptions whenever you need to save settings.

Code

Public Sub GetOptions(Frm As Form)
Dim Ctrl As Control
    For Each Ctrl In Frm.Controls
        With Ctrl
            If .Enabled Then
                If Len(.Parent.Tag & .Tag) Then
                    If TypeOf Ctrl Is TextBox Then
                        .Text = Trim$(GetSettingString(.Parent.Tag, .Tag, .Text))
                        ElseIf TypeOf Ctrl Is CheckBox _
                            Or TypeOf Ctrl Is HScrollBar _
                            Or TypeOf Ctrl Is VScrollBar _
                            Then
                            .Value = GetSettingInt(.Parent.Tag, .Tag, .Value)
                    End If
                End If
            End If
        End With
    Next
End Sub
 
Public Sub PutOptions(Frm As Form)
Dim Ctrl As Control
    For Each Ctrl In Frm.Controls
        With Ctrl
            If .Enabled Then
                If Len(.Parent.Tag & .Tag) Then
                    If TypeOf Ctrl Is TextBox Then
                        SaveSettingString .Parent.Tag, .Tag, .Text
                        ElseIf TypeOf Ctrl Is CheckBox _
                            Or TypeOf Ctrl Is HScrollBar _
                            Or TypeOf Ctrl Is VScrollBar _
                            Then
                            SaveSettingInt .Parent.Tag, .Tag, .Value
                    End If
                End If
            End If
        End With
    Next
End Sub

You'll need to include GetSettingInt, GetSettingString, SaveSettingInt, and SaveSettingString routines to save the settings to your own INI file.

Also, you can certainly adjust the code for other types of controls besides the TextBox, CheckBox, HScrollBar and VScrollBar.

Additional Code

'Set this public variable before you call GetOptions or PutOptions
Public gsIniFile As String
Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" 
(ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal nDefault As Long,
ByVal lpFileName As String) As Long
Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" 
(ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String,
ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" 
(ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any,
ByVal lpFileName As String) As Long
Private Function FixString(sInString As String) As String
Dim nPos As Integer
    On Error Resume Next
    nPos = InStr(sInString, Chr$(0))
    If nPos Then
        FixString = Left$(sInString, nPos - 1)
        Else
            FixString = sInString
    End If
End Function
Private Function GetSettingString(sSection As String, sKey As String, sDefault As String) As String
Const INI_BUF_SIZE = 255
Dim iReturn As Integer
Dim sBuffer As String
    On Error Resume Next
    sBuffer = String$(INI_BUF_SIZE + 1, 0)
    iReturn = GetPrivateProfileString(sSection, sKey, sDefault, sBuffer, INI_BUF_SIZE, gsIniFile)
    GetSettingString = FixString(sBuffer)
End Function
Private Function GetSettingInt(sSection As String, sKey As String, nDefault As Integer) As Integer
    On Error Resume Next
    GetSettingInt = GetPrivateProfileInt(sSection, sKey, nDefault, gsIniFile)
End Function
Private Function SaveSettingInt(sSection As String, sKey As String, nValue As Integer) As Boolean
    On Error Resume Next
    SaveSettingInt = IniPrivateWriteString(sSection, sKey, CStr(nValue), gsIniFile)
End Function
Private Function SaveSettingString(sSection As String, sKey As String, sValue As String) As Boolean
    On Error Resume Next
    SaveSettingString = IniPrivateWriteString(sSection, sKey, sValue, gsIniFile)
End Function
Private Function IniPrivateWriteString(sSection As String, sKey As String, 
sValue As String, sIniFile As String) As Boolean
    On Error Resume Next
    If (Len(sKey) > 0) Then
        IniPrivateWriteString = (WritePrivateProfileString(sSection, sKey, sValue, sIniFile) <> 0)
        Else
        '----- Delete all keys in this section
        IniPrivateWriteString = (WritePrivateProfileString(sSection, vbNullString, sValue, sIniFile) <> 0)
    End If
End Function

 

Tip Submitted By: Bob O`Bob


 
Categories: VB

I have developed a global subroutine that will highlight the text of the active control of the active form.

The routine is simple:

Sub Highlight()
    On Error Resume Next
    Dim FRM1 As Form
    Set FRM1 = Screen.ActiveForm
    FRM1.ActiveControl.SelStart = 0
    FRM1.ActiveControl.SelLength = Len(FRM1.ActiveControl)
End Sub

Create a form object by first dimensioning it and setting it to the active form. Next, select the text of the form's active control starting at the left most character to the end of the text.

Use this in the got_focus method of any control that allows text entry such as a text box or a combo box.

Private Sub Text1_GotFocus ()
    Call Highlight
End Sub

That's it! One subroutine call does it all. I put this routine in a global module so all my forms have access to it.

 

Tip Submitted By: Marc Mueller


 
Categories: VB

February 11, 2004
@ 06:05 PM

If you use a higher screen resolution than your users, your forms could be partially hidden or even completely off the screen.

 

There are a few different ways to center your Forms and this tip is by far the best one. It’s very useful because you can center your form over any other form. It’s good to center status Form over your applications mail form instead of the Screen. It just looks nicer. This object can be another Form or the Screen.

Code

Sub CenterForm(objChild As Object, objParent As _
           Object, Optional vLeftTopOffset As Variant, _
           Optional vTopOffset As Variant, Optional vMode _
           As Variant)
     Dim iLeft As Integer
     Dim iTop As Integer
     Dim iMode As Integer
     Dim iLOffset As Integer
     Dim iTOffset As Integer
     Dim I As Integer
     If TypeOf objParent Is SysInfo Then
           iLeft = objParent.WorkAreaLeft + _
                 (objParent.WorkAreaWidth - objChild.Width) / 2
           iTop = objParent.WorkAreaTop + _
                 (objParent.WorkAreaHeight - objChild.Height) / 2
     ElseIf TypeOf objParent Is MDIForm Then
           If objChild.MDIChild = True Then
                 iLeft = (objParent.ScaleWidth - _
                       objChild.Width) / 2
                 iTop = (objParent.ScaleHeight - _
                       objChild.Height) / 2
           Else
                 iLeft = objParent.Left + (objParent.Width - _
                       objChild.Width) / 2
                 iTop = objParent.Top + (objParent.Height - _
                       objChild.Height) / 2
           End If
     ElseIf TypeOf objParent Is Screen Then
           iLeft = (objParent.Width - objChild.Width) / 2
           iTop = (objParent.Height - objChild.Height) / 2
     ElseIf TypeOf objParent Is Form Then
           If objParent.MDIChild = True Then
                 iLeft = objParent.Left + (objParent.Width - _
                       objChild.Width) / 2
                 iTop = objParent.Top + (objParent.Height - _
                       objChild.Height) / 2
                 For I = 0 To Forms.Count - 1
                       If TypeOf Forms(I) Is MDIForm Then
                             iLeft = iLeft + (Forms(I).Width - _
                                   Forms(I).ScaleWidth) / 2 + _
                                   Forms(I).Left
                             iTop = iTop + (Forms(I).Height - _
                                   Forms(I).ScaleHeight) / 2 + _
                                   Forms(I).Top
                             Exit For
                       End If
                 Next I
           Else
                 iLeft = objParent.Left + (objParent.Width - _
                       objChild.Width) / 2
                 iTop = objParent.Top + (objParent.Height - _
                       objChild.Height) / 2
           End If
     Else
           Exit Sub
     End If
     If IsMissing(vMode) Or objChild.MDIChild = True Then
           iMode = vbModeless
     Else
           iMode = Int(vMode)
     End If
     If IsMissing(vLeftTopOffset) Then
           iLOffset = 0
     Else
           iLOffset = Int(vLeftTopOffset)
     End If
     If IsMissing(vTopOffset) Then
           iTOffset = 0
     Else
           iTOffset = Int(vTopOffset)
     End If
     objChild.Move iLeft + iLOffset, iTop + iTOffset
     objChild.Show iMode
End Sub

Examples

Example 1

Center the Form on the Screen.

CenterForm objChild:=Me, objParent:=Screen

Example 2

Center the Form as Modal on the Screen.

CenterForm objChild:=Me, objParent:=Screen, vMode:=vbModal

Example 3

Center the Form on the Windows 95 viewing area (takes into account the TaskBar). This requires that a SysInfo control (which comes with Visual Basic) be placed on the Form.

CenterForm objChild:=Me, objParent:=SysInfo

Example 4

Centers the Form on a Parent Form.

CenterForm objChild:=Me, objParent:=frmMain

You can also use the vTopOffset and vLeftOffset parameters to center the Form and then add or subtract from the X and Y coordinates.

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.

Compatible With Visual Basic 4.0
Parts of this tip were submitted by: C.G. Ouimet


 
Categories: VB

The Timer's "roll-over" point is 24 hours. Since Timer only returns seconds, using GetTickCount also gives you a much higher resolution.

Declare

Declare Function GetTickCount Lib "User"() As Long

Usage

Dim lTimer1 as Long
lTimer1 = GetTickCount()

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.

Compatible With: Visual Basic 3.0, Visual Basic 4.0 16-bit


 
Categories: VB

January 8, 2004
@ 01:21 AM
  • xFile - The filename (it copies from the application's own directory)
  • xDest - The destination directory

Declare

Declare Function GetVersion Lib "Kernel" () As Long
Declare Function GetFileVersionInfo% Lib "VER.DLL" (ByVal lpszFileName$, ByVal handle As Any, ByVal cbBuf&, ByVal lpvData$)

Code

Sub CheckFile(xFile As String, xDest As String)
On Error Resume Next
Dim retS%
Dim retD%
     If Right(xDest, 1) <> "\" Then xDest = xDest + "\"
     Form2.lblSource.Caption = App.Path + "\" + xFile
     Form2.lblDestination.Caption = xDest + xFile
     If Dir(xFile) = "" Then
           FileCopy App.Path + "\" + xFile, xDest + xFile
     Else
           'Check version
           retS% = GetFileVersionInfo(App.Path + "\" + xFile, 0&, 254, version)
           retD% = GetFileVersionInfo(xDest + xFile, 0&, 254, version)
           If retS% >= retD% Then
                 FileCopy App.Path + "\" + xFile, xDest + xFile
           End If
     End If
 
     'Just wait for a sec
     For i = 1 To 1000
           DoEvents
     Next i
 
End Sub

 

Tip Submitted By: Jeff Williams

 


 
Categories: VB

This value gets passed between the database and the application effortlessly. The problem arises when inevitably you want to export the tables into a flat file. It exports just fine except that the Chr$(13) & Chr$(10) get converted back to the effects of an enter keystroke and cause your export file to be out of whack. Then, when you want to import the file into the new (or old) tables, you get import errors galore and the import process halt's.

The work around is not pretty, but it is effective. This is a two stage process with the first stage looking similar to the above tip. First, we have to convert all the Chr$(13) & Chr$(10)'s into something that DOS won't treat any different than a regular character. We cannot use a keyboard character as our token as inevitably, no matter how obscure you make the symbol, someone will type it in. I chose Chr$(6) which is nothing in particular except an unprintable character.

MySet("Comments") = ReplaceEnter(txtComments.Text)
Function ReplaceEnter (ByVal ParseText As String) As String
Dim Offset as Integer, x as integer
    ParseText = LTrim$(Trim$(ParseText))
    x = InStr(ParseText, Chr$(13))
    If x = 0 Then
        ReplaceEnter = ParseText & " " ' Takes care of the Access zero length string problem
        Exit Function
    End If
    Offset = 1
    Do While x > 0
        ParseText = Left$(ParseText, x - 1) & Chr$(6) & Mid$(ParseText, x + 2)
        Offset = x + 1
        x = InStr(Offset, ParseText, Chr$(13))
    Loop
    ReplaceEnter = ParseText
End Function

So, we do the update on the database but there comes a time when you want to redisplay the contents of the field. Now, you have to reverse the process and convert the Chr$(6)'s into Chr$(13) & Chr$(10)'s:

txtComments.Text = ReplaceChr6(MySet("Comments") & "")
Function ReplaceChr6 (ByVal ParseText As String) As String
Dim Offset as Integer, x as integer
    x = InStr(ParseText, Chr$(6))
    If x = 0 Then
        ReplaceChr6 = ParseText
        Exit Function
    End If
    Offset = 1
    Do While x > 0
        ParseText = Left$(ParseText, x - 1) & Chr$(13) & Chr$(10) & Mid$(ParseText, x + 1)
        Offset = x
        x = InStr(Offset, ParseText, Chr$(6))
    Loop
    ReplaceChr6 = ParseText
End Function

As I said at the beginning, it isn't pretty, but it does get you around a problem you may not be aware of until your user decides to export the file so he/ she can do something with it.

 

Tip Submitted By: Paul A. Birkbeck


 
Categories: VB

January 8, 2004
@ 01:13 AM

The best way to deal with this problem is to use the built-in & operator to concatenate a blank string to each field as you read it. Concatenate 0 for numeric fields.

Sample Code

Dim dbBiblio As Database
Dim rsData As Recordset
Dim sYear As String
Dim sHireDate As Date
Dim lReports As Long
  Set dbBiblio = OpenDatabase("Northwind.mdb")
  Set rsData = dbBiblio.OpenRecordset("Employees")
  'Concatenate empty string ("") here with null values
  sYear = rsData![Title] & vbNullString
  'Concatenate zero so it does not error
  sHireDate = rsData![HireDate] & 0
  lReports = rsData![ReportsTo] & 0


 


 
Categories: VB

Although only one function is presented here, you may notice a gold mine of other associated and required functions that may be used for a multitude of purposes.

Code

Public Function GetUniqueFileName(ThisEXT As String, Optional ThisPath As String) As String
    Dim retval As String, varTmp As String
    varTmp = NormalizePath(GetTEMPdir(True))
    Do
        If LTrim(RTrim(ThisPath)) <> "" Then
            If DirExistCreate(ThisPath, False) Then
                retval = NormalizePath(ThisPath) & UniqueFileName & "." & ThisEXT
            ElseIf DirExistCreate(varTmp, True) Then
                retval = varTmp & UniqueFileName
            End If
        ElseIf DirExistCreate(varTmp, True) Then
            retval = varTmp & UniqueFileName
        End If
           DoEvents      'give someone else a chance...
    Loop While FindFile(retval)
    GetUniqueFileName = retval
End Function
Public Function UniqueFileName() As String
    On Local Error GoTo ufnError
    Dim retval As String
    
    'This example uses the Rnd function to generate a random integer value from 10000 to 32000.
    retval = "~" & Str(Int((32000 * Rnd) + 10000))
ufnOut
    UniqueFileName = retval
    Exit Function
ufnError
    retval = ""
    Resume ufnOut
End Function
Public Function GetTEMPdir(CreateOne As Boolean, Optional tVar As String) As String
    Dim wTmp As String
    On Local Error Resume Next
    
    wTmp = Environ$("TEMP")
    If wTmp = "" Then
        If CreateOne Then
            If LTrim(RTrim(tVar)) = "" Then tVar = "C\TEMP"
            MkDir tVar
            wTmp = tVar
        End If
    End If
    
    wTmp = NormalizePath(wTmp)
    GetTEMPdir = wTmp
 
End Function
Public Function FindFile(ThisFile As String, Optional SetAttribute As Variant) As Boolean
    On Local Error GoTo ffError
    Dim retval As Boolean, tAttr As Integer
    tAttr = vbNormal        'tattr=0
    If Trim(ThisFile) = "" Then
        Exit Function
    End If
    Do While tAttr <= 39
        If Len(Dir(ThisFile, tAttr)) > 0 Then
            If Not IsMissing(SetAttribute) Then
                SetAttr ThisFile, CInt(SetAttribute)
            End If
            retval = True
            Exit Do
        Else
            tAttr = tAttr + 1
            '1 -> 7 valid for files
            If tAttr = 8 Then tAttr = 32
            '32 -> 39 valid for files
            If tAttr = 40 Then
                retval = False
                Exit Do
            End If
        End If
    Loop
ffOut
    FindFile = retval
    Exit Function
ffError
    retval = False
    Msg = "Find File Error " & Error(Err) & vbCrLf
    Msg = Msg & ThisFile
    MsgBox Msg, vbExclamation, App.EXEName
    Err = 0
    Resume ffOut
End Function
Public Function DirExistCreate(ThisDir As String, Optional CreateIt As Variant) As Boolean
    On Local Error GoTo DEerror
    Dim Retval As Boolean, varCreateIt As Boolean
    Dim ThisTest As String, c As Integer, p As String, i As Integer
    Dim b As Integer
TestDiragain
    If Trim(ThisDir) <> "" Then
        If Not IsMissing(CreateIt) Then varCreateIt = CBool(CreateIt)
        
        If Len(Dir(ThisDir, 16)) > 0 Then
            Retval = True
        Else
            'does not exist so create it by parsing
            ThisDir = NormalizePath(ThisDir)
            c = InStr(ThisDir, "\")
            If c <= 0 Then b = 1 Else b = c + 2
            For i = b To Len(ThisDir)
                p = Mid(ThisDir, i, 1)
                If p = "\" Then
                    ThisTest = Left(ThisDir, i - 1)
                    If Len(Dir(ThisTest, 16)) <= 0 Then
                        MkDir ThisTest
                    End If
                End If
            Next
            GoTo TestDiragain
        End If
    End If
DEout
    DirExistCreate = Retval
    Exit Function
DEerror
    Retval = False
    LogError Err, "Unable to create directory " & ThisDir
    Err = 0
    Resume DEout
End Function
Public Function NormalizePath(ThisPath As String) As String
    If Right(ThisPath, 1) <> vbNullChar Then
        If Right(ThisPath, 1) <> "\" Then
            NormalizePath = ThisPath & "\"
        Else
            NormalizePath = ThisPath
        End If
    Else
        NormalizePath = ThisPath
    End If
End Function

 

Tip Submitted By: Dick Wilson


 
Categories: VB

January 8, 2004
@ 01:08 AM

Supposedly, RecordCount is set correctly when you first open a snapshot, but the ListBox test showed otherwise.
Try it yourself. Here is the solution code with my debug lines commented out.

Sub CopyRows () 
Dim i As Integer 
Dim db As Database
Dim snap As Snapshot
Dim tbl As Table
Dim wSQL As String
    Set db = OpenDatabase("MYDATA.MDB", False, False) 
    Set tbl = db.OpenTable("Table1")
    ' select the rows to be copied into a snapshot object 
    'List1.Clear 'Mark's debug code
    wSQL = "Select * from Table1 where Field1 = 'A'" 
    'I also changed your SQL statement a 
    'little, removed characters I don't use, but I don't
    'think it made any difference.
    Set snap = db.CreateSnapshot(wSQL) 
    snap.MoveLast '<===== MoveLast initializes RecordCount of snap
    snap.MoveFirst '<===== Need to MoveFirst
    'List1.AddItem snap.RecordCount 'Mark's debug code 
    'List1.AddItem "**" 'Mark's debug code
    ' loop through all rows in the snapshot 
    Do Until snap.EOF
        tbl.AddNew
        ' copy each field in the snapshot row to the table row
        For i = 0 To snap.Fields.Count - 1
            tbl.Fields(i).Value = snap.Fields(i).Value
        Next i
        ' change the value of the other field
        tbl.Fields("Field2").Value = "B"
        ' insert the new row into the table
        tbl.Update
        ' Ack! Here's the problem. This "tbl.Update" also is
        ' updating the contents of the snapshot. Meaning the
        ' "snap.MoveNext" will never get to EOF!
        'List1.AddItem snap.RecordCount 'Mark's debug code
        'List1.Refresh 'Mark's debug code
        'DoEvents 'Mark's debug code
        snap.MoveNext 
    Loop
    ' close everything 
    snap.Close 
    tbl.Close
    db.Close
End Sub

 

Tip By: Kyle Lutes


 
Categories: VB

January 8, 2004
@ 01:07 AM

This prompted me to do a little digging and I found out that it couldn't access the file to check because it was open in MS Access 2. As a result I rewrote my routine to take into account file sharing, but it struck me that I could use the old routine to check if a database file was in use.

Some routines that check for the existence of a file might not work with a Microsoft Access 2.0 database that is in use. To check for the file, you must open it as shared. This could be used to check a database file before it’s compacted or repaired.

Function FileExists(Filename As String) As Integer
     On Error Resume Next
     Open Filename For Input Access Read Shared As #1
     FileExists = (Err = 0)
     Close #1
End Function

Also, you can use the following code to check to see if a database file is in use.

Function DBFileInUse(Filename As String) As Integer
     On Error Resume Next
     Open Filename For Input As #1
     DBFileInUse = (Err <> 0)
     Close #1
End Function

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: Grahm Jones


 
Categories: VB

January 8, 2004
@ 01:04 AM

Rather than looping manually through every TextBox on the Form, I came up with the following: A function with the Form as a single argument. Loop through each control on the Form, (using "For Each Control etc") and if it's a TextBox which is empty, it returns Err.Number = 0. If this is true, I change the BackColor of the offending TextBox to light pink, and the function returns True. (If the TextBox is not empty, and it's BackColor is light pink, I return the BackColor to white. One can store the original color and restore it.) Then call Err. Clear, and continue in the loop. All TextBoxes which are empty will show up as light pink.

To test, create a Form with several TextBoxes on it; their names are immaterial, and they can even be in some container, like a Frame. Create a Command Button, named TestEmpty. Following is the code:

Private Sub TestEmpty_Click()
  If IsEmpty(Me) Then
    MsgBox "Some textboxes are still empty"
  End If
End Sub
Function IsEmpty(Frm As Form) As Boolean
Dim tmpControl As Control
  On Error Resume Next
  IsEmpty = False
  For Each tmpControl In Frm.Controls
    If Trim(tmpControl.Text) = "" Then
      If Err.Number = 0 Then
        IsEmpty = True
        tmpControl.BackColor = &HFFC0FF 'light pink
      End If
      Err.Clear
    Else
      If tmpControl.BackColor = &HFFC0FF Then
        tmpControl.BackColor = QBColor(15) 'White
      End If
    End If
  Next tmpControl
End Function

Run the program. Fill in some of the TextBoxes, and click on the Command Button, You will see the empty TextBoxes BackColor change to light pink. If you fill these in and click again, their BackColor will change to white.  Note: If the procedure is in a Module, then the argument is the Form name.

 

Tip Submitted By: Yehuda Hilewitz


 
Categories: VB

December 11, 2003
@ 03:15 AM

What happened was that I had objects pointing to other objects. To allow navigation back, I had also included pointers back to the 'owner' of the objects.

This last thing meant that the objects never got freed, because there was always something referencing them: the members were referenced by the parent, and the parents were referenced by the members. No matter if the caller set the pointer to the top-object in the hierarchy to nothing, the hierarchy remained in memory forever.

Another effect was, that the Class_Terminate event for the objects was never called, and that is were the objects' contents are written to the data base.

The tip is: be careful with references between objects. If you have references like the ones described above, ensure that you have a method in the class that frees all cross-references. Otherwise objects never get freed, and their Class_Terminate event will never be called.

This may sound like a trivial something, but it took me quite some time to figure out why my application was never releasing its memory.

 

Tip Submitted By: Marjo van Diem


 
Categories: VB

I have written a simple function called NeedsFiltering which I use to determine if a block of text contains one or more search characters. The function uses the Like operator to determine if one or more characters in the specified range exist in the input string. If the routine returns False, the text block can be "passed through" without the need for a more time-consuming search.

Function NeedsFiltering (szInput As String) As Integer
Dim szLikeExpr1 As String
Dim szLikeExpr2 As String
szLikeExpr1 = "*[" & Chr(0) & "-" & Chr(8) & "]*"
szLikeExpr2 = "*[" & Chr(128) & "-" & Chr(255) & "]*"
NeedsFiltering = szInput Like szLikeExpr1 Or szInput Like szLikeExpr2
End Function

The "*" in the pattern expressions means "zero or more characters." Therefore, the Like operator will return True if one or more characters in the specified range exist anywhere in the input string. I have used this routine quite successfully in a character filtering application which filters out control and extended ANSI characters (0-8,128-255) from an input file, and places the filtered text in a temporary file. The amount of savings depends upon the number and location of characters in the input string that one wishes to filter out.

 

Tip Submitted By: Barth Riley


 
Categories: VB

These files are used to register you program with the Registration Database. The problem is that the files are not needed! When you compile your OLE server, VB compiles code into it that will do this for you! The problem is that MS does not make this easy for you to find. Because the want you to use the Setup Wizard (anyone that knows me, knows how I feel about the Setup Wizard).

To register your program, simply run your server with the following command line parameter.

MYOLESVR.EXE /REGSERVER 

Your program won't start, it will just register itself. Just make sure you do this after all the runtime files have been installed. You can also un-register your server by using the /UNREGSERVER parameter.

 

Tip By: David McCarter


 
Categories: VB

December 11, 2003
@ 03:09 AM

Run Programs During Windows StartUp

Find the key:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

Add a new String Value. Give the value any name, usually the name of the program. Then double-click on it and type in the path, file name and any command line parameters. For example:

Value Name = Notepad
Value Data = c:\windows\notepad.exe

Run Programs When Loading A User

Do the same as listed above, but use the key:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run 

 

Tip Submitted By: Yatir Halevi


 
Categories: VB

December 11, 2003
@ 02:57 AM

These properties are usually ones that cause the control to re-paint, like Enabled, Visible, Caption and Text. The flicker can be easily reduced by not setting a property when it is already set. For instance, if the Enabled property is set to True why set it to True again?

Enable/Disable Routine

Use this to enable or disable a control.

Sub SetEnabled (ctrlIn as Control, bSetting as Integer)
     If ctrlIn.Enabled <> bSetting Then
           ctrlIn.Enabled = bSetting
     End If
End Sub

Caption Routine

Use this to change a Caption property.

Sub SetLabel (ctrlIn as Control, sNewText as String)
     If ctrlIn.Caption <> sNewText Then
           ctrlIn.Caption = sNewText
     End If
End Sub

You can make as many of these types of routines as you like. Any property that affects a controls appearance, such as colors, fonts and text, would be a good prospect.

 

This tip is reprinted from the VB Tips & Tricks Volume 1 book.
Parts of this tip was submitted by: David McCarter


 
Categories: VB