老舅程序猿

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
    duilib版本367
 
duilib 这个版本也集成了类似MFC的消息宏,懂MFC的朋友应该很容易就弄明白了,也可以参考《深入浅出MFC》里对消息宏的讲解。
 
typedef void (CNotifyPump::*DUI_PMSG)(TNotifyUI& msg);  //指针类型
 
//结构定义
struct DUI_MSGMAP_ENTRY //定义一个结构体,来存放消息信息
{
    CDuiString sMsgType;          // DUI消息类型
    CDuiString sCtrlName;         // 控件名称
    UINT       nSig;              // 标记函数指针类型
    DUI_PMSG   pfn;               // 指向函数的指针
};
 
struct DUI_MSGMAP
{
#ifndef UILIB_STATIC
    const DUI_MSGMAP* (PASCAL* pfnGetBaseMap)();        //返回消息映射   
#else
    const DUI_MSGMAP* pBaseMap;                          //返回基类的DUI_MSGMAP*
#endif
    const DUI_MSGMAP_ENTRY* lpEntries;                   //消息实体指针
};
 
______________________________________________________________________________________________________________________________________
 
//定义
#ifndef UILIB_STATIC
#define DUI_DECLARE_MESSAGE_MAP()                                         \
private:                                                                  \
    static const DUI_MSGMAP_ENTRY _messageEntries[];                      \
protected:                                                                \
    static const DUI_MSGMAP messageMap;                                   \
    static const DUI_MSGMAP* PASCAL _GetBaseMessageMap();                 \
    virtual const DUI_MSGMAP* GetMessageMap() const;                      \
#else
#define DUI_DECLARE_MESSAGE_MAP()                                         \
private:                                                                  \
    static const DUI_MSGMAP_ENTRY _messageEntries[];                      \
protected:                                                                \
    static  const DUI_MSGMAP messageMap;                                  \
    virtual const DUI_MSGMAP* GetMessageMap() const;                      \
#endif
 
 
class UILIB_API CNotifyPump
{
public:
    bool AddVirtualWnd(CDuiString strName,CNotifyPump* pObject);
    bool RemoveVirtualWnd(CDuiString strName);
    void NotifyPump(TNotifyUI& msg);
    bool LoopDispatch(TNotifyUI& msg);
    DUI_DECLARE_MESSAGE_MAP()
private:
    CStdStringPtrMap m_VirtualWndMap;
};
 
相当于
class UILIB_API CNotifyPump
{
public:
    bool AddVirtualWnd(CDuiString strName,CNotifyPump* pObject);
    bool RemoveVirtualWnd(CDuiString strName);
    void NotifyPump(TNotifyUI& msg);
    bool LoopDispatch(TNotifyUI& msg);
 
private:                                                     //注意static             
    static const DUI_MSGMAP_ENTRY _messageEntries[];                      
protected:                                                                
    static const DUI_MSGMAP messageMap;                                   
    static const DUI_MSGMAP* PASCAL _GetBaseMessageMap();                 
    virtual const DUI_MSGMAP* GetMessageMap() const;
  
           
         
private:
    CStdStringPtrMap m_VirtualWndMap;
};
 
 
//基类声明开始
#ifndef UILIB_STATIC
#define DUI_BASE_BEGIN_MESSAGE_MAP(theClass)                              \
    const DUI_MSGMAP* PASCAL theClass::_GetBaseMessageMap()               \
        { return NULL; }                                                  \
    const DUI_MSGMAP* theClass::GetMessageMap() const                     \
        { return &theClass::messageMap; }                                 \
    UILIB_COMDAT const DUI_MSGMAP theClass::messageMap =                  \
        {  &theClass::_GetBaseMessageMap, &theClass::_messageEntries[0] };\
    UILIB_COMDAT const DUI_MSGMAP_ENTRY theClass::_messageEntries[] =     \
    {                                                                     \
#else
#define DUI_BASE_BEGIN_MESSAGE_MAP(theClass)                              \
    const DUI_MSGMAP* theClass::GetMessageMap() const                     \
        { return &theClass::messageMap; }                                 \
    UILIB_COMDAT const DUI_MSGMAP theClass::messageMap =                  \
        {  NULL, &theClass::_messageEntries[0] };                         \
    UILIB_COMDAT const DUI_MSGMAP_ENTRY theClass::_messageEntries[] =     \
    {                                                                     \
#endif
 
 
#define UILIB_COMDAT __declspec(selectany)
declspec(selectany)告诉编译器我要使用pick-any COMDAT,说白了就是跟编译器说我要在头文件里初始化东西。参考:http://blog.csdn.net/win2ks/article/details/2537463
 
DUI_BASE_BEGIN_MESSAGE_MAP 用在CNotifyPump类的 cpp里:
 
DUI_BASE_BEGIN_MESSAGE_MAP(CNotifyPump)
DUI_END_MESSAGE_MAP()
 
相当于
const DUI_MSGMAP* PASCAL CNotifyPump::_GetBaseMessageMap()               
        { return NULL; }                                                  
const DUI_MSGMAP* CNotifyPump::GetMessageMap() const                     
        { return &CNotifyPump::messageMap; }                                 
UILIB_COMDAT const DUI_MSGMAP theClass::messageMap =                  
        {  &CNotifyPump::_GetBaseMessageMap, &CNotifyPump::_messageEntries[0] };
UILIB_COMDAT const DUI_MSGMAP_ENTRY theClass::_messageEntries[] =     
{                                                                                                           
        { _T(""), _T(""), DuiSig_end, (DUI_PMSG)0 }                           
};                                                                        
 
 
——————————————————————————————————————————————————————
 
//子类声明开始
#ifndef UILIB_STATIC
#define DUI_BEGIN_MESSAGE_MAP(theClass, baseClass)                        \
    const DUI_MSGMAP* PASCAL theClass::_GetBaseMessageMap()               \
        { return &baseClass::messageMap; }                                \
    const DUI_MSGMAP* theClass::GetMessageMap() const                     \
        { return &theClass::messageMap; }                                 \
    UILIB_COMDAT const DUI_MSGMAP theClass::messageMap =                  \
        { &theClass::_GetBaseMessageMap, &theClass::_messageEntries[0] }; \
    UILIB_COMDAT const DUI_MSGMAP_ENTRY theClass::_messageEntries[] =     \
    {                                                                     \
#else
#define DUI_BEGIN_MESSAGE_MAP(theClass, baseClass)                        \
    const DUI_MSGMAP* theClass::GetMessageMap() const                     \
        { return &theClass::messageMap; }                                 \
    UILIB_COMDAT const DUI_MSGMAP theClass::messageMap =                  \
        { &baseClass::messageMap, &theClass::_messageEntries[0] };        \
    UILIB_COMDAT const DUI_MSGMAP_ENTRY theClass::_messageEntries[] =     \
    {                                                                     \
#endif
//声明结束
#define DUI_END_MESSAGE_MAP()                                             \
    { _T(""), _T(""), DuiSig_end, (DUI_PMSG)0 }                           \
};                                                                        \
//定义消息类型--执行函数宏
#define DUI_ON_MSGTYPE(msgtype, memberFxn)                                \
    { msgtype, _T(""), DuiSig_vn, (DUI_PMSG)&memberFxn},                  \
//定义消息类型--控件名称--执行函数宏
#define DUI_ON_MSGTYPE_CTRNAME(msgtype,ctrname,memberFxn)                 \
    { msgtype, ctrname, DuiSig_vn, (DUI_PMSG)&memberFxn },                \
//定义click消息的控件名称--执行函数宏
#define DUI_ON_CLICK_CTRNAME(ctrname,memberFxn)                           \
    { DUI_MSGTYPE_CLICK, ctrname, DuiSig_vn, (DUI_PMSG)&memberFxn },      \
//定义selectchanged消息的控件名称--执行函数宏
#define DUI_ON_SELECTCHANGED_CTRNAME(ctrname,memberFxn)                   \
    { DUI_MSGTYPE_SELECTCHANGED,ctrname,DuiSig_vn,(DUI_PMSG)&memberFxn }, \
//定义killfocus消息的控件名称--执行函数宏
#define DUI_ON_KILLFOCUS_CTRNAME(ctrname,memberFxn)                       \
    { DUI_MSGTYPE_KILLFOCUS,ctrname,DuiSig_vn,(DUI_PMSG)&memberFxn },     \
//定义menu消息的控件名称--执行函数宏
#define DUI_ON_MENU_CTRNAME(ctrname,memberFxn)                            \
    { DUI_MSGTYPE_MENU,ctrname,DuiSig_vn,(DUI_PMSG)&memberFxn },          \
//定义与控件名称无关的消息宏
  //定义timer消息--执行函数宏
#define DUI_ON_TIMER()                                                    \
    { DUI_MSGTYPE_TIMER, _T(""), DuiSig_vn,(DUI_PMSG)&OnTimer },          \
 
——————————————————————————————————————————————————————————————————————
 
WindowImplBase 继承 CCNotifyPump 在Notify方法中,将消息发给NotifyPump
void WindowImplBase::Notify(TNotifyUI& msg)
{
    return CNotifyPump::NotifyPump(msg);
}
 
然后:
void CNotifyPump::NotifyPump(TNotifyUI& msg)
{
    ///遍历虚拟窗口
    if( !msg.sVirtualWnd.IsEmpty() ){
        for( int i = 0; i< m_VirtualWndMap.GetSize(); i++ ) {
            if( LPCTSTR key = m_VirtualWndMap.GetAt(i) ) {
                if( _tcsicmp(key, msg.sVirtualWnd.GetData()) == 0 ){
                    CNotifyPump* pObject = static_cast<CNotifyPump*>(m_VirtualWndMap.Find(key, false));
                    if( pObject && pObject->LoopDispatch(msg) )
                        return;
                }
            }
        }
    }
    ///
    //遍历主窗口
    LoopDispatch( msg );
}
 

static const DUI_MSGMAP_ENTRY* DuiFindMessageEntry(const DUI_MSGMAP_ENTRY* lpEntry,TNotifyUI& msg )
{
    CDuiString sMsgType = msg.sType;
    CDuiString sCtrlName = msg.pSender->GetName();
    const DUI_MSGMAP_ENTRY* pMsgTypeEntry = NULL;
    while (lpEntry->nSig != DuiSig_end)
    {
        if(lpEntry->sMsgType==sMsgType)
        {
            if(!lpEntry->sCtrlName.IsEmpty())
            {
                if(lpEntry->sCtrlName==sCtrlName)
                {
                    return lpEntry;
                }
            }
            else
            {
                pMsgTypeEntry = lpEntry;
            }
        }
        lpEntry++;
    }
    return pMsgTypeEntry;
}
获取到对应的DUI_MSGMAP_ENTRY
 
bool CNotifyPump::LoopDispatch(TNotifyUI& msg)
{
    const DUI_MSGMAP_ENTRY* lpEntry = NULL;
    const DUI_MSGMAP* pMessageMap = NULL;
#ifndef UILIB_STATIC
    for(pMessageMap = GetMessageMap(); pMessageMap!=NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)())
#else
    for(pMessageMap = GetMessageMap(); pMessageMap!=NULL; pMessageMap = pMessageMap->pBaseMap)
#endif
    {
#ifndef UILIB_STATIC
        ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
#else
        ASSERT(pMessageMap != pMessageMap->pBaseMap);
#endif
        if ((lpEntry = DuiFindMessageEntry(pMessageMap->lpEntries,msg)) != NULL)
        {
            goto LDispatch;
        }
    }
    return false;
LDispatch:
    union DuiMessageMapFunctions mmf;
    mmf.pfn = lpEntry->pfn;
    bool bRet = false;
   int nSig;
    nSig = lpEntry->nSig;
    switch (nSig)
    {
    default:
        ASSERT(FALSE);
        break;
    case DuiSig_lwl:
        (this->*mmf.pfn_Notify_lwl)(msg.wParam,msg.lParam);
        bRet = true;
        break;
    case DuiSig_vn:
        (this->*mmf.pfn_Notify_vn)(msg);
        bRet = true;
        break;
    }
    return bRet;
}
 
posted on 2012-12-26 11:34  老舅程序猿  阅读(1768)  评论(0编辑  收藏  举报