修復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:滑塊滑動過程當中沒法通知主窗體正在改變,這點用在音量改變時,一般咱們是一邊滑動一邊就改變了音量,而不是滑動完成後再改, 爲字符串

此咱們添加一個新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把這個消息的定義放到UIDefine.h文件中get

        #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();
	}

	if( !m_bMouseTracking ) {
		TRACKMOUSEEVENT tme = { 0 };
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_HOVER | TME_LEAVE;
		tme.hwndTrack = m_pManager->GetPaintWindow();
		tme.dwHoverTime =400UL;
		_TrackMouseEvent(&tme);
		m_bMouseTracking = true;
	}
	// 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

相關文章
相關標籤/搜索