Home

A Form and its Environment

 

Forms Messages and Events

 

Creating a Form

When an application made of a form is launched, the form must be created to display to the user. As the form gets created, it initializes 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 during design, the code of this event would be created and made ready for you.

Practical LearningPractical Learning: Creating a Form

  1. To start a new project, on the main menu, click File -> New -> VCL Forms Application - C++Builder
  2. To use the OnCreate() event , double-click the middle of the form
  3. Implement the OnCreate event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
    	ShowMessage("The form has been created");
    }
    //---------------------------------------------------------------------------
  4. To test the application, press F9
  5. Close the form and return to your programming environment

 

Showing a Form

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.

Practical LearningPractical Learning: Showing a Form

  1. On the Object Inspector, click the Events tab
  2. Double-click the right field of OnShow and implement the OnShow() event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormShow(TObject *Sender)
    {
    	ShowMessage("The form is showing");
    }
    //---------------------------------------------------------------------------
  3. Press F9 to test the application
  4.  Then close the form and return to your programming environment

Activating a Form

When two or more forms are running on the computer, only one can receive input from the user. That is, only one form 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 color of the title bar is specified by the operating system and you can check it in the Appearance Settings from the Control Panel:

Display Properties

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 activate a form,  the user can click its button on the task bar. Another option includes pressing Alt + Tab continuously until the main form of the application is selected. When a form has been activated, it fires the OnActivate() event. OnActivate() is a TNotifyEvent type of event. To let you get a handle of the form that is active from the application, the TApplication class provides the  ActiveFormHandle property:

__property HWND__ * ActiveFormHandle = {read=GetActiveFormHandle};

To let you find out whether a certain form is currently activated or it is currently the active one, the TCustomForm provides a read-only Boolean property named Active:

__property bool Active = {read=FActive};

Practical LearningPractical Learning: Activating a Form

  1. On the Events tab of the Object Inspector, double-click the right field of OnActivate and implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormActivate(TObject *Sender)
    {
    	ShowMessage("The form is now activated");
    }
    //---------------------------------------------------------------------------
  2. Press F9 to execute the application to display the form
  3. Close the form and return to your programming environment

Deactivating a Form

If an application contains at least two forms and if both are currently displaying, the form behind the first is referred to as the inactive form. The title bar of that form uses a color set by the operating system and named the Inactive Window.

When a user clicks a form to active it, that form comes to the front and the other is sent to the back. The other form is said to be de-activated. When this is done, that form fires an OnDeactivate() event.

Practical LearningPractical Learning: Activating a Form

  1. In the Object Inspector, double-click the right side of OnDeactivate
  2. Iimplementit as follows:
        
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDeactivate(TObject *Sender)
    {
    	ShowMessage("Our form is deactivated");
    }
    //---------------------------------------------------------------------------
  3. Press F9 to execute the application to display the form
  4. While the form is displaying, open Notepad to deactivate the form
  5. From the taskbar, click the button of our form to activate it
  6. After experimenting with the form, close it and return to your programming environment

Painting a Form

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.

Practical LearningPractical Learning: Painting the Form

  1. From the Events tab of the Object Inspector, double-click the right side of OnPaint
  2. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    	ShowMessage("Window Painting: A hobby or a habit?");
    }
    //---------------------------------------------------------------------------
  3. Test the application and return to your programming environment

Resizing a Form

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.

Practical LearningPractical Learning: Resizing a Form

  1. On the Events tab of the Object Inspector, double-click the right field of OnResize and implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormResize(TObject *Sender)
    {
    	ShowMessage("Changing size or changing sides - Who knows?");
    }
    //---------------------------------------------------------------------------
  2. Execute the application
  3. Close the form and return to your programming environment

Attempting to Close a Form

To let the users close a form, the operating system provides the system Close button (, , or ). When the user clicks the system Close button, the form fires an OnCloseQuery event:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{

}
//---------------------------------------------------------------------------

The OnCloseQuery event is of type TCloseQueryEvent:

__property TCloseQueryEvent OnCloseQuery;

This event allows you to take some action before the form is actually closed. The CanClose argument allows you to decide whether you really want the form to be closed or not. If you want to prevent the form from being closed, set the CanClose argument to False. Consider the following example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
	CanClose = False;
}
//---------------------------------------------------------------------------

In this case, when the form displays, if user clicks the system Close button, the form will not be closed (you will have to give the user another way to close the form).

Closing a Form

When the user has finished using a form, he must be able to close it. To let you do this, the TCustomForm class provides a method named Close. Its syntax is:

void __fastcall Close();

When this method is called:

  • If the application has only one form, it (the application) would be closed
  •  If the application has more than one form:
    • If this method is called from the main form (the form specified as the default of the application), the application would be closed. That is, all forms would be closed
    • If this method is called from one of the form other than the default, only that form would be closed

As a 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:

Value Description
caNone The form must not be closed at all
caHide The form must be hidden but not closed
caFree The form must be closed and its memory freed
caMinimize The form must be minimized and not closed
 

Practical LearningPractical Learning: Attempting to Close a Form

  1. On the Events tab of the Object Inspector, double-click the right field of OnClose and implement the event as follows:
     
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
    	ShowMessage("Time to close");
    }
    //---------------------------------------------------------------------------
  2. Execute the application
  3. Close the form and return to your programming environment

Destroying a Form

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.

The Focus of a Form Children

Unless you are creating some type of a simple message box, a form usually has many controls so that a user can interact with it to create or get values. To use a control, the user usually has to click it or continually press Tab to activate a particular control. This gives focus to it. From the form's point of view, to give  focus to a control, the TCustomForm class provides the FocusControl() method. Its syntax is:

void __fastcall FocusControl(Controls::TWinControl * Control);

This method takes one argument as a pointer to the control that must receive focus. Of course, you must pass a reference to a control that exists on the form. If you pass the name of a control that cannot be found, you would receive an error.

An Application With Many Forms

 

Introduction

When you create a new VCL Forms application, you get a default form. If one form is not enough for your application, you can add as many as necessary. To add (or to create) a (new) form:

  • On the main menu, you can click File -> New -> Form - C++Builder
  • OOn the main menu, you can also click File -> New -> Other... or, on the Standard toolbar, you can click the New Items button. Then, in the New Items dialog box, double-click 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.

The Main Form of an Application

If you add more than one form to a project, the form that was created first is referred to as the main form. If/When you execute the application, that main form would display first. If you want, you can specify what form should come up first. To assist you with this, the TApplication class provides a property named MainForm:

__property Forms::TForm * MainForm = {read=FMainForm};

To visually specify the default form on an application, on the main menu, click Project -> Options... In the left list, click Forms. On the right side, click the arrow of the Main Form combo box to display the list of forms of the current application:

Project Options

Select the name of the desired form and click OK.

To programmatically specify the default form, in the project file of your application, arrange the sequence of form creation so that the desired form is on top. Here is an example:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
USEFORM("Unit2.cpp", Form2);
USEFORM("Unit3.cpp", Form3);
USEFORM("Unit4.cpp", Form4);
//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TForm3), &Form3);
		Application->CreateForm(__classid(TForm1), &Form1);
		Application->CreateForm(__classid(TForm2), &Form2);
		Application->CreateForm(__classid(TForm4), &Form4);

		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");
		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
		}
	}
	return 0;
}
//---------------------------------------------------------------------------

Because TApplication::MainForm is a read-only property, you cannot change it with code. You can only find out what form is set as the default by getting the value of this property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm4::Button1Click(TObject *Sender)
{
	ShowMessage(L"The main form is " + Application->MainForm->Name);
}
//---------------------------------------------------------------------------

You can use this information as you see fit.

Accessing the Other Form

If you visually add two (or more) forms to your application, you may need to link them, allow one to call the other. Since each form is created in its own unit, to let one form know about the existence of another, you must include its unit. A form or unit that wants to communicate with another is called a client of the form. For example, if Unit2 wants to use information stored in, or controlled by, Unit1, Unit2 needs to include Unit1 in its list of header files; and Unit2 becomes a client of Unit.

There are two simple ways you can include a unit's header in another file. Imagine you have created Form1 stored in Unit1 and Form2 stored in Unit2. If you want to have access to Form2 from Form1, using C++, on top of the source file of Unit1, include Unit2's header file. C++Builder provides another technique. After making sure that either Form1 displays on the screen or a Unit1 tab is displaying

  • On the main menu, you can click File -> Use Unit_X
  • Press Alt + F11

From the Use Unit dialog box, you would click the name of the unit you want to include to the current unit and click OK. C++Builder will automatically add the right and selected header to the client.

Practical LearningPractical Learning: Using Multiple Forms

  1. To create a new project, on the main menu, click File -> New -> Other...
  2. In the left list, click C++Builder Projects if necessary.
    In the right list, click VCL Forms Application
  3. Click OK
  4. In the Object Inspector, click the Properties tab if necessary.
    Click Caption and type Rapid Application Development
  5. CClick Name and type frmMain
  6. To add another form to your application, on the View toolbar, click the New Items button img alt="New Items" src="buttons/newitems1.gif" width="24" height="22">
  7. In the left list of the New Items dialog box, click C++Builder Files
  8. In the right list, click Form
  9. Click OK
  10. Click the Name field and change it to frmSecond
  11. As the new form is still selected, double-click in its middle to initiate its OnCreate event
  12. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmSecond::FormCreate(TObject *Sender)
    {
    	Width = 405;
    	Height = 350;
    	Caption = "I know you called me!";
    }
    //---------------------------------------------------------------------------
  13. To display the main form, on the main menu, click View -> Forms
     
  14. On the View Form dialog box, click frmMain
     
    View Form
  15. Click OK
  16. To include the header of the other form, on the main menu, click File -> Use Unit
  17. From the list, click Unit2.cpp
  18. In the Add To section, click the Header radio button
     
    Use Unit
  19. Click OK
  20. In the Object Inspector, click the Events tab and double-click the event field of the OnDblClick field
  21. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMain::FormDblClick(TObject *Sender)
    {
    	frmSecond->ShowModal();
    }
    //---------------------------------------------------------------------------
  22. To test the program, press F9
  23. Move the form from its current position by dragging its title bar
  24. To call the second form, double-click in the middle of the form
  25. After viewing the form, close it
  26. Also close the main form
  27. To add another form to your application, on the main menu, click File -> New -> Form - C++Builder
  28. In the Object Inspector, click the Properties tab
  29. Click Name and change the name of the new form to frmFloater
  30. In the Object Inspector, click the Events tab
  31. Click OnCreate and double-click the right field
  32. Implement the event as follows:
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    include "Unit3.h"
    // Include the dependent header file
    ##include "Unit2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TfrmFloating *frmFloating;
    //---------------------------------------------------------------------------
    __fastcall TfrmFloating::TfrmFloating(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TfrmFloating::FormCreate(TObject *Sender)
    {
    	// The appearance should be that of a floating window
    	BorderStyle = bsToolWindow;
    	// Keep this floating always on top
    	FormStyle = fsStayOnTop;
    	// Change the form's background color
    	Color = TColor(RGB(202, 238, 255));
    	// Make sure this window aligns with the top-left
    	// corner of the calling form
    	Top = frmSecond->Top;
    	Left = frmSecond->Left;
    	// Set the dimensions of the window
    	Height = 325;
    	Width = 124;
    }
    //---------------------------------------------------------------------------
  33. We will call the floating window from the second form. On the View toolbar, click the View Unit button View Unit
  34. On the View Unit dialog, click Unit2.cpp
     
    View Unit
  35. Click OK
  36. Press F12 to display the second form
  37. Press Alt + F11 to call the Use Unit dialog
  38.  Double-click Unit3
  39. In the Object Inspector, double-click the right side of OnClick
  40. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmSecond::FormClick(TObject *Sender)
    {
    	frmFloater->Visible = !frmFloater->Visible;
    }
    //---------------------------------------------------------------------------
  41. To test the program, press F9
  42. To display the second form, double-click the main form
  43. To display the floating form, click the second form. Notice that the floating window appears
  44. Move the second form and try to position it on top of the floating window. Notice that the floating window is always on top of the second window
  45. Click the second form again. Notice that the floating form reappears
  46. Click the second form again to display the floating window. Make sure the floating window displays
  47. Close the second form
  48. Close the first form also
  49. Display the second form
  50. In the Object Inspector, double-click the event field of OnClose
  51. Implement it as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmSecond::FormClose(TObject *Sender, TCloseAction &Action)
    {
    	if( frmFloater->Visible )
    		frmFloater->Close();
    }
    //---------------------------------------------------------------------------
  52. Press F9 to test the program
  53. Display the second form
  54. Click the second form to display the floating window
  55. Close the second form. Notice that the floating window has been closed
  56. Close the first form
 
 
 

Previous Copyright © 2010-2011 FunctionX, Inc. Next