修復duilib庫UISlider控件的4個bug

轉載級請註明原出處,謝謝~· app


        昨天封裝好一個音頻類,我在爲dulib作音頻播放demo時發現了一些問題,由CSliderUI控件致使的,進而發現了這個控件的好幾樣不足,他沒法滿ide

足咱們作一個播放器的進度控件和音量控制控件,詳細問題例如如下:函數

//=====================================================================================================this

         2014.7.28 redrain改動,QQ:491646717,有疑問或者bug2請聯繫我spa

        改動的代碼的DoEvent部分的邏輯借鑑和複製了網友 快樂每一天(羣暱稱 花落半歌,QQ:848861075 )的代碼  .net

        問題說明:我正在製做仿酷狗播放器,作到音樂播放的部分時用到CSliderUI控件,後臺的音頻類回去控制CSliderUI的行爲  CSliderUI的行爲與酷狗的很是不同,有幾樣缺陷:code

        問題1:僅僅能經過點擊CSliderUI的某個位置才幹觸發valuechanged消息,沒法經過滑動滑塊去觸發,這個bug最嚴重
        問題2:點擊CSliderUI的某個位置,當鼠標彈起時滑塊才改變位置,而其它軟件都是鼠標按下時就改變了
        問題3:後臺有代碼一直調用SetValue函數改變滑塊的位置時,會和鼠標土洞滑塊衝突,表現在滑塊會一直來回跳動

        問題4:滑塊滑動過程當中沒法通知主窗口正在改變,這點用在音量改變時,一般咱們是一邊滑動一邊就改變了音量,而不是滑動完畢後再改, 爲blog

咱們加入一個新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把這個消息的定義放到UIDefine.h文件裏事件

        #define DUI_MSGTYPE_VALUECHANGED_MOVE      (_T("movevaluechanged"))ip

        同一時候出於效率考慮,要讓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

相關文章
相關標籤/搜索