问题描述
1.第三层菜单的选中项的前景色失效。
2.第二层及以上菜单背景色失效。XML中Default设置背景色bkcolor,只有第一层菜单生效,第二层及以后就没有效果了。
复现
直接使用MenuDemo的代码,稍微改一下XML布局,其中Default设置如下:
<Default name="Menu" value="inset="2,2,2,2" bkcolor="#ff43CD80" itemtextpadding="30,0,0,0" itemselectedbkcolor="#FF0179ff" itemhottextcolor="#FFFFFFFF" " />
注意,xml中value里面的"要用"代替,下同。博客插入代码后自动显示出来了。
这样出来效果如图:
可以看到:
1.第三层菜单的选中前景色效果和前两个不一样。
2.XML中Default设置绿色背景bkcolor="#ff43CD80";但是只有第一层菜单背景色是绿色的,后面就恢复默认的白色了。
原版Demo:
问题分析&解决
既然有源码,那直接找相关源码分析即可,应该问题不大。
解决菜单选中项前景色失效
经过观察可以看出来,第三层菜单的背景其实是List(Menu控件继承自List)控件的默认背景。那我们就找它为什么创建的时候会用默认的属性,在UIMenu.cpp中可以看到如下代码:
//UIMenu.cpp // MenuUI const TCHAR* const kMenuUIClassName = _T("MenuUI"); const TCHAR* const kMenuUIInterfaceName = _T("Menu"); LRESULT CMenuWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { if( uMsg == WM_CREATE ) { if( m_pOwner != NULL) { //... LPCTSTR pDefaultAttributes = m_pOwner->GetManager()->GetDefaultAttributeList(kMenuUIInterfaceName); if (pDefaultAttributes) { m_pLayout->SetAttributeList(pDefaultAttributes); } m_pLayout->SetBkColor(0xFFFFFFFF); m_pLayout->SetBorderColor(0xFF85E4FF); m_pLayout->SetBorderSize(0); m_pLayout->SetAutoDestroy(false); m_pLayout->EnableScrollBar(); //... }else{ //... } } //... }
看到pDefaultAttributes变量就是关键所在,右键查看GetDefaultAttributeList()的定义:
//UIManager.cpp LPCTSTR CPaintManagerUI::GetDefaultAttributeList(LPCTSTR pStrControlName) const { CDuiString* pDefaultAttr = static_cast<CDuiString*>(m_ResInfo.m_AttrHash.Find(pStrControlName)); if( !pDefaultAttr ) pDefaultAttr = static_cast<CDuiString*>(m_SharedResInfo.m_AttrHash.Find(pStrControlName)); if (pDefaultAttr) return pDefaultAttr->GetData(); return NULL; }
GetDefaultAttributeList(kMenuUIInterfaceName);
传入的是自定义的Menu控件名称,Duilib不自带,所以:
pDefaultAttr = static_cast<CDuiString*>(m_ResInfo.m_AttrHash.Find(pStrControlName));
返回空值。接下来就是这个了:
pDefaultAttr = static_cast<CDuiString*>(m_SharedResInfo.m_AttrHash.Find(pStrControlName));
可以看到找的是带Shared属性的。恍然大悟,回头看看布局XML:
Default name="Menu" value="inset="2,2,2,2" bkcolor="#ff43CD80" itemtextpadding="30,0,0,0" itemselectedbkcolor="#FF0179ff" itemhottextcolor="#FFFFFFFF" " />
发现没有shared属性,于是加上:
<Default name="Menu" shared="true" value="inset="2,2,2,2" bkcolor="#ff43CD80" itemtextpadding="30,0,0,0" itemselectedbkcolor="#FF0179ff" itemhottextcolor="#FFFFFFFF" " />
这样,问题就解决了。
解决菜单背景色失效
同样,在上面的代码中注意到:
LPCTSTR pDefaultAttributes = m_pOwner->GetManager()->GetDefaultAttributeList(kMenuUIInterfaceName); if (pDefaultAttributes) { m_pLayout->SetAttributeList(pDefaultAttributes); } m_pLayout->SetBkColor(0xFFFFFFFF); m_pLayout->SetBorderColor(0xFF85E4FF); m_pLayout->SetBorderSize(0); m_pLayout->SetAutoDestroy(false); m_pLayout->EnableScrollBar();
这个顺序是有点问题的,加载了默认属性后又覆盖设置成固定值,把顺序更改如下:
//UIMenu.cpp LRESULT CMenuWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { if( uMsg == WM_CREATE ) { if( m_pOwner != NULL) { //... m_pLayout->SetBkColor(0xFFFFFFFF); m_pLayout->SetBorderColor(0xFF85E4FF); m_pLayout->SetBorderSize(0); m_pLayout->SetAutoDestroy(false); m_pLayout->EnableScrollBar(); LPCTSTR pDefaultAttributes = m_pOwner->GetManager()->GetDefaultAttributeList(kMenuUIInterfaceName); if (pDefaultAttributes) { m_pLayout->SetAttributeList(pDefaultAttributes); } //... }else{ //... } } //... }
这样,问题解决,最后效果:
那为什么第一层菜单背景没有问题呢?因为第一层菜单的m_pOwner = NULL,走的是else分支的代码,那里没有问题。
END
文章如果有不严谨或者错误的地方,欢迎指正。
如果觉得《修复Duilib MenuDemo右键菜单背景色和前景色无效问题》对你有帮助,请点赞、收藏,并留下你的观点哦!