转载:http://blog.csdn.net/cuiguanghui123/article/details/51674218
.h文件
#ifndef __UIBUTTONEX_H__
#define __UIBUTTONEX_H__ #pragma once #define EVENT_ANIMA_ENTER_TIMERID UIMSG_USER+100 //鼠标进入按钮TimerID
#define EVENT_ANIMA_LEAVE_TIMERID UIMSG_USER+101 //鼠标离开按钮TimerID
class CButtonUIEx : public CButtonUI
{
DECLARE_DUICONTROL(CButtonUIEx)
public:
enum ChannelARGB {
Blue = , Green = , Red = , Alpha =
}; CButtonUIEx();
virtual ~CButtonUIEx(); virtual void SetMaskImage(LPCTSTR pStrImage);
virtual LPCTSTR GetMaskImage(); virtual LPCTSTR GetPushedForeImage();
virtual void SetPushedForeImage(LPCTSTR pStrImage); virtual RECT GetPushedTextPadding();
virtual void SetPushedTextPadding(RECT rc); void SetAnimationImages(vector<DuiLib::CDuiString>); virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue); virtual void DoPaint(HDC hDC, const RECT& rcPaint);
virtual void PaintBkImage(HDC hDC);
void PaintStatusImage(HDC hDC); virtual bool TransferOneARGBChannelFromOneBitmapToAnother(IN Gdiplus::Bitmap &src,
OUT Gdiplus::Bitmap &dst,
ChannelARGB srcChannel,
ChannelARGB dstChannel); //-------------添加---------
void OnTimer(UINT_PTR idEvent);
void DoEvent(TEventUI& event) override;
void DrawFrame(HDC hDC); // 绘制GIF每帧
void OnLeaveTimer(UINT_PTR idEvent);
void DrawLeaveFrame(HDC hDC); // 绘制GIF每帧 void PaintText(HDC hDC); private:
bool _ResizeClone(Gdiplus::Image *&image, INT width, INT height); protected:
DuiLib::CDuiString m_sBkImageEx;
DuiLib::CDuiString m_sMaskImage; Gdiplus::Image *m_pMaskImage;
Gdiplus::Bitmap *m_pBmpFluffy;
Gdiplus::Bitmap *m_pBmpMask; CDuiString m_sPushedForeImage;
vector<DuiLib::CDuiString> vecAnimation;
UINT m_nFrameCount; // 图片总帧数
UINT m_nFramePosition; // 当前放到第几帧
UINT m_nTimerSize; // 帧与帧之间间隔时间
BOOL m_bLeaveFlag;
BOOL m_bNormalFlag;
RECT m_rcPushedTextPadding;
}; #endif //__UIBUTTONEX_H__
.cpp文件
#include "stdafx.h"
#include "UIButtonEx.h" #ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p) = 0; } }
#endif // SAFE_DELETE IMPLEMENT_DUICONTROL(CButtonUIEx)
/////////////////////////////////////////////////////////////////////////////////////
//
// CButtonUIEx::CButtonUIEx()
: CButtonUI()
, m_pMaskImage(NULL)
, m_pBmpFluffy(NULL)
, m_pBmpMask(NULL)
{
m_nFramePosition = ;
m_nFrameCount = ;
m_nTimerSize = ;
m_bLeaveFlag = false;
m_bNormalFlag = true;
::ZeroMemory(&m_rcPushedTextPadding, sizeof(m_rcPushedTextPadding));
} CButtonUIEx::~CButtonUIEx()
{
SAFE_DELETE(m_pMaskImage);
SAFE_DELETE(m_pBmpFluffy);
SAFE_DELETE(m_pBmpMask);
} void CButtonUIEx::SetMaskImage(LPCTSTR pStrImage)
{
m_sMaskImage = pStrImage;
Invalidate();
} LPCTSTR CButtonUIEx::GetMaskImage()
{
return m_sMaskImage;
} LPCTSTR CButtonUIEx::GetPushedForeImage()
{
return m_sPushedForeImage;
} void CButtonUIEx::SetPushedForeImage(LPCTSTR pStrImage)
{
m_sPushedForeImage = pStrImage;
Invalidate();
} void CButtonUIEx::SetAnimationImages(vector<DuiLib::CDuiString> vecList)
{
vecAnimation = vecList;
m_nFrameCount = vecList.size();
} RECT CButtonUIEx::GetPushedTextPadding()
{
return m_rcPushedTextPadding;
} void CButtonUIEx::SetPushedTextPadding(RECT rc)
{
m_rcPushedTextPadding = rc;
Invalidate();
} void CButtonUIEx::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
if (_tcscmp(pstrName, _T("maskimage")) == ) SetMaskImage(pstrValue);
else if (_tcsicmp(pstrName, _T("pushedforeimage")) == ) SetPushedForeImage(pstrValue);
else if (_tcsicmp(pstrName, _T("pushedtextpadding")) == ) {
RECT rcTextPadding = { };
LPTSTR pstr = NULL;
rcTextPadding.left = _tcstol(pstrValue, &pstr, ); ASSERT(pstr);
rcTextPadding.top = _tcstol(pstr + , &pstr, ); ASSERT(pstr);
rcTextPadding.right = _tcstol(pstr + , &pstr, ); ASSERT(pstr);
rcTextPadding.bottom = _tcstol(pstr + , &pstr, ); ASSERT(pstr);
SetPushedTextPadding(rcTextPadding);
}
else CButtonUI::SetAttribute(pstrName, pstrValue);
} void CButtonUIEx::DoPaint(HDC hDC, const RECT& rcPaint)
{
if (!::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem)) return; // RESERVED: add your code here.
if (m_bNormalFlag && vecAnimation.size() > )
DrawImage(hDC, (LPCTSTR)vecAnimation[]); if ((m_uButtonState & UISTATE_HOT) != )
{
DrawFrame(hDC);
m_bNormalFlag = false;
}
if(m_bLeaveFlag)
DrawLeaveFrame(hDC);
__super::DoPaint(hDC, rcPaint);
} void CButtonUIEx::PaintBkImage(HDC hDC)
{
if (m_sMaskImage && m_sBkImageEx != m_sBkImage) {
do {
m_sBkImageEx = m_sBkImage; SAFE_DELETE(m_pBmpFluffy);
m_pBmpFluffy = new Gdiplus::Bitmap(m_pManager->GetResourcePath() + m_sBkImageEx);
if (!m_pBmpFluffy || m_pBmpFluffy->GetLastStatus() != Gdiplus::Status::Ok) {
// TODO: check if m_sBkImageEx contains an absolute path.
m_pBmpFluffy = new Gdiplus::Bitmap(m_sBkImageEx);
if (!m_pBmpFluffy || m_pBmpFluffy->GetLastStatus() != Gdiplus::Status::Ok) {
break;
}
} if (m_sMaskImage.IsEmpty()) {
break;
} SAFE_DELETE(m_pMaskImage);
m_pMaskImage = Gdiplus::Image::FromFile(m_pManager->GetResourcePath() + m_sMaskImage);
if (!m_pMaskImage || m_pMaskImage->GetLastStatus() != Gdiplus::Status::Ok) {
break;
} if (!_ResizeClone(m_pMaskImage, m_pBmpFluffy->GetWidth(), m_pBmpFluffy->GetHeight())) {
break;
} Gdiplus::Rect rectFluffy(, , m_pBmpFluffy->GetWidth(), m_pBmpFluffy->GetHeight()); SAFE_DELETE(m_pBmpMask);
m_pBmpMask = new Gdiplus::Bitmap(rectFluffy.Width, rectFluffy.Height);
if (!m_pBmpMask) {
break;
} Gdiplus::Graphics graphics(m_pBmpMask);
graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
graphics.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
graphics.DrawImage(m_pMaskImage, rectFluffy); TransferOneARGBChannelFromOneBitmapToAnother(*m_pBmpMask, *m_pBmpFluffy, ChannelARGB::Blue, ChannelARGB::Alpha);
SAFE_DELETE(m_pBmpMask);
} while ();
} if (m_pBmpFluffy) {
Gdiplus::Rect rectDst(m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
Gdiplus::Rect rectSrc((m_rcPaint.left - m_rcItem.left) * m_pBmpFluffy->GetWidth() / (m_rcItem.right - m_rcItem.left),
(m_rcPaint.top - m_rcItem.top) * m_pBmpFluffy->GetHeight() / (m_rcItem.bottom - m_rcItem.top),
(m_rcPaint.right - m_rcPaint.left) * m_pBmpFluffy->GetWidth() / (m_rcItem.right - m_rcItem.left),
(m_rcPaint.bottom - m_rcPaint.top) * m_pBmpFluffy->GetHeight() / (m_rcItem.bottom - m_rcItem.top)); Gdiplus::Graphics g(hDC);
g.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
g.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
g.DrawImage(m_pBmpFluffy, rectDst, rectSrc.X, rectSrc.Y, rectSrc.Width, rectSrc.Height, Gdiplus::Unit::UnitPixel);
}
} bool CButtonUIEx::TransferOneARGBChannelFromOneBitmapToAnother(IN Gdiplus::Bitmap &src,
OUT Gdiplus::Bitmap &dst,
ChannelARGB srcChannel,
ChannelARGB dstChannel)
{
if (src.GetWidth() != dst.GetWidth() || src.GetHeight() != dst.GetHeight())
return false; Gdiplus::Rect rectSrc(, , src.GetWidth(), src.GetHeight());
Gdiplus::BitmapData bdSrc, bdDst;
src.LockBits(&rectSrc, Gdiplus::ImageLockMode::ImageLockModeRead, PixelFormat32bppPARGB, &bdSrc);
dst.LockBits(&rectSrc, Gdiplus::ImageLockMode::ImageLockModeWrite, PixelFormat32bppPARGB, &bdDst); // unsafe codes that protected by LockBits
byte *bpSrc = (byte *)bdSrc.Scan0;
byte *bpDst = (byte *)bdDst.Scan0; bpSrc += (int)srcChannel;
bpDst += (int)dstChannel;
for (int i = rectSrc.Height * rectSrc.Width; i > ; i--) {
*bpDst = *bpSrc;
bpSrc += ;
bpDst += ;
}
// end (unsafe codes) src.UnlockBits(&bdSrc);
dst.UnlockBits(&bdDst);
return true;
} bool CButtonUIEx::_ResizeClone(Gdiplus::Image *&image, INT width, INT height)
{
UINT image_width = image->GetWidth();
UINT image_height = image->GetHeight();
INT width_ = width;
INT height_ = height; if (image_width == width_ && image_height == height_)
return true; double ratio = ((double)image_width) / image_height;
if (image_width > image_height) { // Resize down by width
height_ = static_cast<UINT>(((double)width_) / ratio);
}
else {
width_ = static_cast<UINT>(((double)height_) / ratio);
} Gdiplus::Image *dst = new Gdiplus::Bitmap(width_, height_, image->GetPixelFormat());
if (dst && dst->GetLastStatus() == Gdiplus::Status::Ok) {
Gdiplus::Graphics graphics(dst);
graphics.DrawImage(image, , , width_, height_); SAFE_DELETE(image);
image = dst;
return true;
} SAFE_DELETE(dst);
return false;
} void CButtonUIEx::PaintStatusImage(HDC hDC)
{
if (IsFocused()) m_uButtonState |= UISTATE_FOCUSED;
else m_uButtonState &= ~UISTATE_FOCUSED;
if (!IsEnabled()) m_uButtonState |= UISTATE_DISABLED;
else m_uButtonState &= ~UISTATE_DISABLED; if (!::IsWindowEnabled(m_pManager->GetPaintWindow())) {
m_uButtonState &= UISTATE_DISABLED;
}
if ((m_uButtonState & UISTATE_DISABLED) != ) {
if (!m_sDisabledImage.IsEmpty())
{
if (!DrawImage(hDC, (LPCTSTR)m_sDisabledImage)) m_sDisabledImage.Empty();
else goto Label_ForeImage;
}
}
else if ((m_uButtonState & UISTATE_PUSHED) != ) {
if (!m_sPushedImage.IsEmpty()) {
if (!DrawImage(hDC, (LPCTSTR)m_sPushedImage)){
m_sPushedImage.Empty();
}
if (!m_sPushedForeImage.IsEmpty())
{
if (!DrawImage(hDC, (LPCTSTR)m_sPushedForeImage))
m_sPushedForeImage.Empty();
return;
}
else goto Label_ForeImage;
}
else if (m_dwPushedBkColor != ) {
CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwPushedBkColor));
return;
}
}
else if ((m_uButtonState & UISTATE_HOT) != ) {
if (!m_sHotImage.IsEmpty())
{
if (!DrawImage(hDC, (LPCTSTR)m_sHotImage))
{
m_sHotImage.Empty();
}
if (!m_sHotForeImage.IsEmpty())
{
if (!DrawImage(hDC, (LPCTSTR)m_sHotForeImage))
m_sHotForeImage.Empty();
return;
}
else goto Label_ForeImage;
}
else if (m_nFrameCount != )
{
m_pManager->SetTimer(this, EVENT_ANIMA_ENTER_TIMERID, m_nTimerSize);
}
else if (m_dwHotBkColor != ) {
CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwHotBkColor));
return;
}
}
else if ((m_uButtonState & UISTATE_FOCUSED) != ) {
if (!m_sFocusedImage.IsEmpty()) {
if (!DrawImage(hDC, (LPCTSTR)m_sFocusedImage)) m_sFocusedImage.Empty();
else goto Label_ForeImage;
}
} if (!m_sNormalImage.IsEmpty()) {
if (!DrawImage(hDC, (LPCTSTR)m_sNormalImage)) m_sNormalImage.Empty();
else goto Label_ForeImage;
} if (!m_sForeImage.IsEmpty())
goto Label_ForeImage; return; Label_ForeImage:
if (!m_sForeImage.IsEmpty()) {
if (!DrawImage(hDC, (LPCTSTR)m_sForeImage)) m_sForeImage.Empty();
}
} void CButtonUIEx::DoEvent(TEventUI& event)
{
CButtonUI::DoEvent(event);
if (event.Type == UIEVENT_MOUSELEAVE)
{
if (IsEnabled()) {
m_uButtonState &= ~UISTATE_HOT;
Invalidate();
if (m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID))
{
m_bLeaveFlag = true;
m_pManager->SetTimer(this, EVENT_ANIMA_LEAVE_TIMERID, m_nTimerSize);
}
}
}
if (event.Type == UIEVENT_TIMER)
{
if ((UINT_PTR)event.wParam == EVENT_ANIMA_ENTER_TIMERID)
OnTimer((UINT_PTR)event.wParam);
else if ((UINT_PTR)event.wParam == EVENT_ANIMA_LEAVE_TIMERID)
OnLeaveTimer((UINT_PTR)event.wParam);
}
} void CButtonUIEx::OnTimer(UINT_PTR idEvent)
{
if (idEvent != EVENT_ANIMA_ENTER_TIMERID)
return;
m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
this->Invalidate(); m_nFramePosition++; m_pManager->SetTimer(this, EVENT_ANIMA_ENTER_TIMERID, m_nTimerSize);
} void CButtonUIEx::DrawFrame(HDC hDC)
{
if (NULL == hDC || vecAnimation.size() == || m_nFramePosition >= m_nFrameCount)
return;
DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
if (m_nFramePosition + == m_nFrameCount)
{
m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
this->Invalidate();
}
} void CButtonUIEx::OnLeaveTimer(UINT_PTR idEvent)
{
if (idEvent != EVENT_ANIMA_LEAVE_TIMERID)
return;
m_pManager->KillTimer(this, EVENT_ANIMA_LEAVE_TIMERID);
m_pManager->KillTimer(this, EVENT_ANIMA_ENTER_TIMERID);
this->Invalidate(); m_nFramePosition--;
m_pManager->SetTimer(this, EVENT_ANIMA_LEAVE_TIMERID, m_nTimerSize);
} void CButtonUIEx::DrawLeaveFrame(HDC hDC)
{
if (NULL == hDC || vecAnimation.size() == )
return;
DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
if (m_nFramePosition == )
{
m_pManager->KillTimer(this, EVENT_ANIMA_LEAVE_TIMERID);
DrawImage(hDC, (LPCTSTR)vecAnimation[m_nFramePosition]);
this->Invalidate();
m_bLeaveFlag = false;
m_bNormalFlag = true;
}
} void CButtonUIEx::PaintText(HDC hDC)
{
if ((m_uButtonState & UISTATE_PUSHED) != && (m_rcPushedTextPadding.bottom != || m_rcPushedTextPadding.left != || m_rcPushedTextPadding.right != || m_rcPushedTextPadding.top != ))
{
CDuiString sText = GetText();
if (sText.IsEmpty()) return;
DWORD clrColor = IsEnabled() ? m_dwTextColor : m_dwDisabledTextColor; if (GetPushedTextColor() != )
clrColor = GetPushedTextColor(); RECT rc = m_rcItem;
rc.left += m_rcPushedTextPadding.left;
rc.right -= m_rcPushedTextPadding.right;
rc.top += m_rcPushedTextPadding.top;
rc.bottom -= m_rcPushedTextPadding.bottom; CRenderEngine::DrawText(hDC, m_pManager, rc, sText, clrColor, \
m_iFont, m_uTextStyle);
}
else
CButtonUI::PaintText(hDC);
}
效果图:
demo下载地址:动画按钮