问题描述
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
文章如果有不严谨或者错误的地方,欢迎指正。