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