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;
}