Windows DevCenter    
 Published on Windows DevCenter (http://www.windowsdevcenter.com/)
 See this if you're having trouble printing code examples


Date: Nov 2 1999
From: Pascal Klunder
To: ron@oreilly.com
Subject: Creating Dynamic Controls in a Form

Ron,

I'm trying to understand the technique of creating dynamic controls in a form, but with no success!

My problem: ability of dynamically creating 5 or more label and textbox controls.

Solution:
dim Label1 as Label
dim Label2 as Label
( ... )
set Label1= ... ?
set Label2= ... ?

Thanks for any help,
Pascal


Hi Pascal,

For those who don't know about it, dynamic control creation is one of the neatest features found in Visual Basic 6.0, which was released a little over a year ago, in mid-1998.

I've always found that it helps to have a system for understanding why a particular feature is implemented in a particular way. It helps to minimize what is otherwise a confusing array of details that we have to memorize and handle. So let's see if we can introduce some method in VB's madness before we take a look at some code to actually create controls dynamically.

At runtime, the components of a VB user interface form a clear object hierarchy. Every application with a user interface has a Forms collection. The Forms collection contains Form objects, each of which represents a form in the application. Each Form object in turn has a Controls collection, which has one Control object for each control on the form.

In most object models, only a relatively few objects -- typically those at the top of the object model -- are creatable. (Creatable objects are those that can be created by calls to the VB CreateObject function or that can be instantiated using the New keyword.) This makes a good deal of sense, since it prevents us from creating objects outside of and independently of the context and the hierarchy that gives those objects meaning.

A Control object is a good example of this. If abstracted from the form that contains it, a Control object is worse than useless; it will worsen our application's performance without providing any tangible benefit. As a result, Control objects are not creatable. That is, code such as

Dim oTxtName As New TextBox

or

Dim oTxtName As TextBox
Set oTxtName = New TextBox

will not succeed in creating a new textbox control; instead, it generates the compiler error, "Invalid use of New keyword."

When objects are not createable, the most common method of instantiating a new object of that type is to call a method belonging either to its parent object or to its container object. In the case of a Control object, since the object belongs to the Controls collection, you instantiate a new control and retrieve a reference to it by calling the Controls collection's Add method. Its syntax is: (Click here for code example)

with the following parameters:

ProgID
The programmatic identifier of the control to be created. A programmatic identifier is an arbitrary string that can be used instead of a class identifier to identify a class. ProgIDs are defined as direct subkeys of the top-level HKEY_CLASSES_ROOT key in the registry.

Name
The name by which the control is to be referred in code.

Container
A reference to the control's container object. Its default value is Me, the form to whose Controls collection the control is being added. It can also be a reference to any container object (such as a Frame control or a PictureBox control) on the same form.
So to create your label and textbox controls, you'd need code like the following: (Click here for code example)

In other words, dynamically creating a control requires that you perform the following steps:

  1. Declare the control variable using the WithEvents keyword, which allows it to receive event notification from the VB runtime engine. (The WithEvents keyword can be omitted if you're not interested in responding to the control's events. The declaration of the Label control in the code sample, for instance, doesn't include the WithEvents keyword, since presumably the program will simply work with the control's properties and methods while ignoring its events.

  2. Add the control to the Controls collection.

  3. Set the control's Visible property to True. By default, the Visible property of dynamically created controls is False

  4. Size and position the control. This is usually done in the form's Resize event procedure.

  5. If you're trapping any of the control's events, add any necessary event code.
Many programmers erroneously believe that you can add only intrinsic controls to your form in this manner, using the ProgIDs shown in Table 1.

Table 1. ProgIDs of VB's intrinsic controls
Control ProgID
CheckBox VB.CheckBox
ComboBox VB.ComboBox
CommandButton VB.CommandButton
Frame VB.Frame
HScrollBar VB.HScrollbar
Image VB.Image
Label VB.Label
Line VB.Line
ListBox VB.ListBox
OptionButton VB.OptionButton
PictureBox VB.PictureBox
Shape VB.Shape
TextBox VB.TextBox
Timer VB.Timer
VScrollBar VB.VScrollBar

In fact, however, you can add any ActiveX control to your form dynamically, as long as you have the correct ProgID. As I mentioned, ProgIDs are defined in the registry and take the general form

Library_Name.Control_Name

If you don't know quite where to search in HKEY_CLASSES_ROOT, you can use the Object Browser to get the correct ProgID. Just add the control to your project, open Object Browser, and select the control name in the classes list box. The Object Browser's status pane will then display the control name and the library name. For instance, Figure 1 shows that the ProgID for the TreeView control is

ComctlLib.Treeview

Click here for Figure 1. The Object Browser displaying a ProgID

There's one slightly unexpected twist to all of this. Because the Controls collection is dynamic, and because it can hold Control objects of various types, Visual Basic doesn't know at runtime what controls will belong to the collection. As a result, the Controls collection is late-bound. This means that all of the coding aids that we've come to expect from VB -- and particularly Auto List Members and Auto Quick Info -- are unavailable when doing the coding to create dynamic controls. It also means that dynamic control creation won't offer as good performance as the more traditional methods of creating controls, namely using drag-and-drop control creation or adding members to control arrays dynamically at runtime.

If you're interested in exploring the topic of control creation in greater detail, you might be interested in taking a look at the book Visual Basic Controls in a Nutshell, written by Evan S. Dictor and published by O'Reilly & Associates.

-- Ron

Return to: Ron's Archive

Copyright © 2009 O'Reilly Media, Inc.