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