zoukankan      html  css  js  c++  java
  • 修复duilib库UISlider控件的4个bug

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


            昨天封装好一个音频类,我在为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 messages
    	POINT 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

  • 相关阅读:
    CodeSmith 破解
    overflow 及其属性
    Override any CSS style (even inline styles) no matter where it is defined
    CSS驱动的下拉菜单
    对zindex的重新学习
    Eeic Meyer on CSS 之 文字排列成曲线
    Eeic Meyer on CSS 之 背景半透明效果
    background背景窍门
    CSS实现网页图片预加载
    meta 标签举例
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3944896.html
Copyright © 2011-2022 走看看