http://www.duilib.com/ duilib官网。
class C360SafeFrameWnd : public CWindowWnd, public INotifyUI
主窗口类继承于 INotifyUI类。
在窗口类中实现函数Notify()
void Notify(TNotifyUI& msg)
在Notify函数中根据msg消息的发送者/消息类型,判断按钮,并写功能代码。
在主窗口类C360SafeFrameWnd的OnCreate实现中:
CControlUI* pRoot = builder.Create(tstrSkin.c_str(), (UINT)0, &cb, &m_pm); //加载XML并动态创建界面无素,与布局界面元素 ASSERT(pRoot && _T("Failed to parse XML")); m_pm.AttachDialog(pRoot); //控件与m_pm(CPaintMangerUI)关联 //这里间接设置控件的CPaintManagerUI??? //会间接CPaintManagerUI的InitControls(pControl);
CPaintMnagerUI的InitControls函数中调用CControlUI的SetManager,这样控件就与m_pm相关联。
bool CPaintManagerUI::InitControls(CControlUI* pControl, CControlUI* pParent /*= NULL*/) { ASSERT(pControl); if( pControl == NULL ) return false; pControl->SetManager(this, pParent != NULL ? pParent : pControl->GetParent(), true); pControl->FindControl(__FindControlFromNameHash, this, UIFIND_ALL); return true; }
再之后在主窗口类OnCreate中
m_pm.AddNotifier(this);
m_pm的m_aNotifiers成员加上主窗口类本身。
这样,点击按钮的时候,调用流程是 CButtonUI::Event--->CButtonUI::Activate()--->CButtonUI成员m_pManager的SendNotify
---->CPaintMangerUI成员m_aNotifier的Notify (也就包含主窗口类的Notify函数)
for( int i = 0; i < m_aNotifiers.GetSize(); i++ ) { static_cast<INotifyUI*>(m_aNotifiers[i])->Notify(Msg); }
疑惑:
CControlUI* pRoot = builder.Create(tstrSkin.c_str(), (UINT)0, &cb, &m_pm);
builder.Create中循环递归解析xml中的元素,最后调用:
CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager)
_Parse函数中,先是:
// Init default attributes if( pManager ) { pControl->SetManager(pManager, NULL, false); //此处设置控件的CPaintManager
最后又有:
if( pManager ) { pControl->SetManager(NULL, NULL, false); }
ezhong的博客园:http://www.cnblogs.com/ezhong/