The "ActiveX shell" technologyeasy way to enable ActiveX scripting on your Delphi and C++ Builder application |
This technology is for Delphi and C++ Builder.IntroductionIt allows to create special OLE object (named "ActiveX shell") for any Delphi (VCL) object as at design time so at RUN-TIME. That allows OLE mechanism to access properties and methods of the VCL objects.
The technology can be used, for example, to embed scripting language such as VBScript, JScript into the application. In this document you can find all what you need for that.
It is known that Delphi and C++ Builder have own object model which is distinct from object model of MS Windows named COM / DCOM / OLE / ActiveX. Therefore to apply Delphi objects as ActiveX objects it is necessary each time to create ActiveX Library and separated ActiveX object as wrapper. But will be very problematic to make it for all objects used by Delphi application. Moreover that will not be Delphi application.PossibilitiesThe "ActiveX shell" technology overcomes this misunderstanding and makes properties and methods of VCL objects accessible for OLE / ActiveX model that has a HUGE range of use.
Typical example of use is an embedding a scripting language into the application by using Microsoft ActiveX Scripting. Where in role of the scripting language can be used VBScript, JScript or any other maintained MS ActiveX Scripting.
I. Windows applications
supporting OLE, VBAII. Windows Scripting Host
| OLE mechanism <- ActiveX Scripting <- JScript, VBScript, Perl etc | | "ActiveX shell" object Delphi application's internal scripts | Delphi (VCL) objects MS ActiveX scripting is only one of ways to using application's object model created by "ActiveX shell" technology. You can use with your application any other scripting engine that use AciveX object model.
If you create OCX library with "YourAppName.Application" object then is possible to execute your application and to use its object model from Visual Basic or VBA of other Windows application supporting OLE such as Word, Excel, Outlook, Internet Explorer etc.
For example, Windows Scripting Host is new technology that allows to create JScript and VBScript program as Windows batch file. It can use your application's object model created by "ActiveX shell" technology too.
It allows to create special OLE object (named "ActiveX shell") for any Delphi (VCL) object as at design time so at RUN-TIME. That allows OLE mechanism to access properties and methods of the VCL objects.See below how to create "ActiveX shell" object for your Delphi object.
The "ActiveX shell" object is true OLE object.
From the point of view of OLE a "ActiveX shell" object have same properties and methods as defined in corresponding native Delphi object. OLE works with native Delphi object by its "ActiveX shell" object.
Now is possible through this mechanism:
It is enough to create one "ActiveX shell" object to receive access to all other Delphi objects in application as to OLE objects.
- to get and set value of published properties
- for classes inherited from TComponent to receive child-components by name
- for classes implementing Iactivex_shell_executable to call methods with variable number of arguments
For object received as a result of first two listed actions a new "ActiveX shell" object exists automatically.
However to return some Delphi object as result of "ActiveX shell" methods you have to create new "ActiveX shell" object manually.
The "ActiveX shell" object is true OLE object. Therefore to reference such object in Delphi is used Variant type. To determine that some Variant variable is "ActiveX shell" object is used function var_is_object described below.
When having object as "Activex shell" object you can access corresponding Delphi object by calling function var_to_object described below.
For TStrings it creates automatically extended "ActiveX shell" object for receiving access to the basic features of the class TStrings. Because TStrings is frequently used in Delphi but have not sufficient published properties to manipulate. See below in detail.
Limitations of the technology is based on the Run Time Type Information's features.Available versions, downloadingThe request on TPersistent is explained by availability the Run Time Type Information (RTTI) for the object. Though classes inherited from TPersistent is the majority of Delphi classes. And practically absolutely all published properties of Delphi objects are simple data types or reference to classes inherited from TPersistent. For example, TComponent, TPicture, TGraphic, TFont and TStrings are inherited from TPersistent.
- the technology works only for classes inherited from TPersistent
- it is necessary to have one version of Delphi or C++ Builder (it mean RTTI) for all separately compiled modules (.exe, .dll, .ocx etc) in application if they use the given technology together.
Compiled versions:How to installCompiled versions for other Delphi and C++ Builder releases is not available now.
- Delphi 3 version
- Delphi 4 version
But you can use the source code with those releases of course.
UsageExamples source code is located at corresponding directories ( D3\, D4\ ) too.
- Unzip archive axshell.zip with subdirectories.
- Directory D3\ is for Delphi 3 users. Directory D4\ is for Delphi 4 users.
Copy file activex_shell.dcu from one of this to any Delphi library path or to your project path.
Or install activex_shell.dcu from Delphi menu > Component > Install Component.- Simply add activex_shell to uses statement when need it.
Also see examples below.
It is easy to use.
Simply call one function to create "ActiveX shell" object for your Delphi objectfunction obj_to_variant(obj : TObject) : Variant;
This is same as
function Tactivex_shell . CreateShell (obj : TObject) : Variant;
Returned Variant datatype will be varDispatch because it is OLE / ActiveX object.
For example,
unit Unit1; interface
uses
activeX_shell;type
TForm1 = class (TForm)
Button1: TButton;
procedure Button1Click (Sender: TObject);
private
end;implementation
{ $R *.DFM}
procedure TForm1. Button1Click (Sender: TObject);
var v: Variant;
begin// Creation "ActiveX shell" object for the form
v := Tactivex_shell . CreateShell ( Self );// Using published properties
v. Caption := ' New caption ';
v. Font. Size := 22;// Using child-components by name -
// Button1 is not a published property
v. Button1. Caption := ' After click caption ';
// Using the object type properties
v. ActiveControl := v. Button1;end;
end.
The important definitions from the unit activeX_shell.
For all classes implementing Iactivex_shell_executable interface and IUnknown interface it is possible to use methods with variable number of arguments.
This is example of using Iactivex_shell_executable interface in Delphi 3.
Note that Delphi 4 TCustomForm class is already implements IUnknown and you should not implement it.
unit Unit1; interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
activeX_shell;
// ^ ^ ^ ^type
TForm1 = class (TForm, Iactivex_shell_executable)
// ^ ^ ^ ^
Button1: TButton;
procedure Button1Click (Sender: TObject);
private
private
{ Private declarations }// IUnknown
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;// Iactivex_shell_executable
function activex_shell_methods : AnsiString;
function activex_shell_exec(method_name : AnsiString; var param: Variant): Variant;
end;implementation
{ $R *.DFM}
procedure TForm1. Button1Click (Sender: TObject);
var v: Variant;
begin// Creation "ActiveX shell" object
v := Tactivex_shell . CreateShell (Self);// Using "ActiveX shell" methods
v.show_arguments('only one arg');
v.show_arguments('two', 'args');
v.show_arguments('now', 3 ,'args');ShowMessage( v.object_classname( v.Button1 ) );
end;
// Iactivex_shell_executable
// definition of "Activex shell" methods
function TForm1.activex_shell_methods : AnsiString;
begin
result := 'show_arguments,object_classname';
end;// implementation of "Activex shell" methods
function TForm1.activex_shell_exec(method_name : AnsiString; var param: Variant): Variant;
var i : Integer;
temp_str : String;
begin
result := Unassigned;//show_arguments
if method_name = 'show_arguments' then beginif VarIsArray(param) then begin
for i := 0 to VarArrayHighBound(param, 1) do begin
temp_str := temp_str + 'arg' + IntToStr(i) + '=' + var_to_string( param[i] ) + #13;
end;
end;ShowMessage(temp_str);
end
// object_classname
else if method_name = 'object_classname' then beginif VarIsArray( param ) and var_is_object( param[0] ) and (var_to_object( param[0] ) <> nil) then begin
result := var_to_object( param[0] ).ClassName;
end;end;
end;
// IUnknown
function TForm1.QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
begin
if GetInterface(IID, Obj) then result := 0 else result := E_NOINTERFACE;
end;function TForm1._AddRef: Integer; stdcall;
begin
result := 0;
end;function TForm1._Release: Integer; stdcall;
begin
result := 0;
end;end.
For TStrings it creates automatically extended "ActiveX shell" object for receiving access to the basic features of the class TStrings, because TStrings is frequently used in Delphi but have not sufficient published properties to manipulate.
For TStrings class and all inherited classes it is possible to use in appropriate extended "Active X shell" object already defined properties and methods:
Standard TStrings properties, see Delphi documentation
Standard TStrings methods, see Delphi documentation
- Count : Integer;
- Text : String;
Special methods for getting value of element
- function Add(value: String) : Integer;
- procedure Append(value: String) : Integer;
- procedure Clear();
- procedure Exchange(index1, index2: Integer);
- function IndexOf(value: String) : Integer;
- procedure Insert(index: Integer; value: String);
- procedure Move(CurIndex, NewIndex: Integer);
- procedure LoadFromFile(FileName: String);
- procedure SaveToFile(FileName: String);
Special method for setting value of element
- function Strings(index: Integer) : String;
- function Item(index: Integer) : String;
- procedure SetItem(index: Integer; value: String);
Using
with MS ActiveX Scripting, embedding scripts into the application
MS ActiveX Scripting is only one of ways to using application's object model created by "ActiveX shell" technology. You can use with your application any other scripting engine that use AciveX object model. See above about it.For embedding scripts on VBScript or JScript into an application in addition is required
MS Script Engine - already is on your computer if MSIE 4.0 or above is installed. It is possible to install separately with the distribution kit loaded from Microsoft site
- MS Script Engine
- MS Script Control
http://www.microsoft.com/msdownload/vbscript/scripting.asp
Size: ~ 650 Kb
License: Freeware
GUID: {EE09B103-97E0-11CF-978F-00A02463E06F}
MS Script Control - is necessary for use in the application the MS Script Engine . It is possible to install separately with the distribution kit loaded from Microsoft site
http://msdn.microsoft.com/scripting/scriptcontrol/default.htm
Size: ~ 250 Kb
License: Freeware, see site
GUID: {0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}
// Hint:
// You can use this function for checking availability of component by its GUIDfunction check_by_guid (component_guid: String): Boolean;
var v : Variant;
begin
try
v := CreateCOMObject ( StringToGUID (component_guid) );
result := True;
except
result := False;
ShowMessage ('Component is not installed: ' + component_guid);
end;
end;For using MS Script Control it is possible to import it ActiveX class to Delphi ( Delphi IDE Menu > Component > Import ActiveX Control ) and to use it in application as Delphi control, having placed on the necessary form at designer.
Other method is to create OLE object manually in Run Time. This is a small example of use MS Script Control. Where in Run Time two commands on VBScript are interpreted:
var this_form, scripting, module: Variant;
begin// Creation of instance of MS Script Control
scripting := CreateOLEObject ('ScriptControl');
scripting. AllowUI := True;
scripting. Language := 'VBScript';
// Creation of "ActiveX shell" for object
this_form := Tactivex_shell .CreateShell (Self);
// Example of creation of reference 'this' that is global name for all scripts code
scripting. AddObject ('this', this_form, True);// Example of using of the reference 'this'
scripting. ExecuteStatement (' this.Caption = "New Caption 1" ' + #13#10 + ' MsgBox (this.Caption) ');// Example of creation and using of module for the object
module := scripting. Modules. Add ( 'form_module', this_form );
module. ExecuteStatement (' Caption = "New Caption 2" ' + #13#10 + ' MsgBox (Caption) ');end;
In detail about using MS Script Control, its properties, methods and objects see msscript.hlp from the MS Script Control distribution kit.
This is only if you need to execute your application as OLE object.Professional version's advantagesFor creating OCX library with "YourAppName.Application" OLE object:
Now you have OCX library with "YourAppName.Application" object.
- use Delphi menu > New then choose ActiveX > ActiveX Library
- save project as "YourAppName"
- use Delphi menu > New then choose ActiveX > Automation object
- write "Application" as Class Name
- add properties and methods to that object and register library
Now it is possible to execute project and use its object model by calling
CreateOLEObject( 'YourAppName.Application' )
from Delphi or similar function from VBA and other languages.
In detail see Delphi documentation.
The "YourAppName.Application" object can have properties and methods of type Variant that is object reference. They can be implemented easy by using the "ActiveX shell" technology.
In professional version.It is possible to create "ActiveX shell" object with reference counting and without caring about clearing corresponding Delphi object. The Delphi object will be auto destroyed when reference count is 0.
This feature is very powerful, for example, when returning value from function:
function ...
var strings : TStrings;
begin// Creating object
strings := TStringList.Create();strings.Add('line 1');
strings.Add('line 2');
strings.Add('line 3');// Creating and returning from function "ActiveX shell" object
// with feature of reference counting
result := obj_to_activex( strings );// You have not to destroy here the TStringList object.
// It will be auto destroyed when will be not needed.end;
Note that
function obj_to_activex( obj : TObject ) : Variant;
is same as considered above obj_to_variant.
But function obj_to_activex create "ActiveX shell" object with feature of reference counting and auto destruction.
This feature is very flexible not only in "ActiveX shell" methods implementation, it can be used freely in your application to return or store any objects without caring about clearing it. Real Delphi object can be received by using var_to_object function anytime.
Professional version with source code costs only 40 $.Contact information
Click the image and buy it online.After receiving the payment, maximum per two days we send you technology source texts with comments by e-mail or you can download it from our secure web site.
Thank you for support !
Contact person: Karim YusupovSend your questions and comments to apelseen@mail.com
Take a look of http://apelseen.da.ru