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

时间:2023-01-14 10:27:28

转载请说明原出处,谢谢

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

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

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

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

费提供给大家。

我先来描述一下这个bug。

        第一个BUG:

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

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

这一点让人觉得很不舒服,看了一下源码,负责展开与收缩的函数是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:

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

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

图:

仿酷狗音乐播放器开发日志十九——CTreeNodeUI的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

仿酷狗音乐播放器开发日志十九——CTreeNodeUI的bug修复二(附源码)的更多相关文章

  1. 仿酷狗音乐播放器开发日志二十七 用ole为窗体增加文件拖动功能(附源码)

    转载请说明原出处,谢谢~~ 中秋到了,出去玩了几天.今天把仿酷狗程序做了收尾,已经开发完成了,下一篇博客把完结的情况说一下.在这篇博客里说一下使用OLE为窗体增加文件拖拽的功能.使用播放器,我更喜欢直 ...

  2. 仿酷狗音乐播放器开发日志二十四 选项设置窗体的实现(附328行xml布局源码)

    转载请说明原出处,谢谢~~ 花了两天时间把仿酷狗的选项设置窗体做出来了,当然了只是做了外观.现在开学了,写代码的时间减少,所以整个仿酷狗的工程开发速度减慢了.今天把仿酷狗的选项设置窗体的布局代码分享出 ...

  3. 仿酷狗音乐播放器开发日志二十六 duilib在标题栏弹出菜单的方法

    转载请说明原出处,谢谢~~ 上篇日志说明了怎么让自定义控件响应右键消息.之后我给主窗体的标题栏增加右键响应,观察原酷狗后可以发现,在整个标题栏都是可以响应右键并弹出菜单的.应该的效果如下: 本以为像上 ...

  4. 仿酷狗音乐播放器开发日志二十五 duilib右键事件的不足的bug修复

    转载请说明原出处,谢谢~~ 虽然仿酷狗的各个菜单早就写好了,但是一直没有附加到程序里.今天把菜单和播放列表控件关联时发现了问题. 和播放列表相关的菜单有三个,分别是每个音乐项目控件相关的菜单.分组的菜 ...

  5. 仿酷狗音乐播放器开发日志二十三 修复Option控件显示状态不全的bug(附源码)

    转载请说明原出处,谢谢~~ 整个仿酷狗工程的开发将近尾声,现在还差选项设置窗体的部分,显然在设置窗体里用的最多的就是OptionUI控件,我在写好大致的布局后去测试效果,发现Option控件的显示效果 ...

  6. 仿酷狗音乐播放器开发日志十一——CTreeNodeUI的bug修复

    由于做播放列表控件,我的CMusicLength控件继承了CTreeVieWUI控件,在向分组控件中添加播放项目时,发现代码无法正常工作,调用CTreeNodeUI控件的Add方法后无反应,导致我的播 ...

  7. 仿酷狗音乐播放器开发日志三——修复CEditUI的bug2

    无意中发现了CEditUI控件的另一个bug,当我给播放器的搜索栏获取焦点时,这时再改变窗体大小,原本搜索栏应该对应着也改变大小,却发现CEditUI内嵌的edit控件没有跟着改变(如下图),跟着调试 ...

  8. Redrain仿酷狗音乐播放器开发完毕,发布测试程序

    转载请说明原出处,谢谢~~ 从暑假到现在中秋刚过,我用duilib开发仿酷狗播放器大概经历了50天.做仿酷狗的意图只是看原酷狗的界面比较漂亮,想做个完整一些的工程来练习一下duilib.今天把写好的程 ...

  9. 项目源码--Android类似酷狗音乐播放器

    下载源码 知识技能概要: 1.音乐文件的扫描与管理 2.音频流的解码 3. UI控件的综合使用 4.播放列表方式管理 5.随机播放方式 6.源码带详细的中文注释 ...... 详细介绍 1. 音乐文件 ...

随机推荐

  1. mysql-5&period;6&period;34 Installation from Source code

    Took me a while to suffer from the first successful souce code installation of mysql-5.6.34. Just pu ...

  2. python 高级之面向对象初级

    python 高级之面向对象初级 本节内容 类的创建 类的构造方法 面向对象之封装 面向对象之继承 面向对象之多态 面向对象之成员 property 1.类的创建 面向对象:对函数进行分类和封装,让开 ...

  3. 十五个常用的jquery代码段

    十五个常用的jquery代码段 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top ...

  4. Qt中sleep&lpar;&rpar;的实现(耳目一新的两种方法)

    在Qt中并没有Sleep函数可以调用,在程序编写时往往需要休眠几秒,这里举出两个方法,不知道是否啥不良隐患没~~ 方法一: class SleeperThread : public QThread{p ...

  5. Delegate&amp&semi;Event

    Delegate 1.基本类: public class Student { public int Id { get; set; } public string Name { get; set; } ...

  6. BZOJ1861&lbrack;ZJOI2006&rsqb;Book书架

    Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...

  7. DevExpress 控件使用之XtraReport

    DevExpress 系列控件,相信大家做WinForm开发已经再熟悉不过了.报表工具对大家来说,选择面很广,.net 本身也提供了非常好的设计工具.下面主要介绍通过DevExpress XtraRe ...

  8. Dockerize PostgreSQL

    Dockerize PostgreSQL Installing PostgreSQL on Docker Assuming there is no Docker image that suits yo ...

  9. 关于Unity中的本地存储

    本地存储 在做游戏的时候,经常需要在本机存储一些数据,比如闯关类游戏要记录闯到第几关,做单机的时候要把数据保存到本地,下次启动的时候数据存在,就是把数据保存到磁盘里面或者手机的flash闪存里面. U ...

  10. python之模块&lowbar;随手记录的模块

    目录 1.StringIO模块 2.string模块 3.pprint模块 4.struct模块 5.uuid模块 6.itertools 7.prettytable 1.StringIO (1)使用 ...