Windows Systems Programming: Spring 2002

[ Home | Syllabus | Course Notes | Assignments | Search]


ATL (chapter 5) - Building a Single Interface Version

NOTE: The version is chapter 5 of the book adds two interfaces which are not necessary to understanding ATL.
Here we will develop a single interface version which is closer to the version in chapter 4.


ATL handles much of the overhead for generating COM objects and is intended primarily for implementing COM servers. Consists of the following:


App Wizard Generated Files

These directions are similar to those on page 129

  1. Select FILE/NEW/PROJECTS Tab/ATL COM APPWizard

  2. Enter "ATLspellCheck" in project name

  3. Click OK

  4. Keep default "DLL" and click "finish"

You will get the following files


ATL Wizard

Now we will create a single ATL Object using the ATL Object Wizard

  1. Select "Insert/New ATL Object"

  2. Take the default of a "Simple Object" (shown here)/ select "Next"

  3. You should the "ATL Object Wizard  Properties" dialog, type "SpellChecker" in the "Short Name" field, take the defaults on the other derived names (you should see)

  4. Click the "Attributes" tab, set to "Custom" interface, select "OK"

 


COM Object 

SpellChecker.h

// SpellChecker.h : Declaration of the CSpellChecker

#ifndef __SPELLCHECKER_H_
#define __SPELLCHECKER_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CSpellChecker
class ATL_NO_VTABLE CSpellChecker: // multiple inheritance
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CSpellChecker, &CLSID_SpellChecker>, 
	public ISpellChecker
{
public:
	CSpellChecker()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_SPELLCHECKER)// registry info in this resource ID

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CSpellChecker) 
	COM_INTERFACE_ENTRY(ISpellChecker)
END_COM_MAP()

// ISpellChecker
public:
};

#endif //__SPELLCHECKER_H_

Defining the COM interfaces

Need to define the ISpellChecker interface methods.
This requires entries in the IDL, header and implementation files.


 

IDL File

// IDL

// ATLspellCheck.idl : IDL source for ATLspellCheck.dll
//

// This file will be processed by the MIDL tool to
// produce the type library (ATLspellCheck.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";
	[
		object,
		uuid(2FFB4D41-052A-497C-BE43-71B1D09B6360),
	
		helpstring("ISpellChecker Interface"),
		pointer_default(unique)
	]
	interface ISpellChecker : IUnknown
	{
		[helpstring("method CheckSpelling")] HRESULT CheckSpelling([in] LPOLESTR word, [out,retval] VARIANT_BOOL *result);
		[helpstring("method UseCustomDictionary")] HRESULT UseCustomDictionary([in] LPOLESTR path);
	};

[
	uuid(3FED244E-4367-4C8F-932C-C0DF67BEBAFC),
	version(1.0),
	helpstring("ATLspellCheck 1.0 Type Library")
]
library ATLSPELLCHECKLib
{
	importlib("stdole32.tlb");
	importlib("stdole2.tlb");

	[
		uuid(3D233E11-3661-4EA5-87C8-ABCFCFEE76BF),
		helpstring("SpellChecker Class")
	]
	coclass SpellChecker
	{
		[default] interface ISpellChecker;
	};
};
// header file
// ISpellChecker
public:
	STDMETHOD(UseCustomDictionary)(/*[in]*/ LPOLESTR path);
	STDMETHOD(CheckSpelling)(/*[in]*/ LPOLESTR word, /*[out,retval]*/ VARIANT_BOOL *result);
};
// implementation file
STDMETHODIMP CSpellChecker::CheckSpelling(LPOLESTR word, VARIANT_BOOL *result)
{
	// TODO: Add your implementation code here

	return S_OK;
}

STDMETHODIMP CSpellChecker::UseCustomDictionary(LPOLESTR path)
{
	// TODO: Add your implementation code here

	return S_OK;
}

The implementation of this method is almost identical to that for the previous version.

Main difference is use of Wide characters (OLDSTR, wstring) which is compatible with OLE and type libraries.

Also, you need to add "/GX" to Project/Settings/C++ tab/General/Project Options"

See source code


Advantages of using ATL

Check out OLE view in visual studio.

 


Building a Client

Similar interface built in MFC - but access to the COM object is different. Since we will use visual C++ NATIVE COM support by importing the type library. Notice we are using non-native types (OLESTR, LPOLESTR and VARIANT_BOOL. These types are language independent types.

With the type library you can examine the interface using OLEviewer or other suitable object browser.

   By adding an "import" of the type library into "stdafx.h", when the project is built - Visual C++ will use the type library to write "wrapper" classes around the COM interface to make the COM object act like a normal C++ object.

  1. Select "File/New/Projects/MFC AppWizard"

  2. name the project ATLclient

  3. Select "Dialog-based/Finish"

The dialog will be similar to that defined in chapter 4


ATLspellCheck.tlh

#include <comdef.h> 
namespace ATLSPELLCHECKLib { 
struct /* coclass */ SpellChecker;
struct __declspec(uuid("2ffb4d41-052a-497c-be43-71b1d09b6360"))
/* interface */ ISpellChecker;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(ISpellChecker, __uuidof(ISpellChecker));

//
// Type library items
//

struct __declspec(uuid("3d233e11-3661-4ea5-87c8-abcfcfee76bf"))
SpellChecker;
    // [ default ] interface ISpellChecker

struct __declspec(uuid("2ffb4d41-052a-497c-be43-71b1d09b6360"))//  interface ID
ISpellChecker : IUnknown
{
    //
    // Wrapper methods for error-handling
    //

    VARIANT_BOOL CheckSpelling ( 
        LPWSTR word );
    HRESULT UseCustomDictionary (
        LPWSTR path );

    //
    // Raw methods provided by interface
    //

    virtual HRESULT __stdcall raw_CheckSpelling (
        LPWSTR word,
        VARIANT_BOOL * result ) = 0;
    virtual HRESULT __stdcall raw_UseCustomDictionary (
        LPWSTR path ) = 0;
};

---- To access this information - need to add the following line of code to the header file near top 

using namespace ATLSPELLCHECKLib;

and the following inside the class definition

private:
    ISpellCheckerPtr mSpellChecker;

---- to create the COM object, add the following to OnInitDialog

HRESULT hr=mSpellChecker.CreateInstance("ATLspellCheck.SpellChecker"); 
if (FAILED(hr)) {
    AfxMessageBox("Could not instantiate the server.\n" \
    "Check that it is registered.");
}

//Notice the use of the Prog.ID instead of the CLSID (which would have been the following)

HRESULT hr=mSpellChecker.CreateInstance(__uuidof(SpellChecker)); 

// Now just need to add the "logic"

For the client, the difference are small, but include

Source Code here

 


Copyright chris wild 1999-2002.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: March 17, 2002.