1、有一个vcl控件TA,它有一个属性是,Items:TItemCollection,派生自TCollection;
2、我想把TA封装成一个com组件,供别的语言使用,希望能够这样使用:AxObject.Items.Count;
3、创建了一个IAx接口,实现的部分把相应功能转给A的一个实例,即:
TAx=class(T**, IAx)
private
FA:TA;
protected
function Get_Items(out Value: IItems): HRESULT; safecall;
function Set_Items(Value: IItems): HRESULT; safecall;
……
end;
实现为:
function Get_Items(out Value: IItems): HResult;
begin
Value := FA.Items as IItems;
end;
4、为了实现上述做法,再声明一个接口,IItems,然后让TItemCollection实现IItems;
5、问题出来了,IItems=interface(IDispatch),如果要TItemCollection实现IItems,则必须要实现IDispatch的一堆方法,例如Invoke、GetIDsByName等等;
6、看了一下VCL,TComponent默认实现了IDispatch的方法,所以派生自TComponent的类,再让它实现IDispatch丝毫不增加工作量;但上面TItemCollection派生自TCollection,则没有便利基于上面的尝试,我对这样封装的方式产生了极大的怀疑,希望高手们:
1、能帮我理清这种方式的思路;
2、提出更好的解决方案。多谢了。
2、我想把TA封装成一个com组件,供别的语言使用,希望能够这样使用:AxObject.Items.Count;
3、创建了一个IAx接口,实现的部分把相应功能转给A的一个实例,即:
TAx=class(T**, IAx)
private
FA:TA;
protected
function Get_Items(out Value: IItems): HRESULT; safecall;
function Set_Items(Value: IItems): HRESULT; safecall;
……
end;
实现为:
function Get_Items(out Value: IItems): HResult;
begin
Value := FA.Items as IItems;
end;
4、为了实现上述做法,再声明一个接口,IItems,然后让TItemCollection实现IItems;
5、问题出来了,IItems=interface(IDispatch),如果要TItemCollection实现IItems,则必须要实现IDispatch的一堆方法,例如Invoke、GetIDsByName等等;
6、看了一下VCL,TComponent默认实现了IDispatch的方法,所以派生自TComponent的类,再让它实现IDispatch丝毫不增加工作量;但上面TItemCollection派生自TCollection,则没有便利基于上面的尝试,我对这样封装的方式产生了极大的怀疑,希望高手们:
1、能帮我理清这种方式的思路;
2、提出更好的解决方案。多谢了。
private
FCollection : TVariantCollection;
protected
function _NewEnum: IUnknown; safecall;
function Add(Item, vntIndexKey: OleVariant): OleVariant; safecall;
function Count: Integer; safecall;
function Get_Item(Key: OleVariant): OleVariant; safecall;
procedure Clear; safecall;
procedure Remove(vntIndexKey: OleVariant); safecall;
function ItemExists(Key: OleVariant): WordBool; safecall;
public
procedure Initialize; override;
end;function TCPCollection._NewEnum: IUnknown;
begin
Result:= FCollection.GetEnum;
end;function TCPCollection.Get_Item(Key: OleVariant): OleVariant;
begin
try
Result:= FCollection.Items[Key];
except
Raise EOleException.Create('CPCollection Error - Invalid Item retrieving',1819,'','',0);
end;
end;procedure TCPCollection.Remove(vntIndexKey: OleVariant);
begin
try
FCollection.Delete(vntIndexKey);
except
Raise EOleException.Create('CPCollection Error - Invalid Item remove',1818,'','',0);
end;
end; function TCPCollection.Add(Item, vntIndexKey: OleVariant): OleVariant;
var
lString: String;
lKeyPresent: Boolean;
begin
lKeyPresent:= True;
try
lString:= VarToStr(vntIndexKey) + 'ss';
except
lKeyPresent:= False;
end;
try
if lKeyPresent then
if lKeyPresent then begin
if ItemExists(vntIndexKey) then
Raise EOleException.Create('', 2, '', '', 0);
FCollection.AddObject(vntIndexKey, Item)
end else
FCollection.Add(Item);
Result:= Item;
except
Raise EOleException.Create('CPCollection Error - Invalid Item add',1820,'','',0);
end;
end;function TCPCollection.ItemExists(Key: OleVariant): WordBool;
var
lItem : OleVariant;
begin
Result:= True;
try
lItem:= Get_Item(Key);
except
Result:= False;
end;
end;
感觉这么做比较彻底,都转成com对象了;比较担心的一点是,这个vcl组件比较庞大,这么改改动可能比较大一些,多谢!