Featured image of post ATL in a Nutshell

ATL in a Nutshell

ATL in a Nutshell

A Brief History

Back in the day (1990s), Microsoft decided that COM should rule the world.

But writing COM components was about as fun as manually sorting a million lines of XML. MFC was around, but it was too heavyweight. So, Microsoft engineers, probably after one too many cups of coffee, came up with ATL.

It gave C++ devs a lightweight, efficient way to build COM objects without dragging in all the MFC baggage. Basically, if MFC was a Swiss Army knife, ATL was a sleek, laser-focused scalpel.

What Can You Do with ATL?

ATL is mostly about COM development, but it’s good for a few other things too:

  • Building COM Objects – The primary reason ATL exists. You can create ActiveX controls, shell extensions, and other COM-based goodies.
  • Handling Smart Pointers – ATL provides CComPtr to manage COM object lifetimes, so you don’t leak memory like a broken faucet.
  • Windowing Without MFC – It has lightweight windowing classes (CWindow, CWindowImpl) for UI work.
  • Threading Utilities – Provides some handy threading classes like CComAutoThreadModule.
  • Attribute-based Programming – ATL allows you to use attributes to generate boilerplate code for COM interfaces.

Common ATL Operations (with Code!)

1. Creating a Simple ATL COM Object

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <atlbase.h>
#include <atlcom.h>

class ATL_NO_VTABLE CSimpleCOM :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CSimpleCOM, &CLSID_SimpleCOM>,
    public IDispatch {
public:
    BEGIN_COM_MAP(CSimpleCOM)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()
};

What’s Happening?

  • CComObjectRootEx<CComSingleThreadModel> – Base class for reference counting.
  • CComCoClass<CSimpleCOM, &CLSID_SimpleCOM> – Connects our class with a GUID.
  • BEGIN_COM_MAP(CSimpleCOM) – Maps our class to the interfaces it supports.

2. Using Smart Pointers (CComPtr)

1
2
3
4
5
CComPtr<IMyInterface> spMyInterface;
HRESULT hr = spMyInterface.CoCreateInstance(CLSID_MyComponent);
if (FAILED(hr)) {
    printf("Oops, it failed!\n");
}

Why use CComPtr? Because Release() is for people who like memory leaks.

3. A Minimal ATL Window

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class CMyWindow : public CWindowImpl<CMyWindow> {
public:
    BEGIN_MSG_MAP(CMyWindow)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
    END_MSG_MAP()
    LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&) {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(&ps);
        TextOut(hdc, 10, 10, L"Hello, ATL!", 11);
        EndPaint(&ps);
        return 0;
    }
};

Alternatives to ATL

ATL isn’t the only way to do COM programming. Here are some alternatives:

  • MFC (Microsoft Foundation Classes) – If you don’t mind a bit of overhead and want more GUI features.
  • Raw Win32 API – For those who enjoy pain.
  • WRL (Windows Runtime Library) – Microsoft’s modern alternative for COM programming.
  • C# with .NET Interop – Because maybe C++ isn’t the best choice for your project?

References