Creating custom components for wxDev-C++

Esteban Aguilar B.

This tutorial shows how to create a new component wrapper for the wxDev-C++ program. It is recommended (but not necessary) to have some knowledge both on Delphi and wxWidgets programming. Also, it helps to be familiar with the default component creation process for delphi products; you can learn about it at http://delphi.about.com/od/vclusing/a/customvcldev.htm and http://www.delphi-central.com/writing_a_url_label.aspx

Please note that this is my first work in both Delphi and wxWidgets (even when I'm interested in the last one since almost a year). Also, my English is not very good so forgive me for any spelling or grammar mistakes.

In this tutorial I recomend using the component create by David Price program, because it gives you a better idea of what parts compound a component and at the same time generates some necesary code for you. You can download a copy from http://torry.net/tools/components/compcreation/cc.zip

However, if you are proficient writing delphi components, this is not necesary.

First of all, every component in wxDevCpp needs to implement the IWxComponentInterface. Also, depending on its behaviour, it can inherit some other predifined interfaces for wxDevCpp components. These interfaces are defined in "wxUtils.pas"

-IWxDialogNonInsertableInterface

-IWxToolBarInsertableInterface

-IWxToolBarNonInsertableInterface

-IWxWindowInterface

-IWxContainerAndSizerInterface

-IWxContainerInterface

-IWxToolBarInterface

-IWxStatusBarInterface

-IWxCollectionInterface

In this unit are also defined a lot of classes and types that helps you adding properties and properties editors to your components.

Adding your component to wxDevCpp

This section describes the common list of steps that you need to accomplish in order to "install" your component as part of the wxDevCpp program. This is the last step you will make after writing your component code.

1- Add a reference to your component's unit in the main.pas file, preferably under the second "uses" clause so all the components are declared together. Also, register your component under the "TMainForm.ReadClass" procedure:

RegisterClasses([TWxNewComponent]);

You can also add a reference to your component under the "TMainForm.LoadDefaultPalette" pocedure, so it can be loaded even if its not listed in the devcpp.pallete file.

2- Add a reference to your component's unit under the "uses" clause of the Designerfrm.pas file. (I don't know if this is really needed).

3- Add an entry for your component in the devcpp.pallete file that resides in the same folder as the app executable is, before the [version] segment.

Example:

  Samples=TWxNewComponent;

4- Add an image icon for your component editing the STDREG.DCR file (under the source directory), using the image editor, located in the "tools" menu. The image must be 24x24 pixels and in 16 or 256 colors. After opening this file choose "Resource->New->Bitmap" select width and height of 24. Choose "Ok", change the image name to TWXNEWCOMPONENT (or your component's name) and double click and paste your image there. Select "File->Save". NOTE: be careful to not redefine an already defined component here. Guru has added some bitmap resources to non implemented components yet, and if you duplicate an entry, the resources file will break.

a

Tutorial 1: Beginners

In this first example we will create a simple non-visual component, that is already part of the wxWidgets distribution. This is the"Text entry dialog" component. Let's get started.

1- Open "Component Create for delphi" and choose "File->New component definition...".

2- In the "Select parent class" window choose the ";list view" tab and write "TWxNonVisibleBaseComponent,IWxComponentInterface" in the combo box. Those are the classes we need to inherit from. The first one declare that the component has no visual widget associated in the form, and the second is the interface that all our components need to implement. Select "Ok" and then the program will ask for the path to the parent units. I don't know exactly how to use this when you need to inherit from parents defined on different units so, I choose "Yes" and then mark the checkbox that says "No, I don't know what XXXX descends from" and browse the unit containing the WxComponentInterface (wxUtils.pas) that is located in wxdevcpp\source\components.

3- Now in the Main tab we provide the class name "TWxTextEntryDialog", the unit name "WxTextEntryDialog" (unmark the checkbox to allow more than 8 chars). In the include units field you must have

-Windows

-SysUtils

-Classes

-wxUtils

-WxNonVisibleBaseComponent

listed, so you can delete the other references. You can add a description and the copyright line if you want. Choose a Target Directory, (wxdevcpp\source\components) and select "File->Save" to save your component definition file (under wxdevcpp\source\components\compCode).



4- In the "Properties" tab we have to add the following properties:

-Wx_Class --> String

-Wx_Message --> String

-Wx_Caption --> String

Add a default value to Wx_Class property of 'wxTextEntryDialog' (include the quotes) and unmark the "use write method" checkbox. Also add a default value of 'wxTextEntryDialog' for the Wx_Caption propety.



5- Select the "Methods" tab and double click the ";Create" method and add the next code before the "end;" line:

FWx_PropertyList.add('Wx_Message:Message');

FWx_PropertyList.add('Wx_Caption:Caption');

FWx_PropertyList.add('Name:Name');

FWx_PropertyList.add('Wx_Class:Base Class');

These are the properties that will be displayed in the property editor of wxDevCpp for our component. Choose "Ok".



Now we need to add some other methods:

-GenerateGUIControlCreation:String (as function). Double click it and add this code:

Result:='';

Result:=Format('%s = new %s(this, _("%s") , _("%s"));',[self.Name,self.wx_Class,GetCppString(wx_Message),GetCppString(wx_Caption)]);


This is the initialization code that will be auto-generated when a component is inserted in the form. (the declaration of an instance of wxTextEntryDialog).

-GenerateGUIControlDeclaration:String (function). Add this code

Result:='';

Result:=Format('%s *%s;',[trim(Self.Wx_Class),trim(Self.Name)]);


This is the declaration code.

-GenerateHeaderInclude:String (function).

Result:='';

Result:='#include <wx/textdlg.h>';
</p>

This is the header in were wxTextEntryDialog is defined.

-GetEventList:TStringlist (function).

Result:=nil;

Here should be the list of events at what this component responds to. We don't have events now so it returns nil.

-GetWxClassName:String (function)

if trim(wx_Class) = '' then

  wx_Class:='wxTextEntryDialog';

  Result:=wx_Class;


-SetWxClassName(wxClassName:String) (procedure)

wx_Class:=wxClassName;



-GetPropertyList:TStringList (function)

Result:=FWx_PropertyList;

Apart from those methods needed, IWxComponentInterface requires that you declare the next list of methods in order to compile successfully.

- GenerateControlIDs:String (function)

- GenerateEventTableEntries(CurrClassName:String):String (function)

- GenerateImageInclude:String (function)

- GetIDValue:LongInt (function)

- SetIDName(IDName:String) (procedure)

- SetIDValue(IDValue:longInt) (procedure)

- GetTypeFromEventName(EventName:String):String (function)

- GetIDName:String (function)

- GetParameterFromEventName(EventName:String):String (function)

- SaveControlOrientation(ControlOrientation:TWxControlOrientation) (procedure)

- GetStretchFactor:Integer (function)

- SetStretchFactor(intValue:Integer) (procedure)

- GetFGColor:String (function)

- SetFGColor(strValue:String) (procedure)

- GetBGColor:string (function)

- SetBGColor(strValue:String) (procedure)

You don't need to add extra code to these methods at this point, just declare them in Component Create.

6- Select the "Variables" tab and add FWx_PropertyList as a TStringList.

These are variables that you dont want to get displayed (published) in the property editor.

7- Save your work. Select the menu "Generate->Component code..." Click "OK". Add this file to the project. Open the .pas file just created and add the following line to the TWxTextEntryDialog.AutoInitialize method:

Glyph.Handle:=LoadBitmap(hInstance, 'TWxTextEntryDialog');

This code adds the component icon to the form when you drop an onstance of this non visual component there.

8- Register your component on wxDevCpp as described on top of this document. You can replace the TWXTEXTENTRYDIALOG icon currently available in wxDevCpp distribution with this one:



The code for this component for Component Create is here and the delphi generated code is at wxtextentrydialog.pas

here

9- Compile and test your new component. Congratutalions!