转载级请注明原出处,谢谢~·

昨天封装好一个音频类,我在为dulib做音频播放demo时发现了一些问题,由CSliderUI控件导致的,进而发现了这个控件的好几样不足,他无法满

足我们做一个播放器的进度控件和音量控制控件,具体问题如下:

//=====================================================================================================

2014.7.28 redrain修改,QQ:491646717,有疑问或者bug2请联系我

修改的代码的DoEvent部分的逻辑借鉴和复制了网友 快樂每一天(群昵称 花落半歌,QQ:848861075 )的代码

问题说明:我正在制作仿酷狗播放器,做到音乐播放的部分时用到CSliderUI控件,后台的音频类回去控制CSliderUI的行为  CSliderUI的行为与酷狗的很不一样,有几样缺陷:

问题1:只能通过点击CSliderUI的某个位置才能触发valuechanged消息,无法通过滑动滑块去触发,这个bug最严重
        问题2:点击CSliderUI的某个位置,当鼠标弹起时滑块才改变位置,而其他软件都是鼠标按下时就改变了
        问题3:后台有代码一直调用SetValue函数改变滑块的位置时,会和鼠标土洞滑块冲突,表现在滑块会一直来回跳动

问题4:滑块滑动过程中无法通知主窗体正在改变,这点用在音量改变时,通常我们是一边滑动一边就改变了音量,而不是滑动完成后再改, 为

此我们添加一个新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把这个消息的定义放到UIDefine.h文件中

#define DUI_MSGTYPE_VALUECHANGED_MOVE      (_T("movevaluechanged"))

同时出于效率考虑,要让CSliderUI发出这个消息,应该设置属性sendmove为真,默认为假

我修改的代码可以通过搜索字符串“2014.7.28 redrain”,来查找,方便大家查看源码

此次修改不会影响控件原有的属性,我个人水平有限,如果有任何问题,可以联系我

//=====================================================================================================

问题的描述结束了,其中的大部分问题都是由于在DoEvent函数中对一些逻辑的判断的不足导致的。

问题1的解决:只能通过点击CSliderUI的某个位置才能触发valuechanged消息,无法通过滑动滑块去触发这是由于原来的UIEVENT_BUTTONUP

消息处理不当造成的,原代码为:

if( event.Type == UIEVENT_BUTTONUP )
{int nValue;if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {m_uButtonState &= ~UISTATE_CAPTURED;}if( m_bHorizontal ) {if( event.ptMouse.x >= m_rcItem.right - m_szThumb.cx / 2 ) nValue = m_nMax;else if( event.ptMouse.x <= m_rcItem.left + m_szThumb.cx / 2 ) nValue = m_nMin;else nValue = m_nMin + (m_nMax - m_nMin) * (event.ptMouse.x - m_rcItem.left - m_szThumb.cx / 2 ) / (m_rcItem.right - m_rcItem.left - m_szThumb.cx);}else {if( event.ptMouse.y >= m_rcItem.bottom - m_szThumb.cy / 2 ) nValue = m_nMin;else if( event.ptMouse.y <= m_rcItem.top + m_szThumb.cy / 2  ) nValue = m_nMax;else nValue = m_nMin + (m_nMax - m_nMin) * (m_rcItem.bottom - event.ptMouse.y - m_szThumb.cy / 2 ) / (m_rcItem.bottom - m_rcItem.top - m_szThumb.cy);}if(m_nValue !=nValue && nValue>=m_nMin && nValue<=m_nMax){m_nValue =nValue;m_pManager->SendNotify(this, DUI_MSGTYPE_VALUECHANGED);Invalidate();}return;
}

在最后的判断出可以看到,只有当m_nValue !=nValue时才会发送DUI_MSGTYPE_VALUECHANGED消息,而我们滑动滑块时,通过上面的代码

不难分析出,

这两个值一直是相等的,所以导致他没有发出消息,所以我们把这个判断注释掉就行了

问题2的解决:

点击CSliderUI的某个位置,当鼠标弹起时滑块才改变位置,而其他软件都是鼠标按下时就改变了,这是由于原来的UIEVENT_BUTTONDOWN 消

息的处理不全面造成的,原代码为:

if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK ){if( IsEnabled() ) {RECT rcThumb = GetThumbRect();if( ::PtInRect(&rcThumb, event.ptMouse) ) {m_uButtonState |= UISTATE_CAPTURED;}}return;}

可以看到原代码没有做对于控件的外观的任何修改,我们把代码修改如下:

if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK )
{if( IsEnabled() ) {//2014.7.28 redrain 注释掉原来的代码,加上这些代码后可以让Slider不是在鼠标弹起时才改变滑块的位置m_uButtonState |= UISTATE_CAPTURED;int nValue;if( m_bHorizontal ) {if( event.ptMouse.x >= m_rcItem.right - m_szThumb.cx / 2 ) nValue = m_nMax;else if( event.ptMouse.x <= m_rcItem.left + m_szThumb.cx / 2 ) nValue = m_nMin;else nValue = m_nMin + (m_nMax - m_nMin) * (event.ptMouse.x - m_rcItem.left - m_szThumb.cx / 2 ) / (m_rcItem.right - m_rcItem.left - m_szThumb.cx);}else {if( event.ptMouse.y >= m_rcItem.bottom - m_szThumb.cy / 2 ) nValue = m_nMin;else if( event.ptMouse.y <= m_rcItem.top + m_szThumb.cy / 2  ) nValue = m_nMax;else nValue = m_nMin + (m_nMax - m_nMin) * (m_rcItem.bottom - event.ptMouse.y - m_szThumb.cy / 2 ) / (m_rcItem.bottom - m_rcItem.top - m_szThumb.cy);}if(m_nValue !=nValue && nValue>=m_nMin && nValue<=m_nMax){m_nValue =nValue;Invalidate();}}return;
}

问题3的解决:

后台有代码一直调用SetValue函数改变滑块的位置时,会和鼠标土洞滑块冲突,表现在滑块会一直来回跳动,这是因为,当我们拖动滑块时会动

态的修改Slider的m_nValue值,并且会刷新控件,而通过读PaintStatusImage函数可知,控件正式通过这个m_nValue变量来决定滑块的绘制位置。而

我在后台让音乐播放类去根据音乐的进度调用SetValue函数,这个函数理所当然的修改了m_nValue值,这就导致了冲突,这个函数是父类的,所以我

们要重写这个函数。当鼠标正在滑动式不让SetValue去改变控件的滑块的位置。

增加SetValue函数然后重写他,修改的代码为:

void CSliderUI::SetValue(int nValue)
{if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) return;CProgressUI::SetValue(nValue);
}

问题4的解决:

滑块滑动过程中无法通知主窗体正在改变,这点用在音量改变时,通常我们是一边滑动一边就改变了音量,而不是滑动完成后再改变, 为此我们

添加一个新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把这个消息的定义放到UIDefine.h文件中,这个代码只要在DoEvent的UIEVENT_MOUS

EMOVE消息处理中把DUI_MSGTYPE_VALUECHANGED_MOVE事件传送出去就好了,后来听从网友“不乖打Pp.”的建议,增加了一个属性"sendmove"

,当属行为真时才发送消息出去。

修改代码为:

if( event.Type == UIEVENT_MOUSEMOVE )
{if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {if( m_bHorizontal ) {if( event.ptMouse.x >= m_rcItem.right - m_szThumb.cx / 2 ) m_nValue = m_nMax;else if( event.ptMouse.x <= m_rcItem.left + m_szThumb.cx / 2 ) m_nValue = m_nMin;else m_nValue = m_nMin + (m_nMax - m_nMin) * (event.ptMouse.x - m_rcItem.left - m_szThumb.cx / 2 ) / (m_rcItem.right - m_rcItem.left - m_szThumb.cx);}else {if( event.ptMouse.y >= m_rcItem.bottom - m_szThumb.cy / 2 ) m_nValue = m_nMin;else if( event.ptMouse.y <= m_rcItem.top + m_szThumb.cy / 2  ) m_nValue = m_nMax;else m_nValue = m_nMin + (m_nMax - m_nMin) * (m_rcItem.bottom - event.ptMouse.y - m_szThumb.cy / 2 ) / (m_rcItem.bottom - m_rcItem.top - m_szThumb.cy);}if (m_bSendMove)m_pManager->SendNotify(this, DUI_MSGTYPE_VALUECHANGED_MOVE);Invalidate();}// Generate the appropriate mouse messagesPOINT pt = event.ptMouse;RECT rcThumb = GetThumbRect();if( IsEnabled() && ::PtInRect(&rcThumb, event.ptMouse) ) {m_uButtonState |= UISTATE_HOT;Invalidate();}else{m_uButtonState &= ~UISTATE_HOT;Invalidate();}return;
}

至此我们就修改了四处地方,还有其他修改的地方大家可以自己看源文件,此次修改不会影响控件原有的属性,我个人水平有限,如果有任何问

题,可以联系我。

patch的下载地址:http://download.csdn.net/detail/zhuhongshu/7686617

        2014.7.28  13:14  Redrain

修复duilib库UISlider控件的4个bug相关推荐

  1. 改进duilib的richedit控件的部分功能

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 如果要使用透明异形窗体功能,首先要改进duilib库让他本 ...

  2. Duilib教程-控件练习

    一.控件消息的响应. 在HelloDuilib例子中,程序不能退出,在这里,我将添加一个关闭按钮,当点击它时,调用PostQuitMessage进行退出. 首先在界面的右上角添加一个关闭按钮,并取名为 ...

  3. Android开源库集合(控件)

    RecycleView: RecycleView功能增强 https://github.com/Malinskiy/SuperRecyclerView RecycleView功能增强(拖拽,滑动删除, ...

  4. 物联网HMI的关键驱动力—SCADA级功能库和控件库

    一.前言 在这个数字化时代,物联网HMI已成为连接人与设备之间的关键纽带,为用户提供直观.智能的交互体验,背后强大的关键驱动力扮演着至关重要的角色,其中SCADA级功能库和控件库的引入成为了物联网HM ...

  5. duilib 关于wke 控件焦点问题

    转载请说明原出处,谢谢~~ 对象 : 使用着 Redrain 的 uilib , 下载地址: <Redrain个人维护并使用的DuiLib和UiLib库源码下载地址> 问题描述: wke ...

  6. DuiLib的Combo控件点击无响应的问题

    注:此问题具有特殊性,不具有普适性.结果虽然让人很崩溃,但毕竟折磨了自己一个下午的时间,记录下来永记于此. 今天的DuiLib开发过程中遇到了一个Combo点击没有反应,无法弹出下拉菜单的问题.此问题 ...

  7. 1cocos2dx扩展库UI控件,CCControlSlider,CCScale9Sprite(九妹图),CCControlSwitch,CCControlButton

     UI控件来自cocos2dx的扩展库,完善了UI方面的元素,使cocos2dx更加丰富多彩.使用扩展库需包含: #include "cocos-ext.h" USING_NS ...

  8. python tkinter库Entry控件Text控件

    Entry控件是用来输入文本的(单行输入控件) Entry类构造方法的show关键字参数指定录入文本是回显某个字符 Text控件是用来输入文本的(多行文本,图像,富文本等) 下面实例有Entry控件 ...

  9. 组件,库,控件,插件 集合(jQuery/绘图/富文本/PDF/Excel/国际化/Three.js/JSZip/JSEncrypt/Axios/其他)

    组件(库)的概念 包含 控件(UI组件).插件(基物上的组件) jQuery 位置与尺寸 $(window).scrollTop()   //鼠标滚动高度 $(window).height()     ...

最新文章

  1. mysql 加快复制进程_MySQL并发复制进程演进
  2. mysql select a b_MySQL-mysql中,select a,b 与 select *效率到底差多少?
  3. 你连原理都还没弄明白?机甲风暴java破解版下载
  4. 东欧视频游戏市场概况
  5. C++_类和对象_封装_成员属性私有化---C++语言工作笔记038
  6. Struts初学者教程
  7. 对 SharePoint WebService 的调用
  8. java 内部类_Java内部类总结
  9. Eclipse快捷键 10个最有用的快捷键
  10. 计算机专硕都是数二英二吗,【专硕初试】大改革?英二、数二都不考了?
  11. HBuilderX 最新安装使用教程,附详细图解,持续更新
  12. 迪米特法则(最少知道原则)
  13. 论文阅读:HAD-Net: A Hierarchical Adversarial Knowledge Distillation Network for Improved Enhanced Tumour
  14. Linux中 ifconfig命令只有lo没有eth0/ens33
  15. Zoom Cloud Mettings - Zoom 云视频会议
  16. 【智慧地球】图新地球 | 如何将图新地球多要素KML进行分离输出
  17. 看优酷 Node 重构之路,Serverless SSR 未来可期
  18. netlink怎么读_在VB中访问NETLINK并读写S7300 PLC数据
  19. 西门子S7-300PLC ModbusTCP通讯方法
  20. 【半监督医学图像分割 2022 CVPR】S4CVnet 论文翻译

热门文章

  1. 《弃子长安》第九章 大漠金钩
  2. [GYCTF2020]Blacklist
  3. mapboxGL中sprite生成与引用
  4. 通用设计法则:80/20法则
  5. python计算派的值_使用 Python 计算 π 值
  6. android 点击按钮来回切换图片
  7. anaconda常用命令
  8. mysql宕机恢复_mysql突然宕机后事务如何处理?
  9. hihoCoder 买零食
  10. 王某与石某的分歧卡卡罗特