Plug-In Components for MFC
by Stefan Hoenig


Listing One
void CMyView::OnMouseMove(UINT nFlags, CPoint point) 
{
// forward this event to an attached object
m_pObject->OnMouseMove(nFlags, point);
CView::OnMouseMove(nFlags, point);
}

Listing Two
void CUserActionComponent::HandleMessage(UINT nMessage, WPARAM wParam, LPARAM lParam)
{
    switch (nMessage)
    {
    case WM_MOUSEMOVE:
        OnMouseMove(wParam, CPoint(LOWORD(lParam), HIWORD(lParam));
        break;
    }
}
}

Listing Three
BOOL CDDJPluginComponent::HandleMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    m_bSkipOtherPlugins = FALSE;
    m_bExitMesssage = FALSE;
    return CWnd::OnWndMsg(message, wParam, lParam, pResult);
}


Listing Four
LRESULT CMyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
    if (m_pPlugin)
    {
        LRESULT lResult;
m_pPlugin->HandleMessage(message, wParam, lParam, &lResult);
        if (m_pPlugin->m_bExitMesssage)
            return lResult;
    }
    return CScrollView::WindowProc(message, wParam, lParam);
}

Listing Five
_AFXWIN_INLINE void CWnd::Invalidate(BOOL bErase)
    { ASSERT(::IsWindow(m_hWnd)); ::InvalidateRect(m_hWnd, NULL, bErase); }

Listing Six
LRESULT CDDJPluginComponent::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // do nothing - this makes sure that calls to Default() will have no 
    // effect (and thus make sure that the same message is not process twice).
    return 0;
}


Listing Seven
// ddjplgin.h : interface of the CDDJPluginComponent class
#ifndef _DDJPLGIN_H_
#define _DDJPLGIN_H_

class CDDJPluginComponent: public CWnd
{
    DECLARE_DYNAMIC(CDDJPluginComponent);
public:
    CDDJPluginComponent();
    BOOL PlugIn(CWnd* pParentWnd);
    virtual ~CDDJPluginComponent();
public:
    // Attributes 
    // Reserved for later usage with a PluginManager
    BOOL m_bSkipOtherPlugins; // set to TRUE from within message handler if 
                                 // no other plugins should be 
                                 // called for this message
    BOOL m_bExitMesssage;     // set to TRUE from within your message handler
                                 // if no other plugins and also not the 
                                 // default window message should be called
// Generated message map functions
protected:
    //{{AFX_MSG(CDDJPluginComponent)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
public:
    // for processing Windows messages
    BOOL HandleMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
protected:
    // for handling default processing
    virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif
};
#endif //_DDJPLGIN_H_

Listing Eight
// ddjplgin.cpp : implementation of the CDDJPluginComponent class
#include "stdafx.h"
#include "resource.h"

#include "ddjplgin.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNAMIC(CDDJPluginComponent, CWnd);

CDDJPluginComponent::CDDJPluginComponent()
{
    m_bSkipOtherPlugins = FALSE;
    m_bExitMesssage = FALSE;
}
CDDJPluginComponent::~CDDJPluginComponent()
{
    // make sure Detach won't get called
    m_hWnd = NULL;
}
BEGIN_MESSAGE_MAP(CDDJPluginComponent, CWnd)
    //{{AFX_MSG_MAP(CDDJPluginComponent)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CDDJPluginComponent::PlugIn(CWnd* pParentWnd)
{
    m_hWnd = pParentWnd->GetSafeHwnd();
    return TRUE;
}
BOOL CDDJPluginComponent::HandleMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    m_bSkipOtherPlugins = FALSE;
    m_bExitMesssage = FALSE;
#if _MFC_VER >= 0x0400
    return CWnd::OnWndMsg(message, wParam, lParam, pResult);
#else
    *pResult = CWnd::WindowProc(message, wParam, lParam);
    return TRUE;
#endif
}
LRESULT CDDJPluginComponent::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
  // do nothing - this makes sure that calls to Default() will have no effect
  // (and thus make sure that the same message is not process twice).
  // Unused:
    message, wParam, lParam;
    return 0;
}
#ifdef _DEBUG
void CDDJPluginComponent::AssertValid() const
{
    if (m_hWnd == NULL)
        return;     // null (unattached) windows are valid
    // should be a normal window
    ASSERT(::IsWindow(m_hWnd));
    // Regular CWnd's check the permanent or temporary handle map and compare
    // the pointer to this. This will fail for a CDDJPluginComponent because 
    // several Plugin objects share the same HWND. Therefore we must not
    // call CWnd::AsssertValid.
}
void CDDJPluginComponent::Dump(CDumpContext& dc) const
{
    dc << "PluginComponent";
    // It is safe to call CWnd::Dump
    CWnd::Dump(dc);
}
#endif





3


