Adding Properties
and Methods
One
of the things that make a C++ programmer's life hard is the
separation of the class declaration (usually in the .h
file) and the class definition (usually in the .cpp file).
This can be a pain because of the maintenance required between the
two. Any time a member function is added in one, it has to be
replicated in the other. Manually, this can be a tedious process,
and it is made even more tedious for a C++ COM programmer who must
maintain the same definitions in an .idl file. When I'm
adding properties and methods to my interfaces, I'd like my C++
development environment to help translate an IDL method definition
into C++ (with the appropriate ATL attributes, if necessary) and
drop it into my .h and .cpp files for me, leaving
me a nice place to provide my implementation. That's just what
Visual Studio provides.
By right-clicking on a COM interface in Class
view, you can choose to add a new property or method from the Add
submenu of the context menu that appears. Figure 1.7 shows the dialog box that enables you
to add a property to a COM interface. Parameters to the property
can be added by specifying the parameter data type and the
parameter direction (for example, [in] or
[out]).
Figure
1.8 shows the options available on the IDL Attributes tab for
the Add Property Wizard. Selected attributes are inserted into the
appropriate interface definition, in your project's IDL file. In
either case, the effect on the type library is identical. Many of
these attributes apply in rare circumstances, so the default
selections and values shown in the figure are often suitable. In
any event, adding, deleting, or modifying these attributes directly
in the IDL file afterward is a simple matter.
The following shaded code shows the
implementation skeleton that the wizard generates. We have to
provide only the appropriate behavior (shown as unshaded code).
STDMETHODIMP CCalcPi::get_Digits(LONG* pVal) {
*pVal = m_nDigits;
return S_OK;
}
STDMETHODIMP CCalcPi::put_Digits(LONG newVal) {
if( newVal < 0 )
return Error(L"Can't calculate negative digits of PI");
m_nDigits = newVal;
return S_OK;
}
Similarly, we can add a method by right-clicking
an interface in Class view and choosing Add Method. Figure 1.9 shows the Add Method
Wizard. Input and output parameters are added individually using
the Parameter Type combo box, the Parameter Name text box, and the
Add/Remove buttons.
Again, the wizard updates the interface
definition in either the IDL file or the header file, generates the
appropriate C++ code, and places us in the implementation skeleton
to do our job. The shaded code is what remains of the
wizard-generated C++ code after I added the code to implement the
method:
STDMETHODIMP CCalcPi::CalcPi(BSTR* pbstrPi) {
_ASSERTE(m_nDigits >= 0);
if( m_nDigits ) {
*pbstrPi = SysAllocStringLen(L"3.", m_nDigits+2);
if( *pbstrPi ) {
for( int i = 0; i < m_nDigits; i += 9 ) {
long nNineDigits = NineDigitsOfPiStartingAt(i+1);
swprintf(*pbstrPi + i+2, 10, L"%09d", nNineDigits);
}
// Truncate to number of digits
(*pbstrPi)[m_nDigits+2] = 0;
}
}
else {
*pbstrPi = SysAllocString(L"3");
}
return *pbstrPi ? S_OK : E_OUTOFMEMORY;
}
For a description of COM exceptions and the ATL
Error function (used in the put_Digits member
function), see Chapter
4, "Objects in ATL."
|