• 仿酷狗音乐播放器开发日志十九——CTreeNodeUI的bug修复二(附源码)


    转载请说明原出处,谢谢

           今天本来打算把仿酷狗播放列表的子控件拖动插入功能做一下,但是仔细使用播放列表控件时发现了几个逻辑错误,由于我的播放

    列表控件是基于CTreeViewUI和CTreeNodeUI做得,所以产生这几个bug的原因还在于他们两个,在《仿酷狗音乐播放器开发日志十一

    ——CTreeNodeUI的bug修复》中已经修复过一个动态添加控件的相关bug,这属于第二次修复了。关于第一次bug的修复,后来

    Duilib扩展群的 joe 又进行过比我更全面的修复,我现在使用的CTreeViewUI就是joe修复过的,文章结尾会把第二次修复后的源文件免

    费提供给大家。

           我先来描述一下这个bug。

            第一个BUG:

            含有子节点的CTreeNodeUI节点的选中和未选中状态是相反的,这个在我给播放列表添加音乐项目后可以看到,如图:

            

            这一点让人觉得很不舒服,看了一下源码,负责展开与收缩的函数是CTreeViewUI的OnFolderChanged函数和OnDBClickItem,

    CTreeNodeUI在收缩按钮被单击或者整体被双击时就会去分别调用这两个函数,看了这两个函数的源码,发现了一些逻辑错误。首

    先看OnFolderChanged函数的源码:


    bool CTreeViewUI::OnFolderChanged( TNotifyUI* pTNotifyUI,LPARAM lParam,WPARAM wParam )
    {
    	if(pTNotifyUI->sType == DUI_MSGTYPE_SELECTCHANGED)
    	{
    		CCheckBoxUI* pFolder = (CCheckBoxUI*)pTNotifyUI->pSender;
    		CTreeNodeUI* pItem = (CTreeNodeUI*)pFolder->GetParent()->GetParent();
    		pItem->SetVisibleTag(!pFolder->GetCheck());
    		SetItemExpand(!pFolder->GetCheck(),pItem);
    		return true;
    	}
    	return false;
    }



            问题出在pItem->SetVisibleTag(!pFolder->GetCheck());和SetItemExpand(!pFolder->GetCheck(),pItem);上,收缩按钮默认状态下

    未选中状态,当我点击了收缩按钮后,CCheckedUI控件会自动设置自己为选中状态,这时pFolder->GetCheck()会返回真,而

    OnFolderChanged函数却取反,得到了假,然后再调用SetVisibleTag和SetItemExpand函数,恰好得到了相反结果,所以在这里把

    取反去掉就可以了。


           第二个BUG:

           接着看看OnDBClickItem函数的源码:


    bool CTreeViewUI::OnDBClickItem( TNotifyUI* pTNotifyUI,LPARAM lParam,WPARAM wParam )
    {
    	if(pTNotifyUI->sType == DUI_MSGTYPE_ITEMDBCLICK)
    	{
    		CTreeNodeUI* pItem		= static_cast<CTreeNodeUI*>(pTNotifyUI->pSender);
    		CCheckBoxUI* pFolder	= pItem->GetFolderButton();
    		pFolder->Selected(!pFolder->IsSelected());
    		pItem->SetVisibleTag(!pFolder->GetCheck());
    		SetItemExpand(!pFolder->GetCheck(),pItem);
    		return true;
    	}
    	return false;
    }



             这个的bug同样也是那两句代码,在双击了包含子节点的了CTreeViewUI控件后进入到此函数内,第一步先获取收缩按钮的句柄

    并且将他的选中状态取反,pFolder->Selected(!pFolder->IsSelected());,这句代码没问题。接下来收缩按钮的状态已经为正确的状态

    了,此时调用pFolder->GetCheck()后得到的就是正确值,不应该再取反了。所以后面的两句代码又把逻辑搞反了,应该把取反去

    掉。

            第三个BUG:

            在仿酷狗程序中,动态添加音乐项目到播放列表里,这是必须的功能,动态添加的功能已经做好。但是我发现,当一个分组本

    来在收缩状态下,这是给它动态添加音乐项目就会发生很搞笑的问题:分组没有自动展开,而动态添加的项目却显示了出来,如

    图:

              

            可以看到,一共有20个音乐项目,原本的10个已经在收缩状态下所以没有显示,而新添加的项目却直接显示了出来。这里应该

    有两种处理逻辑:

             1)动态添加子项目时,发现分组处于收缩状态后,新添加的项目自动隐藏而不显示出来

             2)动态添加子项目时,发现分组处于收缩状态后,把分组先展开,然后再添加

           为此我先测试了酷狗播放器的行为,发现给它添加项目时,它使用了第二种逻辑,那我也使用了同样的逻辑。修复这个bug只要

    在CTreeNodeUI添加元素时进行判断,发现自己出于收缩状态,就通知CTreeViewUI,让自己先展开。修改CTreeNodeUI的AddAt和

    AddChildNode函数,在适当位置添加判断即可,需要添加的代码为:


    if (!GetFolderButton()->IsSelected())       
    {
    	m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMDBCLICK);
    }


            修改后完整代码为:

    bool CTreeNodeUI::AddChildNode( CTreeNodeUI* _pTreeNodeUI )
    {
    	if (!_pTreeNodeUI)
    		return false;
    
    	if (_tcsicmp(_pTreeNodeUI->GetClass(), _T("TreeNodeUI")) != 0)
    		return false;
    
    	if (!GetFolderButton()->IsSelected())       //add by:Redrain   2014.8.8
    	{
    		m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMDBCLICK);
    	}
    
    	_pTreeNodeUI = CalLocation(_pTreeNodeUI);
    
    	bool nRet = true;
    
    	if(pTreeView){
    		CTreeNodeUI* pNode = static_cast<CTreeNodeUI*>(mTreeNodes.GetAt(mTreeNodes.GetSize()-1));
    		if(!pNode || !pNode->GetLastNode())
    			nRet = pTreeView->AddAt(_pTreeNodeUI,GetTreeIndex()+1) >= 0;
    		else nRet = pTreeView->AddAt(_pTreeNodeUI,pNode->GetLastNode()->GetTreeIndex()+1) >= 0;
    	}
    
    	if(nRet)
    		mTreeNodes.Add(_pTreeNodeUI);
    
    	return nRet;
    }
    bool CTreeNodeUI::AddAt( CControlUI* pControl, int iIndex )
    {
        if (!pControl)
            return false;
    
        if(_tcsicmp(pControl->GetClass(), _T("TreeNodeUI")) != 0)
            return false;
    
    	if (!GetFolderButton()->IsSelected())    //add by:Redrain   2014.8.8
    	{
    		m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMDBCLICK);
    	}
    
        //filter invalidate index
        int iDestIndex = iIndex;
        if (iDestIndex < 0)
        {
            iDestIndex = 0;
        }
        else if (iDestIndex > GetCountChild())
        {
            iDestIndex = GetCountChild();
        }
    //省略·····



            总结:

            在开发仿酷狗播放器的过程中已经修复了好几个bug,估计以后还有会,duilib的作者不维护,只能靠我们这些使

    用者自己修复了。此次修复只是我临时修改,如果有不妥的地方,请联系我,我会及时修复代码。在代码里搜

    索“//add by:Redrain   2014.8.8”和“//edit by:Redrain   2014.8.8 ” 可以找到我修改的地方。此源码是第二次修复

    bug,在这之前已经修复了无法动态添加节点的bug。

            源码下载地址:点击打开链接


           Redrain  2014.8.8  20:29    QQ:491646717

  • 相关阅读:
    数据库系统概念PDF下载
    数据库系统基础教程PDF下载
    推荐系统技术、评估及高效算法PDF下载
    系统分析与设计方法PDF下载
    像计算机科学家一样思考pythonPDF下载
    学习bashPDF下载
    厚书读薄丨《Vim实用技巧》第一部分 模式
    Code Server 是什么?
    ubuntu磁盘分区
    Linux自学之旅-基础命令(umask默认权限)
  • 原文地址:https://www.cnblogs.com/redrainblog/p/3902686.html
Copyright © 2020-2023  润新知