Table of Contents

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;

Original topic

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;
}

Original topic

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
}

Original topic

Setting the active unit in the IDE

TIDEProjectFile *AMyUnit;
 
AMyUnit = IDEEngine1->Files->FindByUnitName("Unit1");
IDEEngine1->ActiveFile = AMyUnit;

Original topic

Running and debugging a project

IDEEngine1->RunProject();

Original topic

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;
}

Original topic

Registering/Unregistering standard tabs

IDEEngine1->UnregisterTab("Win32");

Original topic

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");

Original topic

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;
}

Original topic

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;
}

Original topic

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);
}

Original topic

Working with scripter

Getting started

Scripter->SourceCode->Text = "ShowMessage('Hello world!');";
Scripter->Execute();
 
Scripter->SourceCode->Text = AdvMemo1->Lines->Text;
Scripter->Execute();

Original topic

Cross-language feature: TatScripter and TIDEScripter

TatScript *MyPascalScript, *MyBasicScript;
 
MyPascalScript = atScripter1->AddScript(slPascal);
MyBasicScript = atScripter1->AddScript(slBasic);

Original topic

Common tasks

Calling a subroutine in script

Scripter->ExecuteSubroutine("DisplayHelloWorld");
Scripter->ExecuteSubroutine("DisplayByeWorld");

Original topic

Returning a value from script

Variant FunctionValue;
 
FunctionValue = Scripter->ExecuteSubroutine("Calculate");
 
FunctionValue = Scripter->Execute();

Original topic

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))));

Original topic

Accessing Delphi objects

Registering Delphi components

Scripter->AddComponent(Form1);

Original topic

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);
}

Original topic

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);
}

Original topic

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);
}

Original topic

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);
}

Original topic

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);
}

Original topic

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;
  }
}

Original topic

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));

Original topic

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));
}

Original topic

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();
}

Original topic

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();
}

Original topic

Removing functions from the System library

delete MyScripter->SystemLibrary()->MethodByName("ShowMessage");

Original topic