Re: MessageMap - Funktionszeiger - VS2008
Giovanni Dicanio ha scritto:
The problem is that CRMessageMapTest::func1 is a *non-static* member
function.
If you make CRMessageMapTest::func1() static, I think that it will compile.
If you need some "context" (like the "this" pointer), you may want to
pass it as an additional parameter.
Another approach to implement a custom message map could be to use a map
container (like STL std::map), and associate event IDs to member
functions of C++ classes.
You may want to download a sample MFC project here:
http://www.geocities.com/giovanni.dicanio/vc/TestCustomMessageMap.zip
"MessageMapTest.h" is the key file where the custom message map is
implemented:
<code filename="MessageMapTest.h">
//////////////////////////////////////////////////////////////////////////
// FILE: MessageMapTest.h
// DESC: Implementation of a custom message-map mechanism.
//
// This kind of message map associates an event ID to a member function
// of C++ class, using template and std::map container.
// The event ID is the key in the map; the member function of a C++ class
// is the value in the map.
//
// (Add #include <map> in StdAfx.h)
//
//
// Giovanni Dicanio <giovanni DOT dicanio AT gmail.com>
//
// 2009, July 11th
//
//////////////////////////////////////////////////////////////////////////
namespace CustomMessageMap
{
//=======================================================================
// Common Infrastructure for Message Map
//=======================================================================
//-----------------------------------------------------------------------
// Define event types
//-----------------------------------------------------------------------
enum Event
{
Event_Click,
Event_DoubleClick,
Event_Resize
// ...add others
};
//-----------------------------------------------------------------------
// Common base interface for event handlers.
// Derived classes must implement operator()
//-----------------------------------------------------------------------
class IEventHandlerBase
{
public:
// Define virtual destructor for proper cleanup of derived classes
virtual ~IEventHandlerBase() {}
// Derived classes must implement operator()
virtual void operator()(DWORD customData) = 0;
};
//-----------------------------------------------------------------------
// Event Handler template class
//-----------------------------------------------------------------------
template <typename T>
class CEventHandler : public IEventHandlerBase
{
public:
// The event handler method has a prototype like this:
//
// void HandleSomeEvent(DWORD customData);
//
typedef void (T::*HandleEvent)(DWORD);
// Pass the address of the instance of the event handling class
('obj'),
// and the address of the member function ('f') of this class that
handles the event.
CEventHandler(T * obj, HandleEvent f)
: m_obj(obj), m_eventFunction(f)
{
}
// operator() calls the member function event handler,
// passing custom data
void operator()(DWORD customData)
{
(m_obj->*m_eventFunction)(customData);
}
private:
// This is the 'this' pointer of the handler class instance
T * m_obj;
// This is the address of the event-handler member function
HandleEvent m_eventFunction;
};
//-----------------------------------------------------------------------
// This function creates an event handler object on the heap.
// The returned pointer must be freed using 'delete'.
//-----------------------------------------------------------------------
template <typename T>
CEventHandler<T> * CreateHandler(
T * obj,
typename CEventHandler<T>::HandleEvent f )
{
return new CEventHandler<T>(obj, f);
}
//=======================================================================
//=======================================================================
// Define Some Sample Event Handlers
//
// These are simple example handlers, that just display a message-box
// with event name and hex representation of custom data.
//=======================================================================
//-----------------------------------------------------------------------
// Class to handle click event
//-----------------------------------------------------------------------
class CEventClickHandler
{
public:
void HandleClick(DWORD customData)
{
CString msg;
msg.Format(_T("Handle Click Event (data = %08X)"), customData);
AfxMessageBox(msg, MB_OK);
}
};
//-----------------------------------------------------------------------
// Class to handle double-click event
//-----------------------------------------------------------------------
class CEventDoubleClickHandler
{
public:
void HandleDoubleClick(DWORD customData)
{
CString msg;
msg.Format(_T("Handle Double-Click Event (data = %08X)"),
customData);
AfxMessageBox(msg, MB_OK);
}
};
//-----------------------------------------------------------------------
// Class to handle resize event
//-----------------------------------------------------------------------
class CEventResizeHandler
{
public:
void HandleResize(DWORD customData)
{
CString msg;
msg.Format(_T("Handle Resize Event (data = %08X)"), customData);
AfxMessageBox(msg, MB_OK);
}
};
//-----------------------------------------------------------------------
// Testing custom message map
//-----------------------------------------------------------------------
class CMessageMapTest
{
public:
// Build the message map, filling the std::map data member
CMessageMapTest()
{
// Add event handlers to the map
m_events[Event_Click] = CreateHandler(&m_click,
&CEventClickHandler::HandleClick);
m_events[Event_DoubleClick] = CreateHandler(&m_doubleClick,
&CEventDoubleClickHandler::HandleDoubleClick);
m_events[Event_Resize] = CreateHandler(&m_resize,
&CEventResizeHandler::HandleResize);
}
// Cleanup the message map
virtual ~CMessageMapTest()
{
// Delete pointers stored in map
EventHandlers::iterator it;
for (it = m_events.begin(); it != m_events.end(); ++it)
{
delete it->second;
it->second = NULL;
}
// Clear the map
m_events.clear();
}
// Handle a particular event
void HandleEvent(Event event, DWORD customData)
{
// Call event handler using map
(*m_events[event])(customData);
}
private:
// Event handlers is a map that associates an event ID to an event
handler object
typedef std::map< Event, IEventHandlerBase * > EventHandlers;
// Event handlers stored as data members here
EventHandlers m_events;
// Instantiate event handler classes as data members
CEventClickHandler m_click;
CEventDoubleClickHandler m_doubleClick;
CEventResizeHandler m_resize;
};
}; // namespace CustomMessageMap
//////////////////////////////////////////////////////////////////////////
</code>
HTH,
Giovanni