Visual Basic Developers Resource Centre
Can I install VB6 without first performing the Java installation?
Sure! Before you attempt to install VB, just use Notepad to create a file under c:\windows\system32\ called msjava.dll - it can be 0 length. The installer will see this file and bypass the installation section for the Java runtime.
Note: don't bypass this if you're installing Visual Studio 6 InterDev, as it's required here.
Maximum Number of Controls on a Form (KB article 229756)
The maximum number of controls allowed on a single form depends on the type of controls used and available system resources. However, there is a fixed limit of 254 control names per form. This includes menus. (Although you can have up to 254 control names in a form, a large number of controls in a form will severely degrade your program's performance. In some cases, you will experience out-of-memory error. To maximize the performance of your program, you should minimize the number of controls in each form.)
There are three ways to work around the control name and system resource limitations:
OK, how do I create a control array?
A control array is a group of similar controls that all have the same name but different Index property values. Each control array shares the same event procedures making development of applications easier, and because controls in a control array all share the same control name, this counts as one towards the maximum number of control names allowed on a form.
To create a control array with a new control placed on the form, either change the control's Index property to 0 or copy and paste the control and answer Yes to the resulting ehe unique controhe current actio n is taking place, and can thus be easily coded for different actions, if required, by using a Select Case Index block.
To make a control array out of an existing
control the same technique is used,
however the declarations for each of the control's event procedures
that already contain code will need modification to introduce the
Index property passed to the procedure.
|»||How do I create a
Like a control array, a menu array is a group of menu items under the same parent menu all having the same name but different Index property values. Each menu array member shares the same event code.
To create a menu array for a new menu added to the form, set each menu item's Index property to the next available Index property beginning at 0. Menu array members must be contiguous (you can't break a menu array by inserting a different menu name midway through the list. And menu can have any number of different menu arrays (for example under the File menu you may prefer to have one menu array for the New, Open, Save and Save AS options, and a second menu array for the Print and Print Preview options, or you can use the same menu array for the entire menu. (Naturally, just as for a normal menu the top-level menu item shown in the menu bar must be a different name than the items in its dropdown menu.)
Changing non-array menu into a menu array utilizes pretty well the same technique,
however the menu code residing under the menu click events will need
to be moved to the new menu's click event (the old procedures
containing code will appear under the right-hand combo on the code
installing Crystal Reports takes exceedingly long time.
When the PDW has packaged Crystal reports and corresponding RPT files into a single CAB file, the installation takes an extremely long time. This is a known issue with the PDW and large cabs, and can be resolved by rerunning the PDW and selecting single-disk sized cabs. Although distribution via the web will become more difficult, the actual installation will proceed at an expected rate. If you need to package everything for the web as a single install, you'll have to either follow this suggestion then create a self-extracting exe using one of the pkzip or WinZip tools, use a third party install program, or the new Microsoft Installer, or look to utilities like Open Software Associates NetDeploy.
|»||'Unable to register
<dllname>" error when installing Visual Basic.
Windows 95 and Windows 98 have a maximum registry size of 64k, while NT-based Windows have 64k key limits. This limit can be quickly met with the installation of some of the larger applications (i.e. Office 97/2000, VB6, Informix). Most often the problem is related to unneeded and unreferenced string entries in the registry's Shared DLL key. The Shared DLL key is intended to store the path to all shared DLLs installed on the system. However, many applications use this as a repository for paths to non-DLL files which may not be installed in a customized or partial install, or which remain after an uninstall. VB6 is one such app that stores non-DLL data in this key. Because of the limit on the registry/key size, once the maximum has been reached the installer can't continue and the above (misleading) error is thrown.
VBnet has a
Microsoft utility - shrdll.exe - available
for download (less than 28k). Shrdll.exe is used to identify -- and optionally remove --
those errant entries in the registry's Shared
DLL section that consume valuable registry space but no longer point
to valid files. I have found that using this utility on machines
generating this error resolves the install problem, typically removing
about 25k of unneeded entries. It is perfectly safe - I use it
routinely on my own system after adding/removing programs. But
as it doesn't prepare an 'undo' file you are urged to export the
'Shared DLL' registry key if you are overly concerned.
|»||'Unable to register
<dllname>" error when installing an application onto a user's Windows 95 or Windows 98 machine.
See the solution to the above FAQ.
|»||Can I add my own
variables to a control event procedure in order to pass additional data
to the event?
No. Form and control events that are listed in the Object combo box in the code window can only use the event variables assigned by VB that make up the event's default declaration.
|»||I have a simple
project. Can I declare an API or user-defined type (UDT) just in a form?
Yes, however the declare or Type must be prefaced with the Private keyword. This restricts the scope of the variables (or APIs) to the form they are declared in. Be careful doing this, as its easy to forget to modify an API if a change is required when that API had been declared multiple times as Private in more than one form or module.
|»||How can I activate a
running app, or launch it if it is not running?
Declare the FindWindow and BringWindowToTop APIs in a form or module, then use:
Private Sub Command1_Click()
Dim hCalcWnd As Long
Dim x As Long
hCalcWnd = FindWindow("SciCalc", "Calculator")
If hCalcWnd = 0 Then
Call Shell("CALC.EXE", vbNormalFocus)
|»||How can I display an
ampersand (&) in a menu item or in a label?
The ampersand is a special symbol to windows denoting a keyboard accelerator key (underscoring the ALT+<key> used to access the command from the keyboard). To display an actual ampersand in a label or menu, use two ampersands together, i.e. 'Save && Exit' displays as 'Save & Exit'. Some controls also provide a UseMnemonic property that can be toggled to display the ampersand without resorting to doubling the characters.
Menus on Windows 2000
/ XP / Vista etc. no
longer show the keyboard accelerators (underlined Alt-letters)
The default setting for Windows 2000 is to hide keyboard accelerators until the user presses Alt. This is new behaviour. To configure Windows for the traditional (not to mention _expected_ behaviour), go to Control Panel, Display, Effects and uncheck the "Hide keyboard navigation until I use the Alt key" option.
How do I use an accelerator in a label to have the focus move to the
textbox or control associated with that label?
Label controls, although they support the ampersand accelerator and tabindex/tabstop, never actually receive focus. When a label is activated by the mnemonic key, control moves to the control having the next higher tabindex. So, by setting the tabindex of a textbox (or control) that you want to gain focus when the label mnemonic is pressed to 1 more than tabindex of the label, focus will move to that control when the accelerator key is pressed.
I've finished designing my form. Is there an easy way to set the
desired TabIndex for the controls at design time?
The easiest, sure-fire way of ensuring a user's tabbing between controls follows a route you desire is to set the TabIndex properties of all the controls backwards! Begin with the LAST control on the form that should receive focus using the Tab key, and set that control's TabIndex property to 0. Then move to the second-to-last control, and set that control's TabIndex to 0. Continue backwards through all the controls setting each control's TabIndex to 0 until you've assigned 0 to the first control on the form that will receive receive focus. All the tabs will be ordered ordered correctly - just run the project and hit tab to test the flow. The free mztools (www.mztools.com) also provides a gui-based tab reordering utility.
|»||How can I find out
how many MDI child forms are open in a MDI project?
The Count property of the Forms collection returns the number of forms currently loaded in the project. However, this number also includes the MDI parent form itself, as well as any other non-MDI child forms and hidden forms open in the project. To determine which open forms are actual MDI child windows, you can use:
Public Function GetMDIChildCount() As Integer
Dim frm As Form
Dim cnt As Integer
For Each frm In Forms
If (frm.MDIChild And frm.Visible) Then cnt = cnt + 1
GetMDIChildCount = cnt
Call the routine as:
NumberOfOpenForms = GetMDIChildCount()
|»||What is the easiest
way to find the number of open forms in my app?
There are two ways - equally easy. The first is to retrieve the form collection count...
numFormsOpen = Forms.Count
...and the second is to use the DoEvents function!...
numFormsOpen = DoEvents()
|»||How can I show the
Windows95/98 'Open With' dialog in response to a command button click?
The Open With dialog can be invoked with the following code:
Private Sub Command1_Click()
|»||How can my
application receive command-line parameters?
Simple. All command line parameters are passed to the VB program and are accessible via the Command$ function. Its fully documented in the VB help. Essentially its use is :
Public Sub Main Dim sParams as String sParams = Command$() <do something with sParams> frmMain.Show End Sub
|»||How do I call a
procedure in one form from a routine in another form in VB4/5/6?
In VB4/VB5/VB6, any new sub or function that you create in the form will be exposed to all other forms and bas modules if you declare the routine as Public. Note though that you can not invoke a control's event this way, that is, you can not use Form2.Command1_Click. The routines that are listed in the code window Object combo box are always private to that form unless you change them to Public. However, this practice is unnecessary as the control and its properties are available to other forms and modules, and can be fired by using the <formname>!<controlname>.<property> syntax, as in Form2.Command1.Value = True.
|»||How do I call a
procedure in one form from a routine in another form in VB3?
VB3 does not support Public routines in a form, so form-level routines are not directly callable from outside that form. Common or global routines must be declared in a BAS module.
|»||How do I declare a
constant to make it available to all procedures in all forms?
In a BAS module, place the words Public Const (VB4, VB5, VB6) or Global Const (VB2, VB3) before the variable assignment.
|»||How do I declare a
variable to make it available to all procedures in all forms?
In a BAS module, place the word Public (VB4, VB5, VB6) or Global (VB2, VB3) before the variable. You can also create private or public properties in BAS or CLS modules in VB5 and VB6.
What is the scope of
a variable DIM'med in different parts of a project? (excludes Static variables)
A variable DIM'med inside any sub or function (in any module or form) is local to that routine only (only known about by the dim'ming routine), and is destroyed upon exiting that routine.
A variable DIM'med as Private in the general declarations section of a Form is available only to routines in that form. The variable remains valid as long as the form is loaded.
A variable DIM'med as Public in the general declarations section of a Form (i.e. Public Foo As Long) is available to routines in that form by referencing the variable name (i.e. Foo), or to modules or forms other than the declaring form by explicitly referring to the variable with its form name as a prefix (i.e. Form1.Foo). The variable remains valid as long as the form is loaded.
A variable DIM'med Private in the general declarations section of a BAS module is available routines only in that bas module. The Private keyword is not available in VB2 or 3; use a standard DIM statement.
A variable DIM'med Public (or Global in VB2 or 3) in the general declarations section of a BAS module is available to all routines in all forms and bas modules.
A variable DIM'med inside any sub or function that has the same
name as a Public or Global variable takes precedence over the Public one in that routine where it is DIM'med. Its initial value
is 0 or empty. The Public variable's contents is not affected by use of the local variable of the same name. The local variable is
destroyed upon exiting that routine; the global variable remains valid. Download a VB4 demo
and view the code. Generally, using the same name for a Public and Local variable is considered poor programming practice.
Why do I get an Overflow
Error when multiplying:
Dim x as Long
...yet when I set the value x = 33000 directly, it works with no error?
Because the both data types being multiplied are integers, VB uses an integer as the temporary working variable. As the result of the multiplication exceeds 32k (the limit for an integer), VB is forced to toss an overflow error (even though VB itself was responsible for creating the error in the first place!)
To ensure that VB will use an internal temporary working variable of a data type sufficient to hold the result (as opposed to each item), you must assign a type-declaration character to one of the values in the expression. This, following the rules stated above, forces VB to use an internal temporary working variable of sufficient capability to hold the result, thus completing the action without error. For example:
x = 33 * 1000&
x will hold the correct result, since the expression indicated that 1000 was to be treated as a Long (even though the value 1000 fits inside an integer) and thus VB used a long to create its internal temporary working variable. However, be aware that the code:
x = 33 * 1000 * 100&
will still generate the error. In this case, despite the inclusion of the Long declaration character in the expression, VB must perform the calculation in parts. Since the expression did not contain brackets forcing one portion to be evaluated over another, VB attempts to compute the first part of the multiplication ( 33 * 1000 ) into its internal temporary working variable created it as an integer, again generating the error. The fix under these circumstances is, as above, to assign the long to the one of the first two values being evaluated largest value, or to bracket the equation to have VB perform the computation containing the long first:
x = 33 * 1000& * 100
|»||VB says I don't have a license to use my controls. Why?
When you try to use some components in VB5 or VB6, a message box appears with the message "License information for this component not found. You do not have an appropriate license to use this functionality in the design environment." The problem stems from missing registry information, and can be repaired by running the version-specific Microsoft license fix utility listed on under the Control Fix section on the Dev Resources page.
While these utilities will repair missing or damaged
registry entries for controls provided with your version of Visual
Basic, only those controls for which the VB version applies will be
repaired. In other words, if you are attempting to use a VB control
installed on your machine but not provided with your VB version (for
example you have Learning Edition and you are trying to use a control
provided with the Enterprise version) these utilities will not enable
use of those unlicensed controls.
How do I automatically maximize code windows in VB?
When using VB 6 in MDI mode, to force code/object windows to open maximized add a new key called 'MDIMaximized' to the registry as indicated below, and set its value to a string value of 1:
HKEY_CURRENT_USER/Software/Microsoft/Visual Basic/6.0/MDIMaximized = "1"
How can I prevent a single-selection VB listview control from automatically selecting the first item?
Execute this once all the items have been added to the listview. This only works for single-selection listviews:
If Not ListView1.SelectedItem Is Nothing Then ListView1.SelectedItem.Selected = False Set ListView1.SelectedItem = Nothing End If
How can I prevent a multiple-selection
VB listview control from automatically selecting the first item?
Execute this once all the items have been added to the listview. This works for single- and multi-select listviews:
Dim itmx As ListItem If Not ListView1.SelectedItem Is Nothing Then For Each itmx In ListView1.ListItems itmx.Selected = False Next End If
Using the API, how can I prevent the VB listview control from automatically selecting the first item in the list?
This takes a bit more code than above, but achieves the same result ...:
Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Const LVIF_STATE = &H8 Const LVIS_STATEIMAGEMASK As Long = &HF000 Const LVIS_SELECTED = &H2 Const LVM_GETSELECTEDCOUNT = (LVM_FIRST + 50) Const LVM_SETITEMSTATE = (LVM_FIRST + 43) Private Type LVITEM mask As Long iItem As Long iSubItem As Long state As Long stateMask As Long pszText As String cchTextMax As Long iImage As Long lParam As Long iIndent As Long End Type ' code ---- Dim lv As LVITEM Dim numSelected As Long With lv .mask = LVIF_STATE .state = False .stateMask = LVIS_SELECTED End With Call SendMessage(ListView1.hwnd, LVM_SETITEMSTATE, -1, lv)
How can I set focus to a specific control when the form first loads? Using .SetFocus causes an error.
Focus can only be set to a control that is visible. Until the Load event of a form has completed, the form and its constituent controls are invisible and attempting to SetFocus to a control from the Load event will throw an error.
To set the focus prior to displaying the
form you have two options: set the tabindex of the control to have initial focus to 0 - either
at design time or programmatically, or, in the Load event place an
explicit Me.Show statement just before the code to SetFocus. Note
however this last option is only available when the form is being
shown non-modally; attempting to execute a Show statement for a
modal form will generate an error.
I want to install Visual Studio (or Visual
Basic) on a new computer. Is there anything special I should know
The rule of thumb for installing any software onto a newer operating systems is to install the oldest applications first, then newer ones. For example, if you were installing Visual Basic 5, Visual Studio 6, Microsoft Office 2003, and Microsoft FrontPage 2002, you'd install VB5 first, then VS6, then FrontPage 2002, then Office 2003. I've used this rule when installing apps on all my systems from Win98 through XP and never had a problem at all.
Just be aware that when installing Visual Studio 6 or Visual Basic 6 on Windows XP, the installation CD will require that you first install the MS Java runtime, as on XP MS removed its java per agreement with Sun. Just do it and reboot, and the install will continue.
Remember to install the MSDN help afterwards (install will prompt you), unless you also have the later October 2001 MSDN library CD that also contains the VB help files. If you do have this later version of the MSDN you can skip the Visual Basic (or Visual Studio) MSDN install (say OK when warned that 'help will be unavailable'), and install the Oct 2001 MSDN instead. This will create/associate the MSDN with VB automatically and help will work as usual.