Using Native COM Support in Microsoft Visual C++
Microsoft Visual C++ version 5.0 or later has native COM support through the #import
statement. Using this statement allows you to automatically add type
information contained in a type library into your project. The
generated files normally have the same name as the component DLL with
the extensions .tlh and .tli.
When using the #import statement,
make sure to import the ActiveX Data Objects type information before
the Microsoft CDO for Windows 2000 type information. The following
examples demonstrate using the #import
statement:
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace raw_interfaces_only rename("EOF", "EndOfFile")#import <cdosys.dll> no_namespace raw_interfaces_only#include "cdosysstr.h"#include "cdosyserr.h"void main() { CoInitialize(NULL); IMessage* pMsg = NULL; HRESULT hr = CoCreateInstance( __uuidof(Message), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMessage), (void**) &pMsg ); ... CoUninitialize();}
Note
You
must have the ADO 2.5 type information in the same namespace as CDO
type information. CDO interfaces make use of ADO types in arguments.
These types are not qualified using namespaces in the CDO interface
definitions. If these types are not in the same namespace, errors will
occur. You can do one of the following to solve this problem:
- Rename the default ADODB ADO namespace to CDO.
- Import type information into the global namespace, if feasible.
- Rename both CDO and ADODB to another namespace, such as CDOSYS.
The GUID definitions for ADO and CDO types can be retrieved using the __uuidof
operator supported by Visual C++. You can use #import
flags to specify the CLSID_XXX and IID_XXX definitions if this format is desired.
Consider the following issues when using the #import statement:
- The
header file generated by the #import directive does not contain the
module constant definitions contained within the type library. However,
the Platform SDK provides two separate headers that can be included
within your project so that these constants are available. These files
are
cdosysstr.h
and cdosyserr.h
. The first
contains the field name constants, and the second includes the CDO
custom HRESULT error codes. If you do not include these, you will have
to manually insert these values. For example, the field
"urn:schemas:httpmail:to" has an associated constant called cdoTo in the string constant header file cdosysstr.h
. - The
#import
statement strips the default values for arguments when generating the
header files. If you use #import, you will need to explicitly specify
the defaults. For example: hr = pBp->AddBodyPart(-1); // the -1 is the default value in cdosys.h
Using Interface Pointer Wrapper Classes with Import
The raw_interfaces_only
flag to #import
directive suppresses the creation of "smart pointer" C++ wrapper
classes. However, in many cases these wrappers simplify working with
CDO in C++. The following example demonstrates using the wrapper
classes produced by the #import
statement:
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "EndOfFile")#import <cdosys.dll> no_namespace#include "cdosysstr.h"#include "cdosyserr.h"void main() { CoInitialize(NULL); { try { IMessagePtr iMsg(__uuidof(Message)); FieldsPtr Flds; Flds = iMsg->Fields; Flds->Item[cdoTo]->Value = _variant_t("example@example.com"); Flds->Item[cdoFrom]->Value = _variant_t("example@example.com"); Flds->Item[cdoSubject]->Value = _variant_t("a test"); Flds->Item[cdoTextDescription]->Value = _variant_t("this is a test"); Flds->Update(); iMsg->Send(); } catch( _com_error err) { // ... } } CoUninitialize(); return 1;}
Using the CDO Namespace
You
can use namespaces with the #import statement. However, when you import
the ADO type information, you must make sure to add it to the CDO
namespace, or suppress the namespace by adding it to the global
namespace. If you do not do this, all ADO type information will reside
in the ADODB namespace by default, and CDO arguments that are ADO types
will not resolve at compile time. The following example demonstrates
this:
#import "c:\program files\common files\system\ado\msado15.dll" rename("ADODB","CDO") rename("EOF", "EndOfFile")#import <cdosys.dll>#include "cdosysstr.h"#include "cdosyserr.h"void main() { CoInitialize(NULL); { try { CDO::IMessagePtr iMsg(__uuidof(CDO::Message)); CDO::FieldsPtr Flds; Flds = iMsg->Fields; Flds->Item[cdoTo]->Value = _variant_t("example@example.com"); Flds->Item[cdoFrom]->Value = _variant_t("example@example.com"); Flds->Item[cdoSubject]->Value = _variant_t("a test"); Flds->Item[cdoTextDescription]->Value = _variant_t("this is a test"); Flds->Update(); iMsg->Send(); } catch( _com_error err) { // ... }} } CoUninitialize(); return 1;}