C++Builder Examples
This section contains C++Builder examples equivalent to every Delphi example in this manual. Each example provides a link to the related topic, and vice versa.
Integrated Development Environment
Using TIDEEngine component programatically
Adding/removing units (scripts and forms) to the project
TIDEProjectFile *ANewUnit, *ANewForm;
// Creates a blank unit in Basic
ANewUnit = IDEEngine1->NewUnit(slBasic);
// Creates a blank form in Pascal
ANewForm = IDEEngine1->NewFormUnit(slPascal);
// Remove Unit1 from project
TIDEProjectFile *AUnit = IDEEngine1->Files->FindByUnitName("Unit1");
if(AUnit != NULL)
delete AUnit;
Executing a project programatically
void __fastcall TForm1::RunSampleProject()
{
TIDEProjectFile *AUnit;
TIDEEngine *AEngine;
TIDEScripter *AScripter;
AEngine = new TIDEEngine(NULL);
AScripter = new TIDEScripter(NULL);
AEngine->Scripter = AScripter;
AEngine->NewProject();
AUnit = AEngine->NewUnit(slPascal);
AUnit->Script->SourceCode->Text = "ShowMessage('Hello world!');";
AEngine->RunProject();
delete AEngine;
delete AScripter;
}
void __fastcall TForm1::ShowIDEWithSimpleUnit()
{
TIDEProjectFile *AUnit;
TIDEDialog *ADialog;
TIDEEngine *AEngine;
TIDEScripter *AScripter;
ADialog = new TIDEDialog(NULL);
AEngine = new TIDEEngine(NULL);
AScripter = new TIDEScripter(NULL);
ADialog->Engine = AEngine;
AEngine->Scripter = AScripter;
AEngine->NewProject();
AUnit = AEngine->NewUnit(slPascal);
AUnit->Script->SourceCode->Text = "ShowMessage('Hello world!');";
ADialog->Execute();
delete ADialog;
delete AEngine;
delete AScripter;
}
Managing units and changing its properties
TIDEProjectFile *AUnit;
for(int c = 0; c < IDEEngine1->Files->Count; c++)
{
AUnit = IDEEngine1->Files->Items[c];
// Do something with AUnit
}
Setting the active unit in the IDE
TIDEProjectFile *AMyUnit;
AMyUnit = IDEEngine1->Files->FindByUnitName("Unit1");
IDEEngine1->ActiveFile = AMyUnit;
Running and debugging a project
IDEEngine1->RunProject();
Registering components in the IDE
Retrieving existing registered components
TIDERegisteredComp *ARegComp;
TComponentClass ACompClass;
AnsiString AUnits, APage;
for(int c = 0; c < IDEEngine1->RegisteredComps->Count; c++)
{
ARegComp = IDEEngine1->RegisteredComps->Items[c];
// Contains the class registered, for example, TButton
ACompClass = ARegComp->CompClass;
// Contains the name of units (separated by commas) that will be
// added to the script when the component is dropped in a form.
// For example, 'ComCtrls,ExtCtrls'
AUnits = ARegComp->Units;
// Contains the name of the page (category, tab) where the component
// will be displayed. For example, 'Standard'
APage = ARegComp->Page;
}
Registering/Unregistering standard tabs
IDEEngine1->UnregisterTab("Win32");
Register new components
// Register the new component TMyComponent in the tab "Custom". When the user
// drops this component in the form, the units ComCtrls, ExtCtrls and
// MyComponentUnit are added to the script.
// These units must be registered in scripter in order to give access to them in
// the script environment.
// This registration can be done manually (check "Accessing Delphi objects"
// chapter) or using the ImportTool.
IDEEngine1->RegisterComponent("Custom", __classid(TMyComponent),
"ComCtrls,ExtCtrls,MyComponentUnit");
Storing units in a database (alternative to files)
Replacing save/load operations
void __fastcall TForm1::IDEEngine1SaveFile(TObject *Sender,
TIDEFileType IDEFileType, AnsiString AFileName, AnsiString AContent,
TIDEProjectFile *AFile, bool &Handled)
{
// The IDEFileType parameter tells you if the file to be saved is a project
// file, a script file, or a form file.
// Valid values are: iftScript, iftProject, iftForm}
// The AFileName string contains the name of the file that was chosed in the
// save dialog.
// Remember that you can replace the save dialog by your own, so the AFileName
// will depend on the value returned by the save dialog
// The AContent parameter contains the file content in string format
// The AFile parameter points to the TIDEProjectFile object that is being
// saved. You will probably not need to use this parameter, it's passed only
// in case you need additional information for the file
// If you save the file yourself, you need to set Handled parameter to true.
// If Handled is false, then the IDE engine will try to save the file normally
// So, as an example, the code below saves the file in a table which contains
// the fields FileName and Content. Remember that AContent string might be a
// big string, since it has all the content of the file (specially for form
// files)
MyTable->Close();
switch(IDEFileType)
{
case iftScript:
MyTable->TableName = "CustomScripts";
break;
case iftForm:
MyTable->TableName = "CustomForms";
break;
case iftProject:
MyTable->TableName = "CustomProjects";
break;
}
MyTable->Open();
if(MyTable->Locate("FileName",AFileName, TLocateOptions()<<loCaseInsensitive))
MyTable->Edit();
else
{
MyTable->Append();
MyTable->FieldByName("FileName")->AsString = AFileName;
}
MyTable->FieldByName("Content")->AsString = AContent;
MyTable->Post();
Handled = true;
}
void __fastcall TForm1::IDEEngine1LoadFile(TObject *Sender,
TIDEFileType IDEFileType, AnsiString AFileName, AnsiString &AContent,
TIDEProjectFile *AFile, bool &Handled)
{
// The IDEFileType parameter tells you if the file to be saved is a project
// file, a script file, or a form file.
// Valid values are: iftScript, iftProject, iftForm
// The AFileName string contains the name of the file that was chosed in the
// save dialog. Remember that you can replace the save dialog by your own, so
// the AFileName will depend on the value returned by the save dialog
// The AContent parameter contains the file content in string format. You must
// return the content in this parameter
// The AFile parameter points to the TIDEProjectFile object that is being
// saved. You will probably not need to use this parameter, it's passed only
// in case you need additional information for the file
// If you save the file yourself, you need to set Handled parameter to true.
// If Handled is false, then the IDE engine will try to save the file normally
// So, as an example, the code below saves the file in a table which contains
// the fields FileName and Content. Remember that AContent string might be a
// big string, since it has all the content of the file (specially for form
// files)
MyTable->Close();
switch(IDEFileType)
{
case iftScript:
MyTable->TableName = "CustomScripts";
break;
case iftForm:
MyTable->TableName = "CustomForms";
break;
case iftProject:
MyTable->TableName = "CustomProjects";
break;
}
MyTable->Open();
if(MyTable->Locate("FileName",AFileName, TLocateOptions()<<loCaseInsensitive))
AContent = MyTable->FieldByName("Content")->AsString;
else
throw Exception(Format("File %s not found!",
OPENARRAY(TVarRec, (AFileName))));
Handled = true;
}
Replacing open/save dialogs
void __fastcall TForm1::IDEEngine1SaveDialog(TObject *Sender,
TIDEFileType IDEFileType, AnsiString &AFileName,
TIDEProjectFile *AFile, bool &ResultOk, bool &Handled)
{
// The IDEFileType parameter tells you if the file to be saved is a project
// file, a script file, or a form file.
// Valid values are: iftScript, iftProject. itForm is not used for open/save
// dialogs
// The AFileName string contains the name of the file that was chosed in the
// save dialog. You must return the name of the file to be saved here
// The AFile parameter points to the TIDEProjectFile object that is being
// saved. You will probably not need to use this parameter, it's passed only
// in case you need additional information for the file
// You must set ResultOk to true if the end-user effectively has chosen a file
// name. If the end-user canceled the operation, set ResultOk to false so that
// save process is canceled
// If you display the save dialog yourself, you need to set Handled parameter
// to true. If Handled is false, then the IDE engine will open the default
// save dialog
// So, as an example, the code below shows a very rudimentar save dialog
// (InputQuery) in replacement to the regular save dialog. Note that this
// example doesn't check if the file is a project or a script. You must
// consider this parameter in your application
ResultOk = InputQuery("Save unit", "Choose a file name", AFileName);
Handled = true;
}
void __fastcall TForm1::IDEEngine1OpenDialog(TObject *Sender,
TIDEFileType IDEFileType, AnsiString &AFileName, bool &ResultOk,
bool &Handled)
{
// The IDEFileType parameter tells you if the file to be saved is a project
// file, a script file, or a form file.
// Valid values are: iftScript and iftProject. itForm is not used for
// open/save dialogs
// The AFileName string contains the name of the file that was chosed in the
// save dialog. You must return the name of the file to be saved here
// You must set ResultOk to true if the end-user effectively has chosen a file
// name. If the end-user canceled the operation, set ResultOk to false so that
// save process is canceled
// If you display the save dialog yourself, you need to set Handled parameter
// to true. If Handled is false, then the IDE engine will open the default
// save dialog
// So, as an example, the code below shows an open dialog in replacement to
// the regular save dialog. It considers that the form TMyOpenDlgForm lists
// all available units from a database table or something similar. Note that
// this example doesn't check if the file is a project or a script. You must
// consider this parameter in your application
TMyOpenDlgForm *AMyOpenDlg;
AMyOpenDlg = new TMyOpenDlgForm(Application);
ResultOk = AMyOpenDlg->ShowModal() == mrOk;
if(ResultOk)
AFileName = AMyOpenDlg->ChosenFileName;
delete AMyOpenDlg;
Handled = true;
}
Checking if a file name is valid
void __fastcall TForm1::IDEEngine1CheckValidFile(TObject *Sender,
TIDEFileType IDEFileType, AnsiString AFileName, bool &AValid)
{
// The IDEFileType parameter tells you if the file to be checked is a form,
// script or project.
// Valid values are: iftScript, iftProject
// The AFileName is the file name to be tested
// The AValid parameter must be set to true if the file name is valid.
// The code below is an example of how to use this event
MyTable->Close();
switch(IDEFileType)
{
case iftScript:
MyTable->TableName = "CustomScripts";
break;
case iftForm:
MyTable->TableName = "CustomForms";
break;
case iftProject:
MyTable->TableName = "CustomProjects";
break;
}
MyTable->Open();
AValid = MyTable->Locate("FileName", AFileName,
TLocateOptions() << loCaseInsensitive);
}
Working with scripter
Getting started
Scripter->SourceCode->Text = "ShowMessage('Hello world!');";
Scripter->Execute();
Scripter->SourceCode->Text = AdvMemo1->Lines->Text;
Scripter->Execute();
Cross-language feature: TatScripter and TIDEScripter
TatScript *MyPascalScript, *MyBasicScript;
MyPascalScript = atScripter1->AddScript(slPascal);
MyBasicScript = atScripter1->AddScript(slBasic);
Common tasks
Calling a subroutine in script
Scripter->ExecuteSubroutine("DisplayHelloWorld");
Scripter->ExecuteSubroutine("DisplayByeWorld");
Returning a value from script
Variant FunctionValue;
FunctionValue = Scripter->ExecuteSubroutine("Calculate");
FunctionValue = Scripter->Execute();
Passing parameters to script
Variant FunctionValue;
FunctionValue = Scripter->ExecuteSubroutine("Double", 5);
Variant MyVar;
FunctionValue = Scripter->ExecuteSubroutine("MaxValue",
VarArrayOf(OPENARRAY(Variant, (5, 8))));
Scripter->ExecuteSubroutine("Increase", VarArrayOf(
OPENARRAY(Variant, (MyVar, 3))));
Accessing Delphi objects
Registering Delphi components
Scripter->AddComponent(Form1);
Calling methods
void __fastcall TForm1::ShowModalProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(((TCustomForm*)
AMachine->CurrentObject)->ShowModal());
}
void __fastcall TForm1::PrepareScript()
{
Scripter->AddComponent(Form2);
TatClass *customFormClass = Scripter->DefineClass(__classid(TCustomForm));
customFormClass->DefineMethod("ShowModal", 0, Atscript::tkInteger, NULL,
ShowModalProc);
}
More method calling examples
void __fastcall TForm1::FieldByNameProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg((long) ((TDataSet*)
AMachine->CurrentObject)->FieldByName(AMachine->GetInputArgAsString(0)));
}
void __fastcall TForm1::PrepareScript()
{
Scripter->AddComponent(Table1);
TatClass *datasetClass = Scripter->DefineClass(__classid(TDataSet));
datasetClass->DefineMethod("FieldByName", 1, Atscript::tkClass,
__classid(TField), FieldByNameProc);
}
Acessing non-published properties
void __fastcall TForm1::GetFieldValueProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(((TField*) AMachine->CurrentObject)->Value);
}
void __fastcall TForm1::SetFieldValueProc(TatVirtualMachine *AMachine)
{
((TField*) AMachine->CurrentObject)->Value = AMachine->GetInputArg(0);
}
void __fastcall TForm1::PrepareScript()
{
TatClass *fieldClass = Scripter->DefineClass(__classid(TField));
fieldClass->DefineProp("Value", Atscript::tkVariant, GetFieldValueProc,
SetFieldValueProc);
}
Registering indexed properties
void __fastcall TForm1::GetStringsProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(((TStrings*)
AMachine->CurrentObject)->Strings[AMachine->GetArrayIndex(0)]);
}
void __fastcall TForm1::SetStringsProc(TatVirtualMachine *AMachine)
{
((TStrings*) AMachine->CurrentObject)->Strings[AMachine->GetArrayIndex(0)] =
AMachine->GetInputArgAsString(0);
}
void __fastcall TForm1::PrepareScript()
{
Scripter->AddComponent(Memo1);
TatClass *stringsClass = Scripter->DefineClass(__classid(TStrings));
stringsClass->DefineProp("Strings", Atscript::tkString, GetStringsProc,
SetStringsProc, NULL, false, 1);
}
Retrieving name of called method or property
void __fastcall TForm1::GenericMessageProc(TatVirtualMachine *AMachine)
{
if(AMachine->CurrentMethodName() == "MessageHello")
ShowMessage("Hello");
else if(AMachine->CurrentMethodName() == "MessageWorld")
ShowMessage("World");
}
void __fastcall TForm1::PrepareScript()
{
Scripter->DefineMethod("MessageHello", 1, tkNone, NULL, GenericMessageProc);
Scripter->DefineMethod("MessageWorld", 1, tkNone, NULL, GenericMessageProc);
}
Registering methods with default parameters
float SumNumbers(float a, float b, float c = 0, float d = 0, float e = 0);
Scripter->DefineMethod("SumNumbers",
5 /*number of total parameters*/,
Atscript::tkFloat, NULL, SumNumbersProc, false,
3 /*number of default parameters*/);
void __fastcall TForm1::SumNumbersProc(TatVirtualMachine *AMachine)
{
switch(AMachine->InputArgCount())
{
case 2:
AMachine->ReturnOutputArg(SumNumbers(AMachine->GetInputArgAsFloat(0),
AMachine->GetInputArgAsFloat(1)));
break;
case 3:
AMachine->ReturnOutputArg(SumNumbers(AMachine->GetInputArgAsFloat(0),
AMachine->GetInputArgAsFloat(1), AMachine->GetInputArgAsFloat(2)));
break;
case 4:
AMachine->ReturnOutputArg(SumNumbers(AMachine->GetInputArgAsFloat(0),
AMachine->GetInputArgAsFloat(1), AMachine->GetInputArgAsFloat(2),
AMachine->GetInputArgAsFloat(3)));
break;
case 5:
AMachine->ReturnOutputArg(SumNumbers(AMachine->GetInputArgAsFloat(0),
AMachine->GetInputArgAsFloat(1), AMachine->GetInputArgAsFloat(2),
AMachine->GetInputArgAsFloat(3), AMachine->GetInputArgAsFloat(4)));
break;
}
}
Accessing Delphi functions, variables and constans
Registering global constants
Scripter->AddConstant("MaxInt", MaxInt);
Scripter->AddConstant("Pi", M_PI);
Scripter->AddConstant("MyBirthday", EncodeDate(1992, 5, 30));
Acessing global variables
Variant MyVar;
AnsiString ZipCode;
void __fastcall TForm1::GetZipCodeProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(ZipCode);
}
void __fastcall TForm1::SetZipCodeProc(TatVirtualMachine *AMachine)
{
ZipCode = AMachine->GetInputArgAsString(0);
}
void __fastcall TForm1::PrepareScript()
{
Scripter->AddVariable("ShortDateFormat", ShortDateFormat);
Scripter->AddVariable("MyVar", MyVar);
Scripter->DefineProp("ZipCode", Atscript::tkString, GetZipCodeProc,
SetZipCodeProc);
Scripter->AddObject("Application", Application);
}
void __fastcall TForm1::Run1Click(TObject *Sender)
{
PrepareScript();
MyVar = "Old value";
ZipCode = "987654321";
Application->Tag = 10;
Scripter->SourceCode = Memo1->Lines;
Scripter->Execute();
ShowMessage("Value of MyVar variable in C++ Builder is " + VarToStr(MyVar));
ShowMessage("Value of ZipCode variable in C++ Builder is " +
VarToStr(ZipCode));
}
Calling regular functions and procedures
void __fastcall TSomeLibrary::Init()
{
Scripter->DefineMethod("QuotedStr", 1, Atscript::tkString, NULL,
QuotedStrProc);
Scripter->DefineMethod("StringOfChar", 2, Atscript::tkString, NULL,
StringOfCharProc);
}
void __fastcall TSomeLibrary::QuotedStrProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(QuotedStr(AMachine->GetInputArgAsString(0)));
}
void __fastcall TSomeLibrary::StringOfCharProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(StringOfChar(AMachine->GetInputArgAsString(0)[1],
AMachine->GetInputArgAsInteger(1)));
}
void __fastcall TForm1::Run1Click(TObject *Sender)
{
Scripter->AddLibrary(__classid(TSomeLibrary));
Scripter->SourceCode = Memo1->Lines;
Scripter->Execute();
}
Using libraries
Delphi-based libraries
CODE 1:
class TExampleLibrary: public TatScripterLibrary
{
protected:
void __fastcall CurrToStrProc(TatVirtualMachine *AMachine);
virtual void __fastcall Init();
virtual AnsiString __fastcall LibraryName();
};
AnsiString __fastcall TExampleLibrary::LibraryName()
{
return "Example";
}
void __fastcall TExampleLibrary::Init()
{
Scripter->DefineMethod("CurrToStr", 1, Atscript::tkInteger, NULL,
CurrToStrProc);
}
void __fastcall TExampleLibrary::CurrToStrProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(CurrToStr(AMachine->GetInputArgAsFloat(0)));
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Scripter->AddLibrary(__classid(TExampleLibrary));
Scripter->SourceCode = Memo1->Lines;
Scripter->Execute();
}
CODE 2:
void __fastcall TForm1::PrepareScript()
{
Scripter->DefineMethod("CurrToStr", 1, Atscript::tkInteger, NULL,
CurrToStrProc);
}
void __fastcall TForm1::CurrToStrProc(TatVirtualMachine *AMachine)
{
AMachine->ReturnOutputArg(CurrToStr(AMachine->GetInputArgAsFloat(0)));
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
PrepareScript();
Scripter->SourceCode = Memo1->Lines;
Scripter->Execute();
}
Removing functions from the System library
delete MyScripter->SystemLibrary()->MethodByName("ShowMessage");