Featured image of post MFC CCommandTarget In Detail

MFC CCommandTarget In Detail

Exploring CCommandTarget

MFC CCommandTarget In Detail

Introduction

Ah, MFC (Microsoft Foundation Classes).

If you’ve been around C++ and Windows programming long enough, you’ve probably either loved it or cursed it—possibly both at the same time.

And today, we’re diving into one of its most “mysterious” classes: CCommandTarget.

What is CCommandTarget?

Simply put, CCommandTarget is a base class in MFC that provides message-handling capabilities.

If you’ve ever written an MFC application, there’s a high chance you’ve been using CCommandTarget without even realizing it—because CWnd (the base class for all MFC windows) derives from it.

It’s the foundation for:

  • Message maps (ON_COMMAND, ON_UPDATE_COMMAND_UI, etc.)
  • OLE automation
  • ActiveX control hosting
  • Inter-object communication

So basically, it’s the unsung hero of MFC that makes sure your app listens when users click buttons, select menu items, or even interact with COM objects.

The Role of CCommandTarget in MFC

Think of CCommandTarget as the middle manager of your MFC app.

It doesn’t do the real work, but it makes sure the right messages get to the right places.

It enables the infamous message maps, which allow MFC to handle Windows messages in a clean, object-oriented manner.

Key Features of CCommandTarget:

  1. Message Maps: This is how MFC handles user input. Instead of dealing with raw Windows messages, you use ON_COMMAND, ON_WM_PAINT, and other macros to neatly direct messages to class methods.
  2. Dispatch Maps: If your class needs to expose functions to OLE automation (think scripting and COM integration), this feature lets you do it.
  3. Interface Maps: Used in conjunction with COM to expose interfaces.
  4. Serialization Support: Allows objects to be saved and loaded easily.

Message Maps: The Magic Behind CCommandTarget

Without CCommandTarget, you’d be manually processing messages using giant switch statements. Instead, MFC provides a structured way to handle UI commands with message maps.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class CMyDialog : public CDialog
{
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnButtonClick();
};

BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
    ON_BN_CLICKED(IDC_MYBUTTON, &CMyDialog::OnButtonClick)
END_MESSAGE_MAP()

void CMyDialog::OnButtonClick()
{
    AfxMessageBox(_T("Button clicked!"));
}

Here, CCommandTarget ensures that when a button is clicked, the right function (OnButtonClick) is called.

OLE and COM: CCommandTarget’s Secret Superpowers

If you’ve worked with OLE automation or ActiveX, you’ve already used CCommandTarget’s dispatch and interface maps.

Exposing Functions to OLE:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class CMyAutomationObject : public CCmdTarget
{
    DECLARE_DYNCREATE(CMyAutomationObject)
    DECLARE_DISPATCH_MAP()

public:
    afx_msg void MyFunction();
};

BEGIN_DISPATCH_MAP(CMyAutomationObject, CCmdTarget)
    DISP_FUNCTION(CMyAutomationObject, "MyFunction", MyFunction, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

void CMyAutomationObject::MyFunction()
{
    AfxMessageBox(_T("Called via OLE!"));
}

With this setup, external programs (like VBA, Python, or even another C++ app) can call MyFunction via COM.

Serialization: Making Objects Persist

CCommandTarget supports MFC’s serialization mechanism, meaning you can easily save and load objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class CMyData : public CObject
{
    DECLARE_SERIAL(CMyData)
public:
    CString m_strData;
    void Serialize(CArchive& ar);
};

IMPLEMENT_SERIAL(CMyData, CObject, 1)

void CMyData::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
        ar << m_strData;
    else
        ar >> m_strData;
}

This allows CMyData objects to be stored and retrieved from files, databases, or even network streams.

When to Use CCommandTarget (and When to Avoid It)

Use CCommandTarget When:

  • You need to handle UI commands in an MFC app.
  • You’re implementing OLE automation.
  • You need serialization support.
  • You’re building an ActiveX control.

Avoid CCommandTarget When:

  • You’re writing non-MFC applications.
  • You prefer modern C++ techniques (like std::function for event handling).
  • You don’t need message maps or COM integration.

Conclusion

CCommandTarget is like the plumbing in your house—essential but mostly invisible. It powers message handling, OLE automation, and serialization in MFC applications. While modern C++ has moved on with things like signals/slots and event-driven programming, if you’re maintaining or extending an MFC application, understanding CCommandTarget is a must.

So the next time your MFC app does something cool, take a moment to appreciate CCommandTarget—the silent workhorse of MFC!


Key Ideas

ConceptDescription
CCommandTargetBase class for handling MFC messages, OLE, and serialization
Message MapsAllows MFC apps to handle UI events cleanly
OLE AutomationEnables COM integration and scripting support
SerializationSaves and loads objects easily
When to UseUI commands, OLE, ActiveX, serialization

References