zoukankan      html  css  js  c++  java
  • Duilib动画按钮实现(转载)

    转载:http://blog.csdn.net/cuiguanghui123/article/details/51674218 

    .h文件

     1 #ifndef __UIBUTTONEX_H__
     2 #define __UIBUTTONEX_H__
     3 
     4 #pragma once
     5 
     6 #define EVENT_ANIMA_ENTER_TIMERID    UIMSG_USER+100         //鼠标进入按钮TimerID
     7 #define EVENT_ANIMA_LEAVE_TIMERID    UIMSG_USER+101         //鼠标离开按钮TimerID
     8 class  CButtonUIEx : public CButtonUI
     9 {
    10     DECLARE_DUICONTROL(CButtonUIEx)
    11 public:
    12     enum ChannelARGB {
    13         Blue = 0, Green = 1, Red = 2, Alpha = 3
    14     };
    15 
    16     CButtonUIEx();
    17     virtual ~CButtonUIEx();
    18 
    19     virtual void SetMaskImage(LPCTSTR pStrImage);
    20     virtual LPCTSTR GetMaskImage();
    21 
    22     virtual LPCTSTR GetPushedForeImage();
    23     virtual void SetPushedForeImage(LPCTSTR pStrImage);
    24 
    25     virtual RECT GetPushedTextPadding();
    26     virtual void SetPushedTextPadding(RECT rc);
    27 
    28     void SetAnimationImages(vector<DuiLib::CDuiString>);
    29 
    30     virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
    31 
    32     virtual void DoPaint(HDC hDC, const RECT& rcPaint);
    33     virtual void PaintBkImage(HDC hDC);
    34     void PaintStatusImage(HDC hDC);
    35 
    36     virtual bool TransferOneARGBChannelFromOneBitmapToAnother(IN Gdiplus::Bitmap &src,
    37         OUT Gdiplus::Bitmap &dst,
    38         ChannelARGB srcChannel,
    39         ChannelARGB dstChannel);
    40 
    41     //-------------添加---------
    42     void    OnTimer(UINT_PTR idEvent);
    43     void    DoEvent(TEventUI& event) override;
    44     void    DrawFrame(HDC hDC);        // 绘制GIF每帧
    45     void    OnLeaveTimer(UINT_PTR idEvent);
    46     void    DrawLeaveFrame(HDC hDC);        // 绘制GIF每帧
    47 
    48     void PaintText(HDC hDC);
    49 
    50 private:
    51     bool _ResizeClone(Gdiplus::Image *&image, INT width, INT height);
    52 
    53 protected:
    54     DuiLib::CDuiString m_sBkImageEx;
    55     DuiLib::CDuiString m_sMaskImage;
    56 
    57     Gdiplus::Image *m_pMaskImage;
    58     Gdiplus::Bitmap *m_pBmpFluffy;
    59     Gdiplus::Bitmap *m_pBmpMask;
    60 
    61 
    62     CDuiString m_sPushedForeImage;
    63     vector<DuiLib::CDuiString> vecAnimation;
    64     UINT            m_nFrameCount;                // 图片总帧数
    65     UINT            m_nFramePosition;            // 当前放到第几帧
    66     UINT            m_nTimerSize;                // 帧与帧之间间隔时间
    67     BOOL            m_bLeaveFlag;
    68     BOOL            m_bNormalFlag;
    69     RECT            m_rcPushedTextPadding;
    70 };
    71 
    72 
    73 #endif //__UIBUTTONEX_H__

     .cpp文件

      1 #include "stdafx.h"
      2 #include "UIButtonEx.h"
      3 
      4 #ifndef SAFE_DELETE
      5 #define SAFE_DELETE(p) { if (p) { delete (p); (p) = 0; } }
      6 #endif // SAFE_DELETE
      7 
      8 IMPLEMENT_DUICONTROL(CButtonUIEx)
      9 /////////////////////////////////////////////////////////////////////////////////////
     10 //
     11 //
     12 
     13 CButtonUIEx::CButtonUIEx()
     14     : CButtonUI()
     15     , m_pMaskImage(NULL)
     16     , m_pBmpFluffy(NULL)
     17     , m_pBmpMask(NULL)
     18 {
     19     m_nFramePosition = 0;
     20     m_nFrameCount = 0;
     21     m_nTimerSize = 60;
     22     m_bLeaveFlag = false;
     23     m_bNormalFlag = true;
     24     ::ZeroMemory(&m_rcPushedTextPadding, sizeof(m_rcPushedTextPadding));
     25 }
     26 
     27 CButtonUIEx::~CButtonUIEx()
     28 {
     29     SAFE_DELETE(m_pMaskImage);
     30     SAFE_DELETE(m_pBmpFluffy);
     31     SAFE_DELETE(m_pBmpMask);
     32 }
     33 
     34 void CButtonUIEx::SetMaskImage(LPCTSTR pStrImage)
     35 {
     36     m_sMaskImage = pStrImage;
     37     Invalidate();
     38 }
     39     
     40 LPCTSTR CButtonUIEx::GetMaskImage()
     41 {
     42     return m_sMaskImage;
     43 }
     44 
     45 LPCTSTR CButtonUIEx::GetPushedForeImage()
     46 {
     47     return m_sPushedForeImage;
     48 }
     49 
     50 void CButtonUIEx::SetPushedForeImage(LPCTSTR pStrImage)
     51 {
     52     m_sPushedForeImage = pStrImage;
     53     Invalidate();
     54 }
     55 
     56 void CButtonUIEx::SetAnimationImages(vector<DuiLib::CDuiString> vecList)
     57 {
     58     vecAnimation = vecList;
     59     m_nFrameCount = vecList.size();
     60 }
     61 
     62 RECT CButtonUIEx::GetPushedTextPadding()
     63 {
     64     return m_rcPushedTextPadding;
     65 }
     66 
     67 void CButtonUIEx::SetPushedTextPadding(RECT rc)
     68 {
     69     m_rcPushedTextPadding = rc;
     70     Invalidate();
     71 }
     72 
     73 void CButtonUIEx::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
     74 {
     75     if (_tcscmp(pstrName, _T("maskimage")) == 0) SetMaskImage(pstrValue);
     76     else if (_tcsicmp(pstrName, _T("pushedforeimage")) == 0) SetPushedForeImage(pstrValue);
     77     else if (_tcsicmp(pstrName, _T("pushedtextpadding")) == 0) {
     78         RECT rcTextPadding = { 0 };
     79         LPTSTR pstr = NULL;
     80         rcTextPadding.left = _tcstol(pstrValue, &pstr, 10);  ASSERT(pstr);
     81         rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10);    ASSERT(pstr);
     82         rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10);  ASSERT(pstr);
     83         rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
     84         SetPushedTextPadding(rcTextPadding);
     85     }
     86     else CButtonUI::SetAttribute(pstrName, pstrValue);
     87 }
     88 
     89 void CButtonUIEx::DoPaint(HDC hDC, const RECT& rcPaint)
     90 {
     91     if (!::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem)) return;
     92 
     93     // RESERVED: add your code here.
     94     if (m_bNormalFlag && vecAnimation.size() > 0)
     95         DrawImage(hDC, (LPCTSTR)vecAnimation[0]);
     96 
     97     if ((m_uButtonState & UISTATE_HOT) != 0)
     98     {
     99         DrawFrame(hDC);
    100         m_bNormalFlag = false;
    101     }
    102     if(m_bLeaveFlag)
    103         DrawLeaveFrame(hDC);
    104     __super::DoPaint(hDC, rcPaint);
    105 }
    106 
    107 void CButtonUIEx::PaintBkImage(HDC hDC)
    108 {
    109     if (m_sMaskImage && m_sBkImageEx != m_sBkImage) {
    110         do {
    111             m_sBkImageEx = m_sBkImage;
    112 
    113             SAFE_DELETE(m_pBmpFluffy);
    114             m_pBmpFluffy = new Gdiplus::Bitmap(m_pManager->GetResourcePath() + m_sBkImageEx);
    115             if (!m_pBmpFluffy || m_pBmpFluffy->GetLastStatus() != Gdiplus::Status::Ok) {
    116                 // TODO: check if m_sBkImageEx contains an absolute path.
    117                 m_pBmpFluffy = new Gdiplus::Bitmap(m_sBkImageEx);
    118                 if (!m_pBmpFluffy || m_pBmpFluffy->GetLastStatus() != Gdiplus::Status::Ok) {
    119                     break;
    120                 }
    121             }
    122 
    123             if (m_sMaskImage.IsEmpty()) {
    124                 break;
    125             }
    126 
    127             SAFE_DELETE(m_pMaskImage);
    128             m_pMaskImage = Gdiplus::Image::FromFile(m_pManager->GetResourcePath() + m_sMaskImage);
    129             if (!m_pMaskImage || m_pMaskImage->GetLastStatus() != Gdiplus::Status::Ok) {
    130                 break;
    131             }
    132 
    133             if (!_ResizeClone(m_pMaskImage, m_pBmpFluffy->GetWidth(), m_pBmpFluffy->GetHeight())) {
    134                 break;
    135             }
    136 
    137             Gdiplus::Rect rectFluffy(0, 0, m_pBmpFluffy->GetWidth(), m_pBmpFluffy->GetHeight());
    138 
    139             SAFE_DELETE(m_pBmpMask);
    140             m_pBmpMask = new Gdiplus::Bitmap(rectFluffy.Width, rectFluffy.Height);
    141             if (!m_pBmpMask) {
    142                 break;
    143             }
    144 
    145             Gdiplus::Graphics graphics(m_pBmpMask);
    146             graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
    147             graphics.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
    148             graphics.DrawImage(m_pMaskImage, rectFluffy);
    149 
    150             TransferOneARGBChannelFromOneBitmapToAnother(*m_pBmpMask, *m_pBmpFluffy, ChannelARGB::Blue, ChannelARGB::Alpha);
    151             SAFE_DELETE(m_pBmpMask);
    152         } while (0);
    153     }
    154 
    155     if (m_pBmpFluffy) {
    156         Gdiplus::Rect rectDst(m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
    157         Gdiplus::Rect rectSrc((m_rcPaint.left - m_rcItem.left) * m_pBmpFluffy->GetWidth() / (m_rcItem.right - m_rcItem.left),
    158                                 (m_rcPaint.top - m_rcItem.top) * m_pBmpFluffy->GetHeight() / (m_rcItem.bottom - m_rcItem.top),
    159                                 (m_rcPaint.right - m_rcPaint.left) * m_pBmpFluffy->GetWidth() / (m_rcItem.right - m_rcItem.left),
    160                                 (m_rcPaint.bottom - m_rcPaint.top) * m_pBmpFluffy->GetHeight() / (m_rcItem.bottom - m_rcItem.top));
    161 
    162         Gdiplus::Graphics g(hDC);
    163         g.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
    164         g.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
    165         g.DrawImage(m_pBmpFluffy, rectDst, rectSrc.X, rectSrc.Y, rectSrc.Width, rectSrc.Height, Gdiplus::Unit::UnitPixel);
    166     }
    167 }
    168 
    169 bool CButtonUIEx::TransferOneARGBChannelFromOneBitmapToAnother(IN Gdiplus::Bitmap &src,
    170                                                                         OUT Gdiplus::Bitmap &dst,
    171                                                                         ChannelARGB srcChannel,
    172                                                                         ChannelARGB dstChannel)
    173 {
    174     if (src.GetWidth() != dst.GetWidth() || src.GetHeight() != dst.GetHeight())
    175         return false;
    176 
    177     Gdiplus::Rect rectSrc(0, 0, src.GetWidth(), src.GetHeight());
    178     Gdiplus::BitmapData bdSrc, bdDst;
    179     src.LockBits(&rectSrc, Gdiplus::ImageLockMode::ImageLockModeRead, PixelFormat32bppPARGB, &bdSrc);
    180     dst.LockBits(&rectSrc, Gdiplus::ImageLockMode::ImageLockModeWrite, PixelFormat32bppPARGB, &bdDst);
    181 
    182     // unsafe codes that protected by LockBits
    183     byte *bpSrc = (byte *)bdSrc.Scan0;
    184     byte *bpDst = (byte *)bdDst.Scan0;
    185 
    186     bpSrc += (int)srcChannel;
    187     bpDst += (int)dstChannel;
    188     for (int i = rectSrc.Height * rectSrc.Width; i > 0; i--) {
    189         *bpDst = *bpSrc;
    190         bpSrc += 4;
    191         bpDst += 4;
    192     }
    193     // end (unsafe codes)
    194 
    195     src.UnlockBits(&bdSrc);
    196     dst.UnlockBits(&bdDst);
    197     return true;
    198 }
    199 
    200 bool CButtonUIEx::_ResizeClone(Gdiplus::Image *&image, INT width, INT height)
    201 {
    202     UINT image_width = image->GetWidth();
    203     UINT image_height = image->GetHeight();
    204     INT width_ = width;
    205     INT height_ = height;
    206         
    207     if (image_width == width_ && image_height == height_)
    208         return true;
    209 
    210     double ratio = ((double)image_width) / image_height;
    211     if (image_width > image_height) { // Resize down by width
    212         height_ = static_cast<UINT>(((double)width_) / ratio);
    213     }
    214     else {
    215         width_ = static_cast<UINT>(((double)height_) / ratio);
    216     }
    217 
    218     Gdiplus::Image *dst = new Gdiplus::Bitmap(width_, height_, image->GetPixelFormat());
    219     if (dst && dst->GetLastStatus() == Gdiplus::Status::Ok) {
    220         Gdiplus::Graphics graphics(dst);
    221         graphics.DrawImage(image, 0, 0, width_, height_);
    222 
    223         SAFE_DELETE(image);
    224         image = dst;
    225         return true;
    226     }
    227         
    228     SAFE_DELETE(dst);
    229     return false;
    230 }
    231 
    232 void CButtonUIEx::PaintStatusImage(HDC hDC)
    233 {
    234     if (IsFocused()) m_uButtonState |= UISTATE_FOCUSED;
    235     else m_uButtonState &= ~UISTATE_FOCUSED;
    236     if (!IsEnabled()) m_uButtonState |= UISTATE_DISABLED;
    237     else m_uButtonState &= ~UISTATE_DISABLED;
    238 
    239     if (!::IsWindowEnabled(m_pManager->GetPaintWindow())) {
    240         m_uButtonState &= UISTATE_DISABLED;
    241     }
    242     if ((m_uButtonState & UISTATE_DISABLED) != 0) {
    243         if (!m_sDisabledImage.IsEmpty())
    244         {
    245             if (!DrawImage(hDC, (LPCTSTR)m_sDisabledImage)) m_sDisabledImage.Empty();
    246             else goto Label_ForeImage;
    247         }
    248     }
    249     else if ((m_uButtonState & UISTATE_PUSHED) != 0) {
    250         if (!m_sPushedImage.IsEmpty()) {
    251             if (!DrawImage(hDC, (LPCTSTR)m_sPushedImage)){
    252                 m_sPushedImage.Empty();
    253             }
    254             if (!m_sPushedForeImage.IsEmpty())
    255             {
    256                 if (!DrawImage(hDC, (LPCTSTR)m_sPushedForeImage))
    257                     m_sPushedForeImage.Empty();
    258                 return;
    259             }
    260             else goto Label_ForeImage;
    261         }
    262         else if (m_dwPushedBkColor != 0) {
    263             CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwPushedBkColor));
    264             return;
    265         }
    266     }
    267     else if ((m_uButtonState & UISTATE_HOT) != 0) {
    268         if (!m_sHotImage.IsEmpty()) 
    269         {
    270             if (!DrawImage(hDC, (LPCTSTR)m_sHotImage))
    271             {
    272                 m_sHotImage.Empty();
    273             }
    274             if (!m_sHotForeImage.IsEmpty()) 
    275             {
    276                 if (!DrawImage(hDC, (LPCTSTR)m_sHotForeImage))
    277                     m_sHotForeImage.Empty();
    278                 return;
    279             }
    280             else goto Label_ForeImage;
    281         }
    282         else if (m_nFrameCount != 0)
    283         {
    284             m_pManager->SetTimer(this, EVENT_ANIMA_ENTER_TIMERID, m_nTimerSize);
    285         }
    286         else if (m_dwHotBkColor != 0) {
    287             CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwHotBkColor));
    288             return;
    289         }
    290     }
    291     else if ((m_uButtonState & UISTATE_FOCUSED) != 0) {
    292 if (!m_sFocusedImage.IsEmpty()) {
    293     if (!DrawImage(hDC, (LPCTSTR)m_sFocusedImage)) m_sFocusedImage.Empty();
    294     else goto Label_ForeImage;
    295 }
    296     }
    297 
    298     if (!m_sNormalImage.IsEmpty()) {
    299         if (!DrawImage(hDC, (LPCTSTR)m_sNormalImage)) m_sNormalImage.Empty();
    300         else goto Label_ForeImage;
    301     }
    302 
    303     if (!m_sForeImage.IsEmpty())
    304         goto Label_ForeImage;
    305 
    306     return;
    307 
    308 Label_ForeImage:
    309     if (!m_sForeImage.IsEmpty()) {
    310         if (!DrawImage(hDC, (LPCTSTR)m_sForeImage)) m_sForeImage.Empty();
    311     }
    312 }
    313 
    314 void CButtonUIEx::DoEvent(TEventUI& event)
    315 {
    316     CButtonUI::DoEvent(event);
    317     if (event.Type == UIEVENT_MOUSELEAVE)
    318     {
    319         if (IsEnabled()) {
    320             m_uButtonState &= ~UISTATE_HOT;
    321             Invalidate();
    322             if (m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID))
    323             {
    324                 m_bLeaveFlag = true;
    325                 m_pManager->SetTimer(this, EVENT_ANIMA_LEAVE_TIMERID, m_nTimerSize);
    326             }
    327         }
    328     }
    329     if (event.Type == UIEVENT_TIMER)
    330     {
    331         if ((UINT_PTR)event.wParam == EVENT_ANIMA_ENTER_TIMERID)
    332             OnTimer((UINT_PTR)event.wParam);
    333         else if ((UINT_PTR)event.wParam == EVENT_ANIMA_LEAVE_TIMERID)
    334             OnLeaveTimer((UINT_PTR)event.wParam);
    335     }
    336 }
    337 
    338 void CButtonUIEx::OnTimer(UINT_PTR idEvent)
    339 {
    340     if (idEvent != EVENT_ANIMA_ENTER_TIMERID)
    341         return;
    342     m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
    343     this->Invalidate();
    344 
    345     m_nFramePosition++;
    346 
    347     m_pManager->SetTimer(this, EVENT_ANIMA_ENTER_TIMERID, m_nTimerSize);
    348 }
    349 
    350 void CButtonUIEx::DrawFrame(HDC hDC)
    351 {
    352     if (NULL == hDC || vecAnimation.size() == 0 || m_nFramePosition >= m_nFrameCount)
    353         return;
    354     DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
    355     if (m_nFramePosition + 1 == m_nFrameCount)
    356     {
    357         m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
    358         DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
    359         this->Invalidate();
    360     }
    361 }
    362 
    363 void CButtonUIEx::OnLeaveTimer(UINT_PTR idEvent)
    364 {
    365     if (idEvent != EVENT_ANIMA_LEAVE_TIMERID)
    366         return;
    367     m_pManager->KillTimer(this, EVENT_ANIMA_LEAVE_TIMERID);
    368     m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
    369     this->Invalidate();
    370 
    371     m_nFramePosition--;
    372     m_pManager->SetTimer(this, EVENT_ANIMA_LEAVE_TIMERID, m_nTimerSize);
    373 }
    374 
    375 void CButtonUIEx::DrawLeaveFrame(HDC hDC)
    376 {
    377     if (NULL == hDC || vecAnimation.size() == 0)
    378         return;
    379     DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
    380     if (m_nFramePosition == 0)
    381     {
    382         m_pManager->KillTimer(this, EVENT_ANIMA_LEAVE_TIMERID);
    383         DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
    384         this->Invalidate();
    385         m_bLeaveFlag = false;
    386         m_bNormalFlag = true;
    387     }
    388 }
    389 
    390 void CButtonUIEx::PaintText(HDC hDC)
    391 {
    392     if ((m_uButtonState & UISTATE_PUSHED) != 0 && (m_rcPushedTextPadding.bottom != 0 || m_rcPushedTextPadding.left != 0 || m_rcPushedTextPadding.right != 0 || m_rcPushedTextPadding.top != 0))
    393     {
    394         CDuiString sText = GetText();
    395         if (sText.IsEmpty()) return;
    396         DWORD clrColor = IsEnabled() ? m_dwTextColor : m_dwDisabledTextColor;
    397 
    398         if (GetPushedTextColor() != 0)
    399             clrColor = GetPushedTextColor();
    400 
    401         RECT rc = m_rcItem;
    402         rc.left += m_rcPushedTextPadding.left;
    403         rc.right -= m_rcPushedTextPadding.right;
    404         rc.top += m_rcPushedTextPadding.top;
    405         rc.bottom -= m_rcPushedTextPadding.bottom;
    406 
    407         CRenderEngine::DrawText(hDC, m_pManager, rc, sText, clrColor, 
    408             m_iFont, m_uTextStyle);
    409     }
    410     else
    411         CButtonUI::PaintText(hDC);
    412 }

    效果图:

    demo下载地址:动画按钮

  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/chechen/p/5984484.html
Copyright © 2011-2022 走看看