qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          修復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)  編輯  收藏 所屬分類: 測試學習專欄

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

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 子洲县| 永春县| 阿鲁科尔沁旗| 桑日县| 美姑县| 建宁县| 阿合奇县| 霍山县| 凯里市| 金阳县| 洛浦县| 合作市| 玉门市| 正宁县| 嵩明县| 聂荣县| 吉隆县| 镇平县| 孙吴县| 大城县| 卢龙县| 开阳县| 英山县| 正定县| 武胜县| 新乡市| 班玛县| 鄄城县| 宁晋县| 衡东县| 尖扎县| 大田县| 沐川县| 富蕴县| 杭锦后旗| 双流县| 隆化县| 无锡市| 长兴县| 南京市| 铁岭县|