贴一篇文章,参考一下: Exposing a multi string object in COM Undertitle: How to work with IStrings
Category: COM+ Uploader: Bernhard Angerer
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 另一个: StringlistToVariant / VariantToStringlist StringList和Variant之间的转换Under title: To transfer stringlists via COM+ you can use IStrings or Variants 通过COM+用IStrings或者Variants传递StringList
Question: The OLE type variant allows you to transfer nearly everything via DOM/DCOM what you need. This demo shows how to convert a stringlist into a variant and vice versa. Answer: unit uForm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Memo1: TMemo; Memo2: TMemo; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } hStrList: TStringList; v: OleVariant; end; var Form1: TForm1; implementation {$R *.DFM} procedure VariantToStream(const Data: OleVariant; Stream: TStream); var p: Pointer; begin p := VarArrayLock(Data); try Stream.Write(p^, VarArrayHighBound(Data,1) + 1); //assuming low bound = 0 finally VarArrayUnlock(Data); end; end; function StreamToVariant(Stream: TStream): OleVariant; var p: Pointer; begin Result := VarArrayCreate([0, Stream.Size - 1], varByte); p := VarArrayLock(Result); try Stream.Position := 0; //start from beginning of stream Stream.Read(p^, Stream.Size); finally VarArrayUnlock(Result); end; end; function StringlistToVariant(aStrlist: TStrings): OleVariant; var hStream: TStream; begin hStream := TMemoryStream.Create; try aStrList.SaveToStream(hStream); hStream.Seek(0,soFromBeginning); Result := StreamToVariant(hStream); finally hStream.Free; end; end; procedure VariantToStringlist(const Data: OleVariant; aStrlist: TStrings); var hStream: TStream; begin hStream := TMemoryStream.Create; try VariantToStream(Data,hStream); hStream.Seek(0,soFromBeginning); aStrList.LoadFromStream(hStream); finally hStream.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin hStrList:= TStringList.Create; hStrList.Assign(Memo1.Lines); v := StringlistToVariant(hStrList); hStrList.Destroy; end; procedure TForm1.Button2Click(Sender: TObject); begin VariantToStringlist(v,Memo2.Lines); end; end.
因为TStrings.Text就是一个string了。
另外,可以试试Delphi提供的IStrings,不过这个我没用过。
begin
v:='ddffdfdfdf'
end//直接对olevariant类型的变量赋值即可
或者强制类型转换
tvardata(v).vtype :=varstring;
tvardata(v).vstring:='dere'
s:OleVariant;
i:integer;
begin
s:=varArrayCreate([Tstrings.count,1],varVariant);
for i:=0 to Tstrings.count-1 do
begin
s[i]:=TStrings[i];
end;
你仔细查看一下TStringList的代码就知道了。其实Tstringlist存放的就是一个简单的字符串。他的每个line,其实就是用“换行回车”来分开的。因此你写:
i#10#13an#10#13a#10#13man#10#13
把它付个一个Tstringlist.text,Tstringlist自动就会把它解析到每个行里去了。:)
知道原理后,你应该知道怎么传了吧?用olevariant类型,传我上面说的那种字符串格式,你程序里的Tstringlist就会自动识别了。
另外,D6还带了个istringlist的接口,也有把tstringlist转到istringlist的函数,但是我不记得函数名了。^_^
Exposing a multi string object in COM
Undertitle: How to work with IStrings
Category: COM+
Uploader: Bernhard Angerer
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 另一个:
StringlistToVariant / VariantToStringlist
StringList和Variant之间的转换Under title: To transfer stringlists via COM+ you can use IStrings or Variants
通过COM+用IStrings或者Variants传递StringList
Question: The OLE type variant allows you to transfer nearly everything via DOM/DCOM what you
need. This demo shows how to convert a stringlist into a variant and vice versa.
Answer: unit uForm; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
hStrList: TStringList;
v: OleVariant;
end; var
Form1: TForm1; implementation {$R *.DFM}
procedure VariantToStream(const Data: OleVariant; Stream: TStream);
var
p: Pointer;
begin
p := VarArrayLock(Data);
try
Stream.Write(p^, VarArrayHighBound(Data,1) + 1); //assuming low bound = 0
finally
VarArrayUnlock(Data);
end;
end; function StreamToVariant(Stream: TStream): OleVariant;
var
p: Pointer;
begin
Result := VarArrayCreate([0, Stream.Size - 1], varByte);
p := VarArrayLock(Result);
try
Stream.Position := 0; //start from beginning of stream
Stream.Read(p^, Stream.Size);
finally
VarArrayUnlock(Result);
end;
end; function StringlistToVariant(aStrlist: TStrings): OleVariant;
var
hStream: TStream;
begin
hStream := TMemoryStream.Create;
try
aStrList.SaveToStream(hStream);
hStream.Seek(0,soFromBeginning);
Result := StreamToVariant(hStream);
finally
hStream.Free;
end;
end; procedure VariantToStringlist(const Data: OleVariant; aStrlist: TStrings);
var
hStream: TStream;
begin
hStream := TMemoryStream.Create;
try
VariantToStream(Data,hStream);
hStream.Seek(0,soFromBeginning);
aStrList.LoadFromStream(hStream);
finally
hStream.Free;
end;
end; procedure TForm1.Button1Click(Sender: TObject);
begin
hStrList:= TStringList.Create;
hStrList.Assign(Memo1.Lines); v := StringlistToVariant(hStrList); hStrList.Destroy;
end; procedure TForm1.Button2Click(Sender: TObject);
begin
VariantToStringlist(v,Memo2.Lines);
end; end.