
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:
- 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.
- Add the control to the Controls collection.
- Set the control's Visible property to True. By default, the Visible property of dynamically created controls is
False
- Size and position the control. This is usually done in the form's Resize
event procedure.
- 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

|