Strings Delphi

Title: Exposing a multi string object in COM
Question: This document is intended for those using OLE/COM and want to
expose a multi string object similar to Delphi's TStrings object.
The IStrings interface for COM parallels the functionality of
De
Answer:
The example project contains these units:
Project1_TLB: A Pascal wrapper for the type library containing the
interface definition.

Unit1: The interface implementation containing storage for
interface properties and code to implement interface
methods.
Unit2: The main form for the automation server. This unit
is not strictly necessary, but provides feedback to
know when methods have been successfully called
AutCli: The automation client that obtains a reference to the
interface and uses the interface methods.
The general steps involved are listed below. You can compare each
of these steps with the unit code that follows.
1) Create a type library and add an interface called IStr, with a
single property called Items of type IStrings. See Developer's
Guide, chapter 42 for more information on working with type libraries
and creating interfaces in the type library editor.
2) In the previous step, adding an interface using the type library
editor will cause a Pascal wrapper unit to be produced (in this
example, the unit is called Unit1). Unit1 will contain shell
implementations of get and set methods of the Items property.
In this step you add implementation code to make the get and set
methods functional. Also you need to add a method to create storage
for your Items property, and to clean up that storage when the
interface is no longer needed. Unit1 uses Unit2. Unit2 contains
a form, memo and status bar to display status of each implemtation
method, for diagnostic purposes.
3) Create Unit2 containing a form with TMemo and TStatusBar. The
form is used to reflect activity in Unit1.pas. Though this step is
not strictly necessary, it helps visualize what's happening between
the automation client and server.
4) Create an automation client. In this case the unit is called
AutCli and contains a memo component and two buttons that assign
the Memo's TStrings data to the IStr interface's Items property.
{--------------------------------------------------------------------}
unit Project1_TLB;
{ This file contains pascal declarations imported from a type library.
This file will be written during each import or refresh of the type
library editor. Changes to this file will be discarded during the
refresh process. }
{ Project1 Library }
{ Version 1.0 }
interface
uses Windows, ActiveX, Classes, Graphics, OleCtrls, StdVCL;
const
LIBID_Project1: TGUID = '{E6F9F3B6-FD3C-11D0-908F-00C04FC291A4}';
const
{ Component class GUIDs }
Class_IStr: TGUID = '{E6F9F3B8-FD3C-11D0-908F-00C04FC291A4}';
type
{ Forward declarations: Interfaces }
IIStr = interface;
IIStrDisp = dispinterface;
{ Forward declarations: CoClasses }
IStr = IIStr;
{ Dispatch interface for IStr Object }
IIStr = interface(IDispatch)
['{E6F9F3B7-FD3C-11D0-908F-00C04FC291A4}']
function Get_Items: IStrings; safecall;
procedure Set_Items(const Value: IStrings); safecall;
property Items: IStrings read Get_Items write Set_Items;
end;
{ DispInterface declaration for Dual Interface IIStr }
IIStrDisp = dispinterface
['{E6F9F3B7-FD3C-11D0-908F-00C04FC291A4}']
property Items: IStrings dispid 1;
end;
{ IStrObject }
CoIStr = class
class function Create: IIStr;
class function CreateRemote(const MachineName: string): IIStr;
end;
implementation
uses ComObj;
class function CoIStr.Create: IIStr;
begin
Result := CreateComObject(Class_IStr) as IIStr;
end;
class function CoIStr.CreateRemote(const MachineName: string): IIStr;
begin
Result := CreateRemoteComObject(MachineName, Class_IStr) as IIStr;
end;
end.
{--------------------------------------------------------------------}
unit Unit1;
interface
uses
ComObj, Project1_TLB, StdVCL, Classes, AxCtrls, Unit2;
type
TIStr = class(TAutoObject, IIStr)
private
FItems: TStrings;
public
destructor Destroy; override;
procedure Initialize; override;
function Get_Items: IStrings; safecall;
procedure Set_Items(const Value: IStrings); safecall;
end;
implementation
uses ComServ, Dialogs;
procedure TIStr.Initialize;
begin
Inherited Initialize;
FItems := TStringList.Create;
end;
destructor TIStr.Destroy;
begin
FItems.Free;
end;
function TIStr.Get_Items: IStrings;
begin
Form1.Memo1.Lines.Assign(FItems);
GetOleStrings(FItems, Result);
Form1.StatusBar1.SimpleText := 'TIStr.Get_Items: IStrings';
end;
procedure TIStr.Set_Items(const Value: IStrings);
begin
SetOleStrings(FItems, Value);
Form1.Memo1.Lines.Assign(FItems);
Form1.StatusBar1.SimpleText := 'TIStr.Set_Items(const Value: IStrings)';
end;
initialization
TAutoObjectFactory.Create(ComServer, TIStr, Class_IStr, ciMultiInstance