Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Delphi

Implement Delphi TMethod in C++

4.50/5 (2 votes)
5 Dec 2010CPOL 8.4K  
How to dispatch event messages in C++ like a Delphi TMethod
/*
    created:    2010/12/04
    created:    4:12:2010   20:39
    filename:   EventHandler.h
    author:     [email deleted]

    purpose:
*/

#include <hash_map>

#ifndef __IMsgHandler_h__
#define __IMsgHandler_h__

struct IEventHandler
{
    virtual ~IEventHandler(void) {}
    virtual bool HandleEvent(void* pEvent) = 0;
};

template<typename ThisType, typename EventData>
class TMethod : public IEventHandler
{
public:
    typedef bool (ThisType::*TMemFun)(EventData* pEvent);

    TMethod(ThisType* pThis, TMemFun pFun)
        :m_pThis(pThis)
        ,m_pFun(pFun)
    {
    }

    virtual bool HandleEvent(void* pEvent)
    {
        return HandleEventMsg(static_cast<EventData*>(pEvent));
    }

    virtual bool HandleEventMsg(EventData* pEvent)
    {
        return (m_pThis->*m_pFun)(pEvent);
    }

private:
    ThisType*   m_pThis;
    TMemFun     m_pFun;
};

template<typename ThisType, typename EventData>
IEventHandler* NewEventHandler(ThisType* pThis,
                               bool (ThisType::*pFun)(EventData*))
{
    return new TMethod<ThisType, EventData>(pThis, pFun);
}


//EventHandlerMgr

struct IEventHandler;
typedef IEventHandler* PEventHandler;

typedef stdext::hash_multimap<unsigned int, IEventHandler*> EVENT_HANDLER_MAP;

class TEventHandlerMgr
{
    EVENT_HANDLER_MAP m_MsgHandlerMap;

public:
    TEventHandlerMgr(void) {}

    ~TEventHandlerMgr(void) {}

    bool Listen(unsigned int nEvnetId, PEventHandler pMsgHandler)
    {
        m_MsgHandlerMap.insert(std::make_pair(nEvnetId, pMsgHandler));
        return true;
    }

    PEventHandler FindEventHandler(unsigned int nEvnetId)
    {
        EVENT_HANDLER_MAP::iterator itr = m_MsgHandlerMap.find(nEvnetId);
        if (itr==m_MsgHandlerMap.end())
            return NULL;

        return itr->second;
    }

    bool RemoveListen(unsigned int nMsgId)
    {
        return true;
    }
};

#endif // __IMsgHandler_h__


/*
    created:    2010/12/04
    created:    4:12:2010   20:55
    filename:   TWidget.h
    author:     [email deleted]

    purpose:    Used for test IEventHandler
*/

#include "EventHandler.h"

#ifndef __TWidget_h__
#define __TWidget_h__

#define EVTID_MOUSE_CLICK 1

struct MouseClickInfo
{
    unsigned int nX;
    unsigned int nY;
};

class TWidget
{
protected:
    TEventHandlerMgr m_evtHandlerMgr;
public:
    TWidget(void) {}

    ~TWidget(void) {}

    bool Listen(unsigned int nEvnetId, PEventHandler pMsgHandler)
    {
        return m_evtHandlerMgr.Listen(nEvnetId, pMsgHandler);
    }

    bool RemoveListen(unsigned int nEvnetId)
    {
        return m_evtHandlerMgr.RemoveListen(nEvnetId);
    }

    void MouseClick()
    {
        PEventHandler pEvtHand = m_evtHandlerMgr.FindEventHandler(EVTID_MOUSE_CLICK);
        if (pEvtHand == NULL)
            return ;

        MouseClickInfo aMouseClickInfo;
        aMouseClickInfo.nX = 50;
        aMouseClickInfo.nY = 50;
        pEvtHand->HandleEvent(&aMouseClickInfo);
    }
};

class TDialog : TWidget
{
    TWidget m_btnOk;
    TWidget m_btnCancel;
    TWidget m_btnClose;

public:
    TDialog()
    {
        m_btnOk.Listen(EVTID_MOUSE_CLICK,    NewEventHandler(this, &TDialog::OnButtonOkClick));
        m_btnCancel.Listen(EVTID_MOUSE_CLICK,NewEventHandler(this, &TDialog::OnButtonCancelClick));
        m_btnClose.Listen(EVTID_MOUSE_CLICK, NewEventHandler(this, &TDialog::OnButtonCancelClick));
    }

    void SimulateClick()
    {
        m_btnOk.MouseClick();
    }

private:
    bool OnButtonOkClick(MouseClickInfo* pEvent)
    {
        pEvent->nX;
        pEvent->nY;

        return true;
    }

    bool OnButtonCancelClick(MouseClickInfo* pEvent)
    {
        pEvent->nX;
        return true;
    }
};

#endif // __TWidget_h__


int _tmain(int argc, _TCHAR* argv[])
{
    TDialog dlgMain;
    dlgMain.SimulateClick();

}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)