//------------------------------------------------------------------------------
// $Workfile: ControlledWndT.h $
// $Header: /SbjDev/SbjCore/ControlledWndT.h 3 11/12/08 2:22p Steve $
//
// Copyright � 2008 SbjCat
// All rights reserved.
//
//
// *** Authors ***
// Steve Johnson
//
// $Revision: 3 $
//
//-----------------------------------------------------------------------------
#pragma once
#include "ControlledCmdTargetT.h"
#include "WndController.h"
namespace SbjCore
{
namespace Mvc
{
/**
template class wraps a CWnd or derivative to add a link to
a WndController class for processing messages.
ControlledWndT is derived from ControlledCmdTargetT and adds
an override to CWnd::OnWndMsg in order to route messages
to the assigned WndController. The ControlledWndT will set
the WndController in its constructor with a call to
ControlledCmdTargetT::SetController.
\param _baseClass Any CWnd or derived class
*/
template<class _baseClass>
class ControlledWndT : public ControlledCmdTargetT<_baseClass>
{
public:
/// ctor
ControlledWndT()
{
}
/// dtor
virtual ~ControlledWndT()
{
m_hWnd = NULL;
}
protected:
/** routes Windows messages to the Controller.
If the Controller::HandleWndMsg method returns true, it signals that
it has already handled the call to OnWndMsgDefault, otherwise, OnWndMsg
will call OnWndMsgDefault.
see MFC documentation for further information on CWnd::OnWndMsg
\return true if the message was handled, otherwise false.
*/
virtual BOOL OnWndMsg(UINT message,
WPARAM wParam,
LPARAM lParam,
LRESULT* pResult)
{
BOOL bRslt = false;
try
{
if (message == WM_CREATE)
{
message = WM_CREATE;
}
if (GetSafeHwnd() != NULL)
{
// do pre default handling
if ((pTheController != NULL) && (message != WM_COMMAND) && (message != WM_NOTIFY))
{
WndController* pTheWndCtrlr = dynamic_cast<WndController*>(pTheController);
if (pTheWndCtrlr->CallDefaultFirst(message))
{
// return _baseClass result
bRslt = _baseClass::OnWndMsg(message, wParam, lParam, pResult);
(void)pTheWndCtrlr->HandleWndMsg(message, wParam, lParam, pResult);
}
else
{
// return false to allow default processing
bRslt = pTheWndCtrlr->HandleWndMsg(message, wParam, lParam, pResult);
// do default handling
if (!bRslt)
{
bRslt = _baseClass::OnWndMsg(message, wParam, lParam, pResult);
}
}
}
else
{
bRslt = _baseClass::OnWndMsg(message, wParam, lParam, pResult);
}
}
}
catch(...)
{
// ignore exceptions (I think)
}
return bRslt;
}
/*
The following overrides are only here because the MFC versions called OnCmdMsg
and OnWndMsg as CWnd::OnCmdMsg and CWnd::OnWndMsg which bypassed the overrides
presented in ControlledWndT.h and ControlledCmdTarget.h.
*/
virtual BOOL OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
#ifndef _AFX_NO_OCC_SUPPORT
if (m_pCtrlSite != NULL)
{
// first forward raw OCM_ messages to OLE control sources
LRESULT lResult = SendMessage(OCM__BASE+uMsg, wParam, lParam);
if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC &&
(HBRUSH)lResult == NULL)
{
// for WM_CTLCOLOR msgs, returning NULL implies continue routing
return FALSE;
}
if (pResult != NULL)
*pResult = lResult;
return TRUE;
}
#endif
return ReflectChildNotify(uMsg, wParam, lParam, pResult);
}
struct AFX_CTLCOLOR
{
HWND hWnd;
HDC hDC;
UINT nCtlType;
};
BOOL ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// Note: reflected messages are send directly to CWnd::OnWndMsg
// and CWnd::OnCmdMsg for speed and because these messages are not
// routed by normal OnCmdMsg routing (they are only dispatched)
switch (uMsg)
{
// normal messages (just wParam, lParam through OnWndMsg)
case WM_HSCROLL:
case WM_VSCROLL:
case WM_PARENTNOTIFY:
case WM_DRAWITEM:
case WM_MEASUREITEM:
case WM_DELETEITEM:
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
case WM_COMPAREITEM:
// reflect the message through the message map as WM_REFLECT_BASE+uMsg
return OnWndMsg(WM_REFLECT_BASE+uMsg, wParam, lParam, pResult);
// special case for WM_COMMAND
case WM_COMMAND:
{
// reflect the message through the message map as OCM_COMMAND
int nCode = HIWORD(wParam);
if (OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_COMMAND), NULL, NULL))
{
if (pResult != NULL)
*pResult = 1;
return TRUE;
}
}
break;
// special case for WM_NOTIFY
case WM_NOTIFY:
{
// reflect the message through the message map as OCM_NOTIFY
NMHDR* pNMHDR = (NMHDR*)lParam;
int nCode = pNMHDR->code;
AFX_NOTIFY notify;
notify.pResult = pResult;
notify.pNMHDR = pNMHDR;
return OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL);
}
// other special cases (WM_CTLCOLOR family)
default:
if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC)
{
// fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
AFX_CTLCOLOR ctl;
ctl.hDC = (HDC)wParam;
ctl.nCtlType = uMsg - WM_CTLCOLORMSGBOX;
//ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
// reflect the message through the message map as OCM_CTLCOLOR
BOOL bResult = OnWndMsg(WM_REFLECT_BASE+WM_CTLCOLOR, 0, (LPARAM)&ctl, pResult);
if ((HBRUSH)*pResult == NULL)
bResult = FALSE;
return bResult;
}
break;
}
return FALSE; // let the parent handle it
}
};
}
}
//*** Modification History ***
// $Log: /SbjDev/SbjCore/ControlledWndT.h $
//
// 3 11/12/08 2:22p Steve
// Finished Generalization of Model v2.0.1