In C++ Builder, we can create many Units to run different modules with different Form designs in Windows. A unit is a separately compiled module of C++ Builder code. Every form has its unit, and most components (or groups of related components) have their units as well. A Unit shaped with two files,
- Header file (
<unit name>.hpp
) , it is used to define classes, components, variables and to define some function definitions. - Implementation file (
<unit name>.cpp
) It is used to define sub-functions, a main program with a header.
We can use properties of components as a variable that they are defined in units. Here we explained well about Using Variables in C++ Programming Language (link will be added later). We can define global variables or local variables in each unit. We can define private, public or __published variables in classes too.
In this post, we will learn how to interact with variables in two units. To learn this;
1. Let’s create a new C++ Builder VCL Application and save all project and unit.
2. Add a Button and an Edit box by dragging from the Palette. Now let’s examine what happened in our auto-generated codes. Cpp File (Implementation File) is like this,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- |
cpp file will have <vcl.h> library included and “Unit1.h”. It will have a TForm1 procedure which is used on form generation.
If we look at Unit1.h file we will see our Button1 and Edit1 components are defined as pointers automatically in __published: section of TForm1 class;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <Vcl.Controls.hpp> #include <Vcl.StdCtrls.hpp> #include <Vcl.Forms.hpp> //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; TEdit *Edit1; private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif |
This means we can use these components like Form1->Edit1 or Form1->Button1. In Classes,
__published: this section is used to define variables which are auto generated by IDE
private: this section is used for private user declarations, these can not be used by other units,, classes or functions, something like a local variable defined in a class
public: this section is used for general user declarations, these can be used by other units,, classes or functions, it is something like a global variable defined in a class
2. If we double click to Button1 you will see that our cpp will have new OnClick() event, modify inside it as below to see text in Edit1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage(Form1->Edit1->Text); } |
and you will see this Buttoon1Click() procedure definition is also declared in __published: section of Form1. Here we can use Edit1->Text in our Button1Click() too;
1 2 3 |
ShowMessage(Edit1->Text); |
Because, If you look at to Unit.h header, Button1Click() is defined as a part of Form1 class, and Edit1 is also part of Form1 class,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <Vcl.Controls.hpp> #include <Vcl.StdCtrls.hpp> #include <Vcl.Forms.hpp> //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; TEdit *Edit1; void __fastcall Button1Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif |
3. Now let’s create a new Unit. Select File-> New-> VCL Form — C++ Builder menu to create a new Unit, it will automatically have Unit2 name
4. Add an Edit box and a Button to Form2, Double click to Button1 and
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <vcl.h> #pragma hdrstop #include "Unit2.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm2 *Form2; //--------------------------------------------------------------------------- __fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm2::Button1Click(TObject *Sender) { ShowMessage(Edit1->Text); } |
At this point, note that now we have two Units ( Unit1 and Unit2 ) and each Unit has Button1 and Edit1 components. Now, how we can see Text of Edit1 of Unit2 from the Unit1? To interact between units you must add their header files. Both cpp files of Units should have both Units, please add missing headers to cpp files of modules as below,
Unit1.cpp should have,
1 2 3 4 |
#include "Unit1.h" #include "Unit2.h" |
Unit2.cpp should have,
1 2 3 4 |
#include "Unit2.h" #include "Unit1.h" |
Now both units has both headers, so we can interact with them. For example, we can show Text of Edit1 from Form2 in Form1 as shown Unit1.cpp below,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <vcl.h> #pragma hdrstop #include "Unit1.h" #include "Unit2.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage(Form2->Edit1->Text); } |
We can do same on the Unit2.cpp as below;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <vcl.h> #pragma hdrstop #include "Unit2.h" #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage(Form1->Edit1->Text); } |
As you see both Units has both headers and and we just add Form1-> or Form2-> to see it’s members.
How do I use Global Variables between Units?
We can also use Global Variables, let’s define a global mytext in the Unit1.cpp like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <vcl.h> #pragma hdrstop #include "Unit1.h" #include "Unit2.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; String mytext = L"This is Global"; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage(mytext); } |
To use this global in Unit2.cpp we should use extern command as below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <vcl.h> #pragma hdrstop #include "Unit2.h" #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; extern String mytext; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ShowMessage(mytext); } |
As you see, in this example mytext is defined as a global in Unit1 and we obtain it in Unit2 by using extern command. Note that this is same on FMX applications too. In general, using variables in Classes is much more safe about memory management. So avoid to use global variables or be careful when using them, do not forget to free them if they have been allocated in the memory.
Design. Code. Compile. Deploy.
Start Free Trial
Free C++Builder Community Edition