Adding Properties
Go Up to Adding Additional Properties, Methods, and Events
The ActiveX wrapper class implements properties in its interface using read and write access methods. That is, the wrapper class has COM properties, which appear on an interface as getter and/or setter methods. Unlike VCL properties, you do not see a "property" declaration on the interface for COM properties. Rather, you see methods that are flagged as property access methods. When you add a property to the ActiveX control's default interface, the wrapper class definition (which appears in the _TLB unit that is updated by the Type Library editor) gains one or two new methods (a getter and/or setter) that you must implement, just as when you add a method to the interface, the wrapper class gains a corresponding method for you to implement. Thus, adding properties to the wrapper class's interface is essentially the same as adding methods: the wrapper class definition gains new skeletal method implementations for you to complete.
Note: For details on what appears in the generated _TLB unit, see Code Generated When You Import Type Library Information.
For example, consider a Caption property, of type TCaption in the underlying VCL object.
To add this property to the object's interface, you enter the following when you add a property to the interface via the Type Library Editor:
property Caption: TCaption read Get_Caption write Set_Caption;
Delphi adds the following declarations to the wrapper class:
function Get_Caption: WideString; safecall;
procedure Set_Caption(const Value: WideString); safecall;
In addition, it adds skeletal method implementations for you to complete:
function TButtonX.Get_Caption: WideString;
begin
end;
procedure TButtonX.Set_Caption(Value: WideString);
begin
end;
When you add this property in the type Library Editor, C++Builder adds the following declarations to the wrapper class:
STDMETHOD(get_Caption(BSTR* Value));
STDMETHOD(set_Caption(BSTR Value));
C++Builder also adds skeletal method implementations for you to complete:
STDMETHODIMP TButtonXImpl::get_Caption(BSTR* Value)
{
try
{
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
STDMETHODIMP TButtonXImpl::set_Caption(BSTR Value)
{
try
{
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
Typically, you can implement these methods by simply delegating to the associated VCL control, which can be accessed using either the FDelphiControl or the m_VclCtl member of the wrapper class:
function TButtonX.Get_Caption: WideString;
begin
Result := WideString(FDelphiControl.Caption);
end;
procedure TButtonX.Set_Caption(const Value: WideString);
begin
FDelphiControl.Caption := TCaption(Value);
end;
STDMETHODIMP TButtonXImpl::get_Caption(BSTR* Value)
{
try
{
*Value = WideString(m_VclCtl->Caption).Copy();
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
STDMETHODIMP TButtonXImpl::set_Caption(BSTR Value)
{
try
{
m_VclCtl->Caption = AnsiString(Value);
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
In some cases, you might need to add code to convert the COM data types to native types. The preceding example manages this with typecasting.
Note: Because the Automation interface methods are declared safecall, you do not have to implement COM exception code for these methods. The Delphi compiler handles this for you by generating code around the body of safecall methods to catch Delphi exceptions and to convert them into COM error info structures and return codes.