![]() |
The Form |
|
Characteristics of Forms |
|
Introduction |
|
The form is the primary object of a VCL application. It is rectangular window whose main purpose is to carry, host, or hold other controls to allow the user to interact with the computer. Although there are various types of parent containers we will use, the form is the commonly and regularly used. When C++ Builder starts, it creates a starting form and initializes an application. You can use such as form as you see fit. If you need additional forms, you can create them visually by clicking File -> New -> Form on the main menu. You can also click the New Form button on the Standard toolbar. Alternatively, you can display the New Items dialog box from where you would select the Form icon. |
|
Another technique you can use is to create a form programmatically. To do this, declare a pointer to the TForm class using the new operator. Like every other control, you must specify the owner of the form that will be responsible for destroying it. This owner is usually the form that is calling it.
The top section of a form or a dialog box is called a title bar:
On the left side of the form's title bar, there is a small picture called an icon. By default, C++ Builder uses an icon shipped with the compiler. If you want to use your own icon, you can specify it using the Icon property. To do this, on the Object Inspector, you can either double-click the (None) value of the Icon field or click the ellipsis button of the field. This would call the Picture Editor dialog box: |
|
After selecting the icon and clicking Open, the icon would be made available in the Picture Editor dialog box:
After clicking OK, the new icon would be used as the system icon of the form:
The icon used on the title bar possesses a menu called the system menu. This menu displays if you click the icon:
The system menu of the icon's title bar allows you to perform the common actions of a regular Windows form. If you do not want to display the icon and its menu, refer to the section on the BorderIcons below.
On the right side of the system icon, there is long bar that is actually usually referred to as the title bar. This section displays a word or a group of words known as the caption of the form. By default, the title bar displays the name of the form. To customize the text displayed on the title bar, on the Object Inspector, change the text of the Caption property. At design time, you can only set the caption as text. The caption can be any type of string. At run time, you can control and programmatically display anything on the caption of the form. It can consist of an expression or the result of a calculation. To change the caption at run time, you can use a function, a method, or an event. Just type “Caption = “ and the sentence you want. For example, you can display today’s date on the caption as follows: //---------------------------------------------------------------------------
void __fastcall TForm1::ChangingFormCaption()
{
Caption = "Today is " + Date();
}
//---------------------------------------------------------------------------
You can also indirectly control the caption. For example, after the user has typed his or her name in an edit box, you can display it in the form’s caption as follows: //---------------------------------------------------------------------------
void __fastcall TForm1::ChangingFormCaption()
{
Caption = Edit1->Text;
}
//---------------------------------------------------------------------------
On the right side caption, there are three system buttons that allow minimizing
The BorderIcons property is a (Pascal-style) set, which means it can use one or more values in any allowed combination. Each member of the set can have a true or false value. If you set the biSystemMenu property to true, regardless of the values of the other fields of the BorderIcons property, the form would have neither the system icon (which also makes the system menu unavailable) nor the system buttons. If a form does not have a system close button, you should make sure the user has a way to close the form:
Using a combination of the biSystemMenu, the biMinimize and the biMaximimize properties, you can control the availability of the system buttons:
You can also programmatically control the system buttons. Since the BorderIcons property is a set, you must use the overloaded extractor operators. To remove or set a property to false, use the >> operator. To include or set a property to true, use the << operator. For example, to set the
biSystemMenu property to false, you can use code such as: //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
BorderIcons = TBorderIcons() >> biSystemMenu;
}
//---------------------------------------------------------------------------
biSystemMenu = true //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
BorderIcons = TBorderIcons() << biSystemMenu >> biMinimize << biMaximize;
}
//---------------------------------------------------------------------------
biSystemMenu = true //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
BorderIcons = TBorderIcons() << biSystemMenu << biMinimize >> biMaximize;
}
//---------------------------------------------------------------------------
biSystemMenu = true is equivalent to: //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
BorderIcons = TBorderIcons() << biSystemMenu >> biMinimize >> biMaximize;
}
//---------------------------------------------------------------------------
If you do not explicitly define the values of the BorderIcons, by default, the form would be equipped with all system buttons.
One of the ways you can use the title bar is to move the form at design time. The location of a form is set at design time because the VCL provides another property that follows the directives of the design. At design time, you can position the form anywhere on your screen and when you run the application, the form would appear following that position. This is based on the fact that the position of the form is controlled by the TPosition enumerator. The default position of the form is recognized as the way it was designed if you do not change the Position property. The default value of the Position property is poDesigned.
One of the most visual aspects of an object's appearance is its border. A border is a line that sets the visual limits of an object. Most objects, including a form, have four borders: left, top, right, and bottom. In VCL applications, the borders of a form are controlled by a property called BorderStyle. This is also the main property that specifies whether you are creating a regular form or a dialog box. To control the appearance of the borders of your form, on the Object Inspector, if you click BorderStyle, you would see that it is a combo box property. The BorderStyle property is an enumerator and you can choose one of its values needed for your form.
To change a property programmatically, assign one of the above values to the BorderStyle variable. Here is an example that would transform the form in a dialog box: //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
BorderStyle = bsDialog;
}
//---------------------------------------------------------------------------
When a form appears as it was designed, it is said to be "normal". C++ Builder allows you to have the form minimized or maximized when the application is launched. This ability is controlled by the WindowState property. The default value of this property is wsNormal, which means the form would appear in a normal fashion. If you want the form to be minimized or maximized at startup, in the Object Inspector, select the desired value for the WindowState property. To control the window’s state programmatically, simply assign the wsMaximized or the wsMinimized value to the WindowState property. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
WindowState = wsMaximized;
}
//---------------------------------------------------------------------------
If you want to check the state of a window before taking action, simply use a conditional statement to compare its WindowState property with the wsNormal, the wsMaximized, or the wsMinimized values. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
if( WindowState == wsNormal )
WindowState = wsMaximized;
else if( WindowState == wsMaximized )
WindowState = wsMinimized;
else
WindowState = wsMaximized;
}
//---------------------------------------------------------------------------
The area that a form makes available to its control is its body. As the main container of Windows controls, a form provides some particular properties to the controls it hosts. The client area of a form is represented by the ClientRect property. This property can be used to get the dimensions of the body of the form. Like the TControl::ClientRect property, the TForm::ClientRect property provides the width and the eight of the client area, omitting the location (left and top) which is set to the client origin (0, 0) located on the top-left corner of the body of the form. Alternatively, to get the width of the client area of the form, you can call the ClientWidth property. To get the height of the client area, use the ClientHeight. The client aspects can be illustrated as follows:
Overall, you will hardly be concerned with the dimensions of the client area, unless you want to draw or render an image. If you do not have a particular reason, let C++ Builder take care of the client area.
An object is referred to as transparent when you can see through it. If you are working under Windows 2000 or later running on a Pentium or equivalent, you can make your form transparent. To create a transparent form, set the AlphaBlend Boolean property to true from its default false value. Once this property is set to true, you can use the AlphaBlendValue property to set the degree of transparency. The value must be a BYTE integer between 0 and 255. At 0, you would not see the form at all. The only presence of the form would be on the taskbar. At 255, the form would appear as if the property were not applied.
The form in implemented by the TForm class which itself is derived from TCustomForm. Like every other control, the form is equipped with a constructor that allows you to dynamically create it.
When the user has finished using a form, he or she must be able to close it. Closing a form is made possible by a simple call to the Close() method. Its syntax is: void __fastcall Close(); Although this method can be used to close any form of an application, if it is called by the main form, it also closes the application.
When an application made of a form is launched, the form must be created to display to the user. At the form gets created, it initialize its controls. This is done before the form can display to the screen. At this time the OnCreate() event fires. This is a TNotifyEvent event, which means that it does not take any argument other than the Sender, which is a TObject type. OnCreate() is the default event of a form. This means that if you double-click the form, the code of this event would be created and made ready for you.
After the form has been created, it must display to the user. If the application contains more than one form, you can display it. To display a form, just like any control, we saw that the TControl::Show() method must be called. If the application is being launched, it would call this method to display the main form of the application. If you have more than one form and you want to display the other form, you can call the TControl::Show() method. When the TControl::Show() method is called, the OnShow() event is fired. This allows you to perform any last minute processing before the form can display.
When two or more forms are running on the computer, only one can receive input from the user, that is, only one can actually be directly used at one particular time. Such a window has a title bar with the color identified in Control Panel as Active Window. The other window(s), if any, display(s) its/their title bar with a color called Inactive Window:
To manage this setting, the windows are organized in a 3-dimensional coordinate system and they are incrementally positioned on the Z coordinate, which defines the (0, 0, 0) origin on the screen (on the top-left corner of your monitor) with Z coordinate coming from the screen towards you. In order to use a form other than the one that is active, it must be activated. To do this, the OnActivate() event must be fired. OnActivate() is a TNotifyEvent type of event. If there is more than one form or application on the screen, only one can be in front of the others and be able to receive input from the others. If a form is not active and you want to bring it to the top, you must activate it, which sends the OnActivate() event. When a form is being activated, the one that was on top would become deactivated. The form that was on top, when losing focus, would fire the OnDeactivate() event.
Whether a form has just been created or it needs to be shown, the operating system must display it on the screen. To do this, the form colors and other visual aspects must be retrieved and restored. This is done by painting it (the form). If the window was hidden somewhere such as behind another window or was minimized, when it comes up, the operating system needs to paint it. When a form gets painted, it fires the OnPaint() event. This event also is a TNotifyEvent type.
When using an application, one of the actions a user can perform on a form is to change its size, provided the form allows it. Also, some time-to-time, if possible, the user can minimize, maximize, or restore a window. Whenever any of these actions occur, the operating system must keep track of the location and size of a window. For example, if a previously minimized or maximized window is being restored, the operating system must remember where the form was previously positioned and what its dimensions were. When the size of a form has been changed, it fires the OnResize() event, which is a TNotifyEvent type.
As mentioned above, the user can close the form after using it. When the form is being closed, it fires the OnClose() event. This gives you the opportunity to perform any last minute processing such as finding out some information about the application or the form itself before the form is actually closed. The OnClose() event is a TCloseEvent function pointer whose syntax is: void __fastcall OnClose(TObject *Sender, TCloseAction &Action); When the form is being closed, you can use the Action argument to specify how you want the closing to be performed. This argument is a value of the TCloseAction enumerator whose members are:
Once the form has been closed, the operating system must destroy it and reclaim the memory space it was using. This causes the OnDestroy() event to fire. OnDestroy() is a TNotifyEvent. If you had dynamically created some controls using the form’s OnCreate() event, use the OnDestroy() event to destroy them.
When you start Borland C++ Builder, it creates a starting form for you. If one form is not enough for your application, you can add as many as necessary. To add (or to create) a (new) form:
Any of these techniques will add a new form to your application. If your
application is using various forms and you want to display a particular one at
design time, on the main menu, you can click View -> Forms, which would open
the View Form dialog box. From there, you can select the desired form and click
OK.
Besides designing a form visually, sometimes this will not be possible. You may have to create the form dynamically. To create a form dynamically, declare a pointer to a TForm class. If you want to quickly use a form in a function or an event, you can create it easily. There are two options you have. If you want to create a duplicate of the form you already have, you can use it as the base class and simply create an instance of the form using the new operator. When dynamically creating a form, you must specify the object or form that "owns" the form. If you are creating a duplicate of the form, set the owner as the current form or the this pointer. The owner is provided to the constructor. For example, to create a duplicate form using a form’s OnDblClick event, you can implement the event as follows: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm1* Former = new TForm1(this);
}
//---------------------------------------------------------------------------
The problem with a duplicate is that, unless you go through a big deal of code writing, every time you do anything on the form, the duplicate produces the same action. Therefore, the second option consists of creating a fresh form. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm* Former = new TForm(this);
}
//---------------------------------------------------------------------------
The biggest problem with a locally created form is that it is available only in the event or the function in which it is created. If you try to access it outside, you would receive an error. If you want a form to be available to more than one event or function, you must create it in a header file of an existing form. If you want the form to be available outside of the parent form that “owns” the header file, you must declare it in the public section. Otherwise, you should declare it in the private section: //---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
TForm* Comet; // A dynamically created form
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
After declaring the form, you can use the constructor of the host form to initialize the dynamic form. This is done by using the new operator and initializing the TForm class with the this pointer. Here is an example: //---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Comet = new TForm(this);
}
//---------------------------------------------------------------------------
Whatever technique you use to create your form, you can set its properties using code. The most basic thing you should do is to display it. This is done using the TForm::Show() method. If the form was created locally, you must display it in the function or event where it was created: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm* Former = new TForm(this);
Former->Show();
}
//---------------------------------------------------------------------------
After creating and using a form, you should make sure the memory allocated to it is regained. The Borland C++ Builder compiler can take care of cleaning your dynamic controls when the application exists. Otherwise, you can delete it manually: delete MyForm; Furthermore, to avoid any memory leak, you can reclaim the dynamically allocated memory by assigning NULL to the deleted object: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm1 *Cosmos = new TForm1(this);
Cosmos->ShowModal();
delete Cosmos;
Cosmos = NULL;
}
//---------------------------------------------------------------------------
Imagine you dynamically declare an object, such as a form, as follows: //---------------------------------------------------------------------------
class TForm1 : public TForm
{
...
private: // User declarations
TForm* Fake;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
We have seen that you can initialize it in the constructor of the form that owns your object: //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Comet = new TForm(Form1);
}
//---------------------------------------------------------------------------
Once the dynamic object has been initialized you can display it any time you choose. For example, you can do this when the user double-clicks in the primary form: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
Comet->Show();
}
//---------------------------------------------------------------------------
Over all, the C++ Builder compiler takes care of deleting the dynamic object when the form that owns it is closed. If you want to make sure that your dynamic object is destroyed, you can use the delete operator as seen above. In reality, since you can use your judgment to decide when the object would be displayed, when the form that owns it is closed, before deleting the dynamic object, you can first find out if the object was really created. This can be performed with a simple if statement. The best place to destroy a dynamically created object that a form owns is when the form is destroyed. When a form is being closed, it fires the OnDestroy event. This is the favorite place to perform any housecleaning necessary and related to the form. Based on this, you can destroy the above Fake object as follows: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if( Fake )
{
delete Fake;
Fake = NULL;
}
}
//---------------------------------------------------------------------------
|
| Previous | Copyright © 2005-2007 Yevol | Next |