修復(fù)duilib庫UISlider控件的4個Bug
問題說明:我正在制作仿酷狗播放器,做到音樂播放的部分時用到CSliderUI控件,后臺的音頻類回去控制CSliderUI的行為 CSliderUI的行為與酷狗的非常不一樣,有幾樣缺陷:
問題1:僅僅能通過點(diǎn)擊CSliderUI的某個位置才干觸發(fā)valuechanged消息,無法通過滑動滑塊去觸發(fā),這個bug最嚴(yán)重
問題2:點(diǎn)擊CSliderUI的某個位置,當(dāng)鼠標(biāo)彈起時滑塊才改變位置,而其它軟件都是鼠標(biāo)按下時就改變了
問題3:后臺有代碼一直調(diào)用SetValue函數(shù)改變滑塊的位置時,會和鼠標(biāo)土洞滑塊沖突,表如今滑塊會一直來回跳動
問題4:滑塊滑動過程中無法通知主窗口正在改變,這點(diǎn)用在音量改變時,通常我們是一邊滑動一邊就改變了音量,而不是滑動完畢后再改, 為
此我們加入一個新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把這個消息的定義放到UIDefine.h文件里
#define DUI_MSGTYPE_VALUECHANGED_MOVE (_T("movevaluechanged"))
同一時候出于效率考慮,要讓CSliderUI發(fā)出這個消息,應(yīng)該設(shè)置屬性sendmove為真,默覺得假
我改動的代碼能夠通過搜索字符串“2014.7.28 redrain”,來查找,方便大家查看源代碼
此次改動不會影響控件原有的屬性,我個人水平有限,假設(shè)有不論什么問題,能夠聯(lián)系我
//=====================================================================================================
問題的描寫敘述結(jié)束了,當(dāng)中的大部分問題都是因?yàn)樵贒oEvent函數(shù)中對一些邏輯的推斷的不足導(dǎo)致的。
問題1的解決:僅僅能通過點(diǎn)擊CSliderUI的某個位置才干觸發(fā)valuechanged消息,無法通過滑動滑塊去觸發(fā)這是因?yàn)樵瓉淼腢IEVENT_BUTTONUP
消息處理不當(dāng)造成的,原代碼為:
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; } |
在最后的推斷出能夠看到,僅僅有當(dāng)m_nValue !=nValue時才會發(fā)送DUI_MSGTYPE_VALUECHANGED消息,而我們滑動滑塊時,通過上面的代碼不難分析出,這兩個值一直是相等的,所以導(dǎo)致他沒有發(fā)出消息,所以我們把這個推斷凝視掉即可了
問題2的解決:
點(diǎn)擊CSliderUI的某個位置,當(dāng)鼠標(biāo)彈起時滑塊才改變位置,而其它軟件都是鼠標(biāo)按下時就改變了,這是因?yàn)樵瓉淼腢IEVENT_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不是在鼠標(biāo)彈起時才改變滑塊的位置 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的解決:
后臺有代碼一直調(diào)用SetValue函數(shù)改變滑塊的位置時,會和鼠標(biāo)土洞滑塊沖突,表如今滑塊會一直來回跳動,這是由于,當(dāng)我們拖動滑塊時會動態(tài)的改動Slider的m_nValue值,而且會刷新控件,而通過讀PaintStatusImage函數(shù)可知,控件正式通過這個m_nValue變量來決定滑塊的繪制位置。而我在后臺讓音樂播放類去依據(jù)音樂的進(jìn)度調(diào)用SetValue函數(shù),這個函數(shù)理所當(dāng)然的改動了m_nValue值,這就導(dǎo)致了沖突,這個函數(shù)是父類的,所以我們要重寫這個函數(shù)。當(dāng)鼠標(biāo)正在滑動式不讓SetValue去改變控件的滑塊的位置。
添加SetValue函數(shù)然后重寫他,改動的代碼為:
void CSliderUI::SetValue(int nValue)
{
if( (m_uButtonState & UISTATE_CAPTURED) != 0 )
return;
CProgressUI::SetValue(nValue);
}
問題4的解決:
滑塊滑動過程中無法通知主窗口正在改變,這點(diǎn)用在音量改變時,通常我們是一邊滑動一邊就改變了音量,而不是滑動完畢后再改變, 為此我們加入一個新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把這個消息的定義放到UIDefine.h文件里,這個代碼僅僅要在DoEvent的UIEVENT_MOUSEMOVE消息處理中把DUI_MSGTYPE_VALUECHANGED_MOVE事件傳送出去就好了,后來聽從網(wǎng)友“不乖打Pp.”的建議,添加了一個屬性"sendmove",當(dāng)屬行為真時才發(fā)送消息出去。
改動代碼為:
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; } |
至此我們就改動了四處地方,還有其它改動的地方大家能夠自己看源文件,此次改動不會影響控件原有的屬性,我個人水平有限,假設(shè)有不論什么問題,能夠聯(lián)系我。
posted on 2014-11-14 10:02 順其自然EVO 閱讀(539) 評論(0) 編輯 收藏 所屬分類: 測試學(xué)習(xí)專欄