轉載級請註明原出處,謝謝~· 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最嚴重問題4:滑塊滑動過程當中沒法通知主窗口正在改變,這點用在音量改變時,一般咱們是一邊滑動一邊就改變了音量,而不是滑動完畢後再改, 爲blog
此咱們加入一個新的消息DUI_MSGTYPE_VALUECHANGED_MOVE,把這個消息的定義放到UIDefine.h文件裏事件
#define DUI_MSGTYPE_VALUECHANGED_MOVE (_T("movevaluechanged"))ip
同一時候出於效率考慮,要讓CSliderUI發出這個消息,應該設置屬性sendmove爲真,默以爲假這次改動不會影響控件原有的屬性,我我的水平有限,假設有不論什麼問題,可以聯繫我
//=====================================================================================================
問題的描寫敘述結束了,當中的大部分問題都是由於在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; }
後臺有代碼一直調用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