qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          修復(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í)專欄

          <2014年11月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 博罗县| 昭苏县| 彝良县| 民县| 张北县| 将乐县| 定边县| 依安县| 玛纳斯县| 旌德县| 澄江县| 西青区| 闻喜县| 池州市| 花莲县| 赤城县| 甘孜县| 靖州| 班玛县| 孟连| 南漳县| 保靖县| 洮南市| 英超| 长乐市| 佛坪县| 克拉玛依市| 南皮县| 阿克陶县| 祁门县| 丽江市| 曲阳县| 衡南县| 九台市| 遵义县| 拜城县| 逊克县| 昌图县| 阿拉善右旗| 保亭| 合作市|