修复Duilib MenuDemo右键菜单背景色和前景色无效问题

问题描述

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里面的"要用&quot;代替,下同。博客插入代码后自动显示出来了。

这样出来效果如图:

可以看到:

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

文章如果有不严谨或者错误的地方,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值