|
The C# Column
Visual Inheritance
In
Visual Studio 6.0, to display a dialog box, we derive a class from
a pre-defined MFC class. The event handlers and variables associated
with controls get added to this user-defined class. All the information
about controls get stored in a separate .rc file. The
compiler creates and displays controls using information stored
in the .rc file. Visual Studio 6.0 IDE provides facilities
for adding controls, variables for controls and handlers.
So far so good. Now, consider a situation where an extensive user interface
on a dialog comprising of several controls exists and we want to reuse this
user interface in other application. What we would try is to inherit the dialog
class creating the user interface to create a new class. The major problem with
this is that although we get access to the base dialog class members, we dont
get controls placed on the new dialog. This is because the IDE of Visual Studio
6.0 has no means to access the .rc file and render the controls
according to the information stored in it.
So, our next step would be to copy all the controls from the existing dialog
template and paste them on the new dialog. Now we get the controls and the variables
and event handlers. But the problem here is that the code that associates controls
with their variables and handlers remains missing. So, reusing an existing user
interface is far more different and difficult than reusing an existing class.
Through Inheritance we create a new class by using an existing
class. Through Visual Inheritance we create a new form by using
an existing form. When we inherit a form from an existing form we also inherit
controls, their properties, events and methods. So, the user interface that
is already created can be reused in a new application thereby reducing the repetitive
designing of controls. This makes visual inheritance a powerful weapon in this
era of Rapid Application Development. We can use visual inheritance in cases
where we need to use the same set of controls again and again.
Visual Studio.NET has incorporated visual inheritance as a part of the .NET
framework. Visual inheritance is so called because it gives the visual expression
of the inherited control objects. Using visual inheritance is a two-step process:
- Creating Base Form
- Creating Derived Form
These steps are explained below.
Creating Base Form
Carry out the following steps to create a Base Form.
(a) Create a Windows application named baseform.
(b) Add a button having label as Click and name as b. Also add a
text box having name as t. By default, these variables get added as private
data members. Change the access modifiers to public through the Modifiers property.
If we change the Modifiers property of a control to protected or public we will
be able to change its properties in the derived form. The controls marked as
private in the base form will be visible on the derived form but will not be
accessible through its name. This seems relevant because in OOP inheritance
also only protected and public members of a base class are visible to its derived
classes. In any case, we would not be able to delete the derived controls from
the form.
(c) Add the Click event handler for the button and add following statement in
it.
MessageBox.Show ( t.Text ) ;
(d) Now since our form stands ready we can build it into a class library so
that we can export the form. Note that we cannot import a form from an exe file.
To build the project in a class library, right-click the solution name in Solution
Explorer and select Properties. The baseform Property Pages gets
displayed. Select the Output Type as Class Library, as shown in the following
figure.

Now build the project to create baseform.dll. This assembly contains
the baseform.Form1 class that we can inherit.
Creating Derived Form
(a) Create another Windows Application named derivedform.
(b) Right-click the solution name in Solution Explorer and select the Add
| Add Inherited Form menu option. The Add New Item dialog
box gets displayed.
(c) Select the Inherited Form from the Templates list
and provide a name of your choice in the Name text box. We have
kept the default name Form2.cs. This is shown in the following figure.

(d) The Inheritance Picker dialog gets displayed. This dialog
allows us to select an assembly that contains the form we want to inherit. For
this, click the Browse button. A dialog appears from where we can
select the baseform.dll file and click the Open button.
(e) Clicking the Open button dismisses the dialog and displays the
forms exported by the assembly (an assembly can export any number of forms)
in Specify the component to inherit from list control.
(f) Select the form name from the Specify the component to inherit from
list control and click the OK button. As soon as we click the OK
button, a new form derived from the baseform gets displayed in the
design editor. The file Form2.cs also gets displayed in the Solution
Explorer as shown in the earlier figure.

The figure also displays the reference of baseform.dll being added
in the References tree in the Solution Explorer. The derived form
displays the derived controls being added to the base form. These controls are
accompanied by a small icon at the top left corner to distinguish between the
derived controls and the new controls.
(g) Open the Form1.cs file. Change form name in Application.Run(
) method to Form2 as shown below.
Application.Run ( new Form2( ) ) ;
This ensures that when we execute the application, the new form, i.e. Form2,
gets displayed. If we enter the text in the textbox and click the button the
text gets displayed in a message box.
Let us now see how the whole thing works. To begin with, the statement Application.Run
( new Form2( ) ) gets executed. Here we are creating an object of the Form2
class which is derived from the baseform.Form1 class. When we create an object
of derived class, the base classs constructor gets called. So, in our
case the constructor of the baseform.Form1 class would get called. This class
is accessible to us since a reference to the baseform.dll assembly
is already being added to our project.
The compiler adds a call to the InitializeComponent( ) method in the constructor
of every form class. The InitializeComponent( ) method contains the code for
creating and customising the controls. Once this method gets executed and controls
get created, the control returns to the constructor of the Form2 class. This
constructor again calls the InitializeComponent( ) method. This time the InitializeComponent(
) method of the Form2 class gets called. This is the reason why derived form
contains the derived controls (initialised by InitializeComponent( ) method
of the baseform.Form1 class) and the new controls (initialised by InitializeComponent(
) method of the Form2 class).
We have already added the Click event handler
for the Click button. We can override this handler in
the Form2 class and add our code in it. Now if we click the button,
firstly, event handler of the base class gets executed and then
the overridden handler gets executed. This is because, the InitializeComponent(
) method of the baseform.Form1 class gets executed first, wherein,
an address of the Click event handler defined in the baseform.Form1
class gets stored in the Click delegate. Next the InitializeComponent(
) method of the Form2 class gets executed. In it, the address of
the Click event handler defined in the Form2 class gets added to
the Click delegate.
 |
Yashavant Kanetkar, one of the first
Express Computer columnists, is an established software expert,
speaker and author with several best-sellers to his credit,
including titles like “Let Us C” and the “Fundas” series. Contact
him at kanetkar@dcubesoft.com |
|