修復duilib庫UISlider控件的4個Bug
問題說明:我正在制作仿酷狗播放器,做到音樂播放的部分時用到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_MOUSEMOVE消息處理中把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; } |
至此我們就改動了四處地方,還有其它改動的地方大家能夠自己看源文件,此次改動不會影響控件原有的屬性,我個人水平有限,假設有不論什么問題,能夠聯系我。
posted on 2014-11-14 10:02 順其自然EVO 閱讀(539) 評論(0) 編輯 收藏 所屬分類: 測試學習專欄