Building VCL Components with CBuilder

Building VCL Components with C++Builder

If you don't have an existing package that you use, the first thing that you need to do, in both Delphi and C++, is to create a new package. To create a C++ package, select File ® New ® Package - C++ for Win32.

Once you've created the package, save it to disk, and then select Component ® New VCL Component to start building your new component. The IDE will, based on the package that you've created earlier, know that you want to create a C++ VCL component. If you don't open a package before starting to create a new component, the first page on the New VCL Component wizard will ask you to select the language you want to use and the platform you wish to target.

image from book
Figure 24-25: Building a component without an opened package

But when you first open a package and then select to create a new VCL component, the first page in the New VCL Component wizard will ask you to select the ancestor class of your new component. Select TComponent as the ancestor class and press Next.

On the Component page of the wizard, type TCPPSimple in the Class Name text box and My CPP Components in the Palette Page text box, and press Next to go to the final page. Since the final page only informs you that a unit will be created for the component, press the Finish button to finish building the component.

The New VCL Component wizard will create a source and a header file for the component. Before you add any code to the component, you should save it, in this case under CPPSimple. Delphi will use this name for both the source and the header file. Listings 24-15A and 24-15B show the component's source and header files.

Listing 24-15A: TCPPSimple component's source file

image from book
#include <vcl.h> #pragma hdrstop #include "CPPSimple.h" #pragma package(smart_init) //------------------------------------------------------ // ValidCtrCheck is used to assure that the components // created do not have any pure virtual functions. // static inline void ValidCtrCheck(TCPPSimple *) {    new TCPPSimple(NULL); } //----------------------------------------------------------- __fastcall TCPPSimple::TCPPSimple(TComponent* Owner)    : TComponent(Owner) { } //----------------------------------------------------------- namespace Cppsimple {    void __fastcall PACKAGE Register()    {       TComponentClass classes[1] = {__classid(TCPPSimple)};       RegisterComponents("My CPP Components", classes, 0);    } } //-----------------------------------------------------------
image from book

Listing 24-15B: TCPPSimple component's header file

image from book
//---------------------------------------------------- #ifndef CPPSimpleH #define CPPSimpleH //---------------------------------------------------- #include <SysUtils.hpp> #include <Classes.hpp> //---------------------------------------------------- class PACKAGE TCPPSimple : public TComponent { private: protected: public:    __fastcall TCPPSimple(TComponent* Owner); __published: }; //---------------------------------------------------- #endif
image from book

Finally, when you've saved the component's files to disk, right-click the package file (CppPackage.bpl) in the Project Manager and select Add on the context menu to add the component to the package. If you want, you can right-click the page file again and select Install on the context menu to add the newly created component to the Tool Palette, as shown in Figure 24-26.

image from book
Figure 24-26: A simple C++Builder VCL component

Creating Properties

Properties in C++Builder VCL components are created with the reserved word __property, using the following syntax:

/* Read-only property */ __property DataType PropertyName = {    read = Variable or Function }; /* Complete property that can be read   from and written to. */ __property DataType PropertyName = {    read = Variable or Function,    write = Variable or Function }; 

Based on the above syntax, here's the MyString property in C++:

class PACKAGE TCPPSimple : public TComponent { private:    AnsiString FMyString; protected: public:    __fastcall TCPPSimple(TComponent* Owner); __published:    __property AnsiString MyString = {       read = FMyString,       write = FMyString    }; };

To give the property a default value, you have to use the reserved word default inside the property block and also assign the same value to the underlying field in the component's constructor. Here's the MyInteger property with a default value of 20:

class PACKAGE TCPPSimple : public TComponent { private:    int FMyInteger; protected: public:    __fastcall TCPPSimple(TComponent* Owner); __published:    __property int MyInteger = {       read = FMyInteger,       write = FMyInteger,       default = 20    }; }; __fastcall TCPPSimple::TCPPSimple(TComponent* Owner)    : TComponent(Owner) {    FMyInteger = 20; }

Methods and Events

Adding methods and events to a C++ VCL component is as simple as it is in Delphi. To see how to create methods and events, let's implement the OnAccess event we implemented in the Delphi TSimple class.

To implement the OnAccess event, you'll need to add a TNotifyEvent field to the private section of the class and create a read method for the MyInteger property that will actually fire the OnAccess event when the property value is read:

class PACKAGE TCPPSimple : public TComponent { private:    int FMyInteger;    TNotifyEvent FOnAccess; public:     int __fastcall GetMyInteger(void); __published:    __property int MyInteger = {       // use the GetMyInteger read method       read = GetMyInteger,       write = FMyInteger,       default = 20    };    __property TNotifyEvent OnAccess = {       read = FOnAccess,       write = FOnAccess    }; }; //----------------------------------------------------------- int __fastcall TCPPSimple::GetMyInteger(void) {    /* fire the OnAccess event */    if(FOnAccess != NULL)       FOnAccess(this);    return FMyInteger; }

Object Properties

To create an object property in a VCL component, you need to declare an object field, instantiate the object in the component's constructor, and delete the object in the component's destructor. To see how to add object properties to a C++ VCL component, let's recreate the TStringsCache component.

First, add the TStringList field to the private section of the component, and then create the object in the component's constructor:

class PACKAGE TCPPStringsCache : public TComponent { private:    TStringList* FStrings; ... }; __fastcall TCPPStringsCache::TCPPStringsCache(TComponent* Owner)    : TComponent(Owner) {    FStrings = new TStringList; } 

All objects that are created in the constructor should be deleted in the component's destructor. In C++, the destructor isn't called Destroy. Instead, it is denoted by a tilde followed by the class name:

TClass::~TClass() {  }

Since we only need to delete the FStrings object, we can inline the destructor to reduce typing. Here's the TCPPStringCache component's destructor:

class PACKAGE TCPPStringsCache : public TComponent { private:    TStringList* FStrings; public:    __fastcall TCPPStringsCache(TComponent* Owner);    /* inlined destructor */    virtual __fastcall ~TCPPStringsCache()    {       delete FStrings;    } };

To finish the property, we still need to create the SetStrings write method to allow us to change the contents of the TStringList (this should preferably be a protected virtual method if you plan on changing it in the future), and we need to define the property in the published section of the class:

class PACKAGE TCPPStringsCache : public TComponent { protected:    virtual void __fastcall SetStrings(TStringList* Value); __published:    __property TStringList* Strings = {       read = FStrings,       write = SetStrings    }; }; //--------------------------------------------------------------------------- void __fastcall TCPPStringsCache::SetStrings(TStringList* Value) {    FStrings->Assign(Value); }

Inside Delphi 2006
Inside Delphi 2006 (Wordware Delphi Developers Library)
ISBN: 1598220039
EAN: 2147483647
Year: 2004
Pages: 212
Authors: Ivan Hladni

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: