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下载地址:动画按钮

原文地址:https://www.cnblogs.com/chechen/p/5984484.html