自己写的GDI+ 图片文字按钮 ButtonIT

#pragma once
#include "afxwin.h"

#include
#include

#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

class CButtonIT : public CButton
{
public:
CButtonIT();
virtual ~CButtonIT();

DECLARE_MESSAGE_MAP()
public:

enum ButtonType
{
  PUSHBUTTON,  // 普通按钮
  CHECKBOX,  // 复选框
  RADIOBUTTON, // 单选按钮
};

// 按钮状态,即鼠标与按钮的位置
enum ButtonState
{   
  MOUSE_OUT  = 0, // 鼠标在按钮外面
  MOUSE_IN,    // 鼠标在按钮里面
  MOUSE_DOWN,    // 按钮按下
  MOUSE_FOCUS,   // 按钮获得焦点
  MOUSE_DISABLE   // 按钮禁用
};

// 图像和文字位置
enum ButtonImgTextPosion
{
  IT_CENTER,  // 图像和文字重叠居中
  IT_OUT_LEFT, // 文字在图像外面,及左边
  IT_OUT_TOP,  // 文字在图像外面,及右边
  IT_OUT_RIGHT,   // 文字在图像外面,及上面
  IT_OUT_BOTTOM, // 文字在图像外面,及下面
  IT_IN_LEFT,  // 文字在图像里面,及左边
  IT_IN_TOP,  // 文字在图像里面,及右边
  IT_IN_RIGHT,    // 文字在图像里面,及上面
  IT_IN_BOTTOM // 文字在图像里面,及下面
};
protected:
virtual void PreSubclassWindow();

public:
void FreeImagesResources(); 
void SetFrameColors(const Color& crOut = Color(0, 255, 255, 255)
  , const Color& crIn = Color(0, 255, 255, 255)
  , const Color& crDown = Color(0, 255, 255, 255)
  , const Color& crFocus = Color(0, 255, 255, 255)
  , const Color& crDisable = Color(0, 255, 255, 255));

void SetBackgroundColors(const Color& crOut = Color(0, 220, 220, 247)
  , const Color& crIn = Color(0, 240, 240, 240)
  , const Color& crDown = Color(0, 240, 240, 240)
  , const Color& crFocus = Color(0, 240, 240, 240)
  , const Color& crDisable = Color(0, 240, 240, 240));

void SetFontFamilys(LPCTSTR lpszOut = _T("宋体")
  , LPCTSTR lpszIn = _T("宋体")
  , LPCTSTR lpszDown = _T("宋体")
  , LPCTSTR lpszFocus = _T("宋体")
  , LPCTSTR lpszDisable = _T("宋体"));

void SetFontSizes(const float& sizeOut = 16
  , const float& sizeIn = 16
  , const float& sizeDown = 16
  , const float& sizeFocus = 16
  , const float& sizeDisable = 16);

void SetFontStyles(const FontStyle& fsOut = FontStyleRegular
  , const FontStyle& fsIn = FontStyleRegular
  , const FontStyle& fsDown = FontStyleRegular
  , const FontStyle& fsFocus = FontStyleRegular
  , const FontStyle& fsDisable = FontStyleRegular);

void SetTextColors(const Color& crOut = Color(255, 0, 0, 0)
  , const Color& crIn = Color(255, 0, 0, 0)
  , const Color& crDown = Color(255, 0, 0, 0)
  , const Color& crFocus = Color(255, 0, 0, 200)
  , const Color& crDisable = Color(255, 0, 0, 0));

void InitToolTip();
void SetTooltipText(LPCTSTR lpszText, BOOL isActivate = TRUE);
void ActivateTooltip(BOOL isEnable = TRUE);
void EnableBalloonTooltip(BOOL isEnable);
virtual BOOL PreTranslateMessage(MSG* pMsg);

afx_msg BOOL OnEraseBkgnd(CDC* pDC);

Status LoadImages(UINT nImageOut, UINT nImageIn = NULL, UINT nImageDown = NULL, UINT nImageFocus = NULL, UINT nImageDisable = NULL);
Status LoadImages(LPCTSTR lpImageOut, LPCTSTR lpImageIn = NULL, LPCTSTR lpImageDown = NULL, LPCTSTR lpImageFocus = NULL, LPCTSTR lpImageDisable = NULL);

inline void SetImgTextPosition(ButtonImgTextPosion btPos);

inline void SetWindowText(LPCTSTR lpszString);
inline void SetBmpTextDistance(BYTE distance);
void SetHitOffset(byte offset);

inline byte GetIndex();
void GetImageTextRect(LPRECT lpRectItem, LPRECT lpRectImage, LPRECT lpRectText);

virtual void DrawImage(Graphics& graphics, LPRECT lpRectImage);
virtual void DrawText(Graphics& graphics, LPRECT lpRectText);

virtual void DrawRoundRectange(Graphics& graphics, LPRECT lpRect, Color& color);
virtual void FillRoundRectangle(Graphics& graphics, LPRECT lpRect, Color& color);

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg void OnKillFocus(CWnd* pNewWnd);

private:
    ULONG_PTR m_gdiplusToken;
    Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;

const static BYTE BTN_STATES = 5; 
//const double EPSINON;     // 最小精度
const int ROUND_RADIUS;     // 圆角半径

byte  m_type;  // 按钮类型,为ButtonType中的值之一
byte  m_state;  // 按钮状态,为ButtonState中的值之一,但不表示是否拥有焦点,用m_isFocus表示
byte  m_itPosition; // 图像和文字位置,为ButtonImgTextPosion中的值之一
byte  m_hitOffset;  // 单击时,图像文字偏移量

BYTE m_itDistance;

bool  m_isFocus;    // 表示是否获得焦点

CRect m_frameRect;  // 边框区域
CRect m_drawRect;   // 绘画背景按钮文字区域
CRect m_imgRect;    // 图像区域
CRect m_textRect;   // 文字区域

//
CDC     m_bgDC;
CBitmap m_bgBmp;
Image* m_pImgs[BTN_STATES];

Color m_frameColors[BTN_STATES];   // button background color
Color m_bgColors[BTN_STATES];   // button background color

CString     m_text;     // button caption
CString     m_fontNames[BTN_STATES];
float       m_fontSizes[BTN_STATES];
FontStyle   m_fontStyles[BTN_STATES];
Color       m_fontColors[BTN_STATES];

CToolTipCtrl m_tooltip;
DWORD m_dwTooltipStyle; // Style of tooltip control

BOOL m_isTracking; 
};

inline byte CButtonIT::GetIndex()

byte index;
if (m_isFocus && m_state == MOUSE_OUT)
{

  index = MOUSE_FOCUS;
}
else
{
  index = m_state;
}

if (m_pImgs[index] == NULL)
{
  index = 0;
}

return index;
}

inline void CButtonIT::SetImgTextPosition(ButtonImgTextPosion btPos)
{
m_itPosition = btPos;
GetImageTextRect(m_drawRect, m_imgRect, m_textRect); 
}

inline void CButtonIT::SetWindowText(LPCTSTR lpszString)
{
m_text = lpszString;
GetImageTextRect(m_drawRect, m_imgRect, m_textRect); 
}

inline void CButtonIT::SetBmpTextDistance(BYTE distance)
{
m_itDistance = distance;
GetImageTextRect(m_drawRect, m_imgRect, m_textRect); 
}

///////////////////////////////////////////////

#include "StdAfx.h"
#include "ButtonIT.h"
#include

CButtonIT::CButtonIT(void)
: ROUND_RADIUS(5)
, m_type(PUSHBUTTON)
, m_state(MOUSE_OUT)
, m_itPosition(IT_OUT_BOTTOM)
, m_hitOffset(2)
, m_isFocus(false)
, m_frameRect(CRect(0,0,0,0))
, m_drawRect(CRect(0,0,0,0))
, m_imgRect(CRect(0,0,0,0))
, m_textRect(CRect(0,0,0,0))
, m_dwTooltipStyle(0)
, m_itDistance(2)
, m_isTracking(FALSE)
{
    // 初始化GDI+
    Gdiplus::GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);

for (int i(0); i < BTN_STATES; ++i)
{
  m_pImgs[i] = NULL;  

SetFontFamilys();
SetFontSizes();
SetFontStyles();
SetTextColors();
SetFrameColors();
SetBackgroundColors();
}

CButtonIT::~CButtonIT(void)
{
    // 清理所有GDI+资源
    Gdiplus::GdiplusShutdown(m_gdiplusToken);

FreeImagesResources();
if (m_tooltip.m_hWnd)
{
  m_tooltip.DestroyWindow();
}
}

BEGIN_MESSAGE_MAP(CButtonIT, CButton)
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_WM_KILLFOCUS()
END_MESSAGE_MAP()

void CButtonIT::FreeImagesResources()

for (int i(0); i < BTN_STATES; ++i)
{
  if (m_pImgs[i])
  {
   delete m_pImgs[i];
   m_pImgs[i] = NULL;  
  }
}
}

void CButtonIT::PreSubclassWindow()
{
m_type = GetButtonStyle(); // get specific BS_ styles
if ((m_type & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX)
{
  m_type = CHECKBOX;
}
else if ((m_type & BS_AUTORADIOBUTTON) == BS_AUTORADIOBUTTON)
{
  m_type = RADIOBUTTON;
}
else
{
  m_type = PUSHBUTTON;
}

if (!IsWindowEnabled())
{
  m_state = MOUSE_DISABLE;
}

GetWindowText(m_text);

InitToolTip();

ModifyStyle(NULL, BS_OWNERDRAW);

//设置按钮的有效区域
GetClientRect(&m_drawRect);

m_frameRect = m_drawRect;
m_drawRect.DeflateRect(1,1,1,1);
GetImageTextRect(m_drawRect, m_imgRect, m_textRect);

//有效区域为一个角半径为5的圆角矩形
CRgn rgn;
rgn.CreateRoundRectRgn(m_frameRect.left, m_frameRect.top, m_frameRect.right, m_frameRect.bottom, ROUND_RADIUS, ROUND_RADIUS);
SetWindowRgn(rgn, TRUE); 
rgn.DeleteObject();

CButton::PreSubclassWindow();
}

void CButtonIT::SetFontFamilys(LPCTSTR lpszOut
          , LPCTSTR lpszIn
          , LPCTSTR lpszDown
          , LPCTSTR lpszFocus
          , LPCTSTR lpszDisable)
{
m_fontNames[MOUSE_OUT] = lpszOut;
m_fontNames[MOUSE_IN] = lpszIn;
m_fontNames[MOUSE_DOWN] = lpszDown;
m_fontNames[MOUSE_FOCUS] = lpszFocus;
m_fontNames[MOUSE_DISABLE] = lpszDisable;
}

void CButtonIT::SetFontSizes(const float& sizeOut
      , const float& sizeIn
      , const float& sizeDown
      , const float& sizeFocus
      , const float& sizeDisable)
{
m_fontSizes[MOUSE_OUT] = sizeOut;
m_fontSizes[MOUSE_IN] = sizeIn;
m_fontSizes[MOUSE_DOWN] = sizeDown;
m_fontSizes[MOUSE_FOCUS] = sizeFocus;
m_fontSizes[MOUSE_DISABLE] = sizeDisable;
}

void CButtonIT::SetFontStyles(const FontStyle& fsOut
       , const FontStyle& fsIn
       , const FontStyle& fsDown
       , const FontStyle& fsFocus
       , const FontStyle& fsDisable)
{
m_fontStyles[MOUSE_OUT] = fsOut;
m_fontStyles[MOUSE_IN] = fsIn;
m_fontStyles[MOUSE_DOWN] = fsDown;
m_fontStyles[MOUSE_FOCUS] = fsFocus;
m_fontStyles[MOUSE_DISABLE] = fsDisable;
}

void CButtonIT::SetTextColors(const Color& crOut /* = Color */
          , const Color& crIn /* = Color */
          , const Color& crDown /* = Color */
          , const Color& crFocus /* = Color */
          , const Color& crDisable /* = Color */)
{
m_fontColors[MOUSE_OUT] = crOut;
m_fontColors[MOUSE_IN] = crIn;
m_fontColors[MOUSE_DOWN] = crDown;
m_fontColors[MOUSE_FOCUS] = crFocus;
m_fontColors[MOUSE_DISABLE] = crDisable;
}

void CButtonIT::SetFrameColors(const Color& crOut /* = Color */
         , const Color& crIn /* = Color */
         , const Color& crDown /* = Color */
         , const Color& crFocus /* = Color */
         , const Color& crDisable /* = Color */)
{
m_frameColors[MOUSE_OUT] = crOut;
m_frameColors[MOUSE_IN] = crIn;
m_frameColors[MOUSE_DOWN] = crDown;
m_frameColors[MOUSE_FOCUS] = crFocus;
m_frameColors[MOUSE_DISABLE] = crDisable;
}

void CButtonIT::SetBackgroundColors(const Color& crOut /* = Color */
         , const Color& crIn /* = Color */
         , const Color& crDown /* = Color */
         , const Color& crFocus /* = Color */
         , const Color& crDisable /* = Color */)
{
m_bgColors[MOUSE_OUT] = crOut;
m_bgColors[MOUSE_IN] = crIn;
m_bgColors[MOUSE_DOWN] = crDown;
m_bgColors[MOUSE_FOCUS] = crFocus;
m_bgColors[MOUSE_DISABLE] = crDisable;
}

void CButtonIT::InitToolTip()
{
if (m_tooltip.m_hWnd == NULL)
{
  m_tooltip.Create(this, m_dwTooltipStyle);
  m_tooltip.Activate(FALSE);
  m_tooltip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 400);
}
}

void CButtonIT::SetTooltipText(LPCTSTR lpszText, BOOL isActivate)
{
if (lpszText)
{
  InitToolTip();

  if (m_tooltip.GetToolCount() == 0)
  {
   CRect rectBtn;
   GetClientRect(rectBtn);
   m_tooltip.AddTool(this, lpszText, rectBtn, 1);
  }

  m_tooltip.UpdateTipText(lpszText, this, 1);
  m_tooltip.Activate(isActivate);

}

void CButtonIT::ActivateTooltip(BOOL isActivate)
{
if (m_tooltip.GetToolCount() > 0)
{
  m_tooltip.Activate(isActivate);
}
}

// 必须调用SetTooltipText,重新设置文字
void CButtonIT::EnableBalloonTooltip(BOOL isEnable)
{
if (m_tooltip.m_hWnd)
{
  m_tooltip.DestroyWindow();
}
if (isEnable)
{
  m_dwTooltipStyle |= TTS_BALLOON;
}
else
{
  m_dwTooltipStyle  = NULL;
}

InitToolTip();
}

BOOL CButtonIT::PreTranslateMessage(MSG* pMsg)
{
m_tooltip.RelayEvent(pMsg);

return CButton::PreTranslateMessage(pMsg);
}

BOOL CButtonIT::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

Status CButtonIT::LoadImages(UINT nImageOut, UINT nImageIn /* = NULL */, UINT nImageDown /* = NULL */, UINT nImageFocus /* = NULL */, UINT nImageDisable /* = NULL */)

return LoadImages(MAKEINTRESOURCE(nImageOut)
  , MAKEINTRESOURCE(nImageIn)
  , MAKEINTRESOURCE(nImageDown)
  , MAKEINTRESOURCE(nImageFocus)
  , MAKEINTRESOURCE(nImageDisable));
}
Status CButtonIT::LoadImages(LPCTSTR lpImageOut, LPCTSTR lpImageIn /* = NULL */, LPCTSTR lpImageDown /* = NULL */, LPCTSTR lpImageFocus /* = NULL */, LPCTSTR lpImageDisable /* = NULL */)
{
Status status = GenericError;

try
{
  if (lpImageOut)
  {
   Image* pImage(NULL);
   pImage = new Image(lpImageOut);
   status = pImage->GetLastStatus();
   if(status != Ok)
   {
    m_pImgs[MOUSE_OUT] = NULL;
    throw  false;
   }
   else
   {
    m_pImgs[MOUSE_OUT] = pImage;
   }
  }
  else
  {
   m_pImgs[MOUSE_OUT] = NULL;
   throw false;
  }

  if (lpImageIn == NULL)
  {
   lpImageIn = lpImageOut;
  }
  if (lpImageDown == NULL)
  {
   lpImageDown = lpImageOut;
  }
  if (lpImageFocus == NULL)
  {
   lpImageFocus = lpImageOut;
  }
  if (lpImageDisable == NULL)
  {
   lpImageDisable = lpImageOut;
  }

  if (lpImageIn)
  {
   Image* pImage(NULL);
   pImage = new Image(lpImageIn);
   status = pImage->GetLastStatus();
   if(status != Ok)
   {
    m_pImgs[MOUSE_IN] = NULL;
    throw  false;
   }
   else
   {
    m_pImgs[MOUSE_IN] = pImage;
   }
  }

  if (lpImageDown)
  {
   Image* pImage(NULL);
   pImage = new Image(lpImageDown);
   status = pImage->GetLastStatus();
   if(status != Ok)
   {
    m_pImgs[MOUSE_DOWN] = NULL;
    throw  false;
   }
   else
   {
    m_pImgs[MOUSE_DOWN] = pImage;
   }
  }

  if (lpImageFocus)
  {
   Image* pImage(NULL);
   pImage = new Image(lpImageFocus);
   status = pImage->GetLastStatus();
   if(status != Ok)
   {
    m_pImgs[MOUSE_FOCUS] = NULL;
    throw  false;
   }
   else
   {
    m_pImgs[MOUSE_FOCUS] = pImage;
   }
  }

  if (lpImageDisable)
  {
   Image* pImage(NULL);
   pImage = new Image(lpImageDisable);
   status = pImage->GetLastStatus();
   if(status != Ok)
   {
    m_pImgs[MOUSE_DISABLE] = NULL;
    throw  false;
   }
   else
   {
    m_pImgs[MOUSE_DISABLE] = pImage;
   }
  }
}
catch (...)
{
}

GetImageTextRect( m_drawRect, m_imgRect, m_textRect);

return status;
}

void CButtonIT::GetImageTextRect(LPRECT lpRectItem, LPRECT lpRectImage, LPRECT lpRectText)
{
// 按钮高宽
UINT width(lpRectItem->right - lpRectItem->left);
UINT height(lpRectItem->bottom - lpRectItem->top);

CClientDC dc(this);
Gdiplus::Graphics graphics(dc);
FontFamily fontFamily(m_fontNames[0]);
Gdiplus::Font font(&fontFamily, m_fontSizes[0], m_fontStyles[0], UnitPixel); 
RectF outrect;
graphics.MeasureString(m_text, m_text.GetLength(), &font, RectF(0,0,0,0), &outrect);
UINT textWidth = static_cast (outrect.Width);
UINT textHeight = static_cast (outrect.Height);

if (textWidth > width)
{
  textWidth = width;
}
if (textHeight > height)
{
  textHeight = height;
}

lpRectImage->left = 0;
lpRectImage->top = 0;
lpRectImage->right = 0;
lpRectImage->bottom = 0;

lpRectText->left = 0;
lpRectText->top = 0;
lpRectText->right = 0;
lpRectText->bottom = 0;

if (m_pImgs[0] == NULL)
{
  lpRectText->left = lpRectItem->left;
  lpRectText->top = lpRectItem->top;
  lpRectText->right = lpRectItem->right;
  lpRectText->bottom = lpRectItem->bottom;

  // 文字居中
  lpRectText->left  += (width - textWidth) / 2;
  lpRectText->top   += (height - textHeight) / 2;
  lpRectText->right  = lpRectText->left + textWidth;
  lpRectText->bottom = lpRectText->top + textWidth;
}
else
{
  lpRectImage->left = lpRectItem->left;
  lpRectImage->top = lpRectItem->top;
  lpRectImage->right = lpRectItem->right;
  lpRectImage->bottom = lpRectItem->bottom;

  UINT imgWidth = m_pImgs[0]->GetWidth();
  UINT imgHeight = m_pImgs[0]->GetHeight();
  if (imgWidth > width)
  {
   imgWidth = width;
  }
  if (imgHeight > height)
  {
   imgHeight = height;
  }

  // 计算位置是否已经完成
  bool isFinished(true);

  if (!m_text.IsEmpty())
  {
   switch (m_itPosition)
   {
   case IT_OUT_LEFT:
    {       
     // 图像文字水平排列宽度
     UINT btWidth = textWidth + imgWidth + m_itDistance;

     // 图像 + 文字 + 间隔 宽度 <= 按钮宽度
     if (btWidth <= width)
     {
      // |  text Bmp  |
      lpRectText->left   = (width - btWidth) / 2;     
      lpRectText->top   += (height - textHeight) / 2;   // 高居中
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

      lpRectImage->left   = lpRectText->right + m_itDistance;
      lpRectImage->top   += (height - imgHeight) / 2; // 高居中
      lpRectImage->right  = lpRectImage->left + imgWidth;
      lpRectImage->bottom = lpRectImage->top + imgHeight;
     }
     // 两边对齐,中间交叉
     else
     {
      lpRectText->left   = 1;     
      lpRectText->top   += (height - textHeight) / 2;   // 高居中
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

      lpRectImage->right   = width - 1;
      lpRectImage->top    += (height - imgHeight) / 2; // 高居中
      lpRectImage->left    = lpRectImage->right - imgWidth;
      lpRectImage->bottom  = lpRectImage->top + imgHeight;
     }
    }
    break;

   case IT_OUT_TOP:
    {
     // 图像文字垂直排列宽度
     UINT btHeight = textHeight + imgHeight + m_itDistance;

     // 图像 + 文字 + 间隔 宽度 <= 按钮宽度
     if (btHeight <= height)
     {
      // |  text  |
      // |   Bmp  |
      lpRectText->left  += (width - textWidth) / 2;   // 左 居中  
      lpRectText->top    = (height - btHeight) / 2;
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

      lpRectImage->left  += (width - imgWidth) / 2; // 左 居中 
      lpRectImage->top    = lpRectText->bottom + m_itDistance;
      lpRectImage->right  = lpRectImage->left + imgWidth;
      lpRectImage->bottom = lpRectImage->top + imgHeight;
     }
     // 两边对齐,中间交叉
     else
     {
      lpRectText->left  += (width - textWidth) / 2;   // 左 居中    
      lpRectText->top    = 1;  
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

      lpRectImage->left  += (width - imgWidth) / 2; // 左 居中 
      lpRectImage->bottom = height - 1;
      lpRectImage->top    = lpRectImage->bottom - imgHeight;
      lpRectImage->right  = lpRectImage->left + imgWidth;

     }
    }
    break;

   case IT_OUT_RIGHT:
    {   
     // 图像文字水平排列宽度
     UINT btWidth = textWidth + imgWidth + m_itDistance;

     // 图像 + 文字 + 间隔 宽度 <= 按钮宽度
     if (btWidth <= width)
     {
      // |  Bmp  text |

      lpRectImage->left   = (width - btWidth) / 2; 
      lpRectImage->top   += (height - imgHeight) / 2; // 高居中
      lpRectImage->right  = lpRectImage->left + imgWidth;
      lpRectImage->bottom = lpRectImage->top + imgHeight;

      lpRectText->left  =  lpRectImage->right + m_itDistance;   
      lpRectText->top   += (height - textHeight) / 2;   // 高居中
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

     }
     // 两边对齐,中间交叉
     else
     {
      lpRectImage->left  = 1;
      lpRectImage->top   += (height - imgHeight) / 2; // 高居中
      lpRectImage->right   = lpRectImage->left + imgWidth;
      lpRectImage->bottom = lpRectImage->top + imgHeight;

      lpRectText->right   = width - 1;     
      lpRectText->top   += (height - textHeight) / 2;   // 高居中
      lpRectText->left  = lpRectText->right - textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;     
     }
    }
    break;

   case IT_OUT_BOTTOM:
    {
     // 图像文字垂直排列宽度
     UINT btHeight = textHeight + imgHeight + m_itDistance;

     // 图像 + 文字 + 间隔 宽度 <= 按钮宽度
     if (btHeight <= height)
     {
      // |   Bmp  |
      // |  text  |

      lpRectImage->left  += (width - imgWidth) / 2; // 左 居中 
      lpRectImage->top    = (height - btHeight) / 2;
      lpRectImage->right  = lpRectImage->left + imgWidth;
      lpRectImage->bottom = lpRectImage->top + imgHeight;

      lpRectText->left  += (width - textWidth) / 2;   // 左 居中  
      lpRectText->top    = lpRectImage->bottom + m_itDistance;
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->bottom = lpRectText->top + textHeight;

     }
     // 两边对齐,中间交叉
     else
     {
      lpRectImage->left  += (width - imgWidth) / 2; // 左 居中 
      lpRectImage->top = 1;     
      lpRectImage->right  = lpRectImage->left + imgWidth;
      lpRectImage->bottom    = lpRectImage->top + imgHeight;

      lpRectText->left  += (width - textWidth) / 2;   // 左 居中    
      lpRectText->bottom    = height - 1;  
      lpRectText->right  = lpRectText->left + textWidth;
      lpRectText->top = lpRectText->bottom - textHeight;
     }
    }
    break;

   default:
    isFinished = false;

    break;
   }
  }
        else
        {
            isFinished = false;
        }

  if (isFinished == false)
  {
   // 图像居中
   lpRectImage->left  += (width - imgWidth) / 2;
   lpRectImage->top   += (height - imgHeight) / 2;
   lpRectImage->right  = lpRectImage->left + imgWidth;
   lpRectImage->bottom = lpRectImage->top + imgHeight;

   switch (m_itPosition)
   {
   case IT_IN_LEFT:
    {
     lpRectText->left  =  lpRectImage->left + m_itDistance;   
     lpRectText->top   += (height - textHeight) / 2;   // 高居中
     lpRectText->right  = lpRectText->left + textWidth;
     lpRectText->bottom = lpRectText->top + textHeight;

    }
    break;
   case IT_IN_TOP:
    {
     lpRectText->left  += (width - textWidth) / 2;   // 左 居中  
     lpRectText->top = lpRectImage->top + m_itDistance;
     lpRectText->right  = lpRectText->left + textWidth;
     lpRectText->bottom = lpRectText->top + textHeight;
    }
    break;
   case IT_IN_RIGHT:
    {
     lpRectText->right  = lpRectImage->right - m_itDistance;   
     lpRectText->top   += (height - textHeight) / 2;   // 高居中
     lpRectText->left   = lpRectText->right - textWidth;
     lpRectText->bottom = lpRectText->top + textHeight;
    }
    break;
   case IT_IN_BOTTOM:
    {
     lpRectText->left  += (width - textWidth) / 2;   // 左 居中  
     lpRectText->bottom = lpRectImage->bottom - m_itDistance;
     lpRectText->right  = lpRectText->left + textWidth;
     lpRectText->top = lpRectText->bottom - textHeight;
    }
    break;
   default:
    {
     // 文字居中
     lpRectText->left  += (width - textWidth) / 2;
     lpRectText->top   += (height - textHeight) / 2;
     lpRectText->right  = lpRectText->left + textWidth;
     lpRectText->bottom = lpRectText->top + textHeight;
    }

    break;
   }  
  } 
}
}

void CButtonIT::DrawImage(Graphics& graphics, LPRECT lpRectImage)

byte index(GetIndex());

int offset(0);
if (m_state == MOUSE_DOWN)
{
  offset = m_hitOffset;
}

    // CClientDC dc(this);
    // Graphics g(dc.m_hDC);

if (m_state == MOUSE_OUT || m_state == MOUSE_DISABLE)
{
  graphics.DrawImage(m_pImgs[index], m_imgRect.left + offset, m_imgRect.top + offset, m_pImgs[index]->GetWidth(), m_pImgs[index]->GetHeight());   
}
else if (m_state == MOUSE_IN || m_state == MOUSE_DOWN)
{
  ColorMatrix HotMat = { 1.05f, 0.00f, 0.00f, 0.00f, 0.00f,
   0.00f, 1.05f, 0.00f, 0.00f, 0.00f,
   0.00f, 0.00f, 1.05f, 0.00f, 0.00f,
   0.00f, 0.00f, 0.00f, 1.00f, 0.00f,
   0.05f, 0.05f, 0.05f, 0.00f, 1.00f };

  ImageAttributes ia;
  ia.SetColorMatrix(&HotMat);

  float width = (float)m_pImgs[index]->GetWidth();
  float height = (float)m_pImgs[index]->GetHeight();

  RectF rectF(static_cast (m_imgRect.left + offset), static_cast (m_imgRect.top + offset), width, height);

  graphics.DrawImage(m_pImgs[index], rectF, 0, 0, width, height, UnitPixel, &ia);  
}
}

void CButtonIT::DrawText(Graphics& graphics, LPRECT lpRectText)
{
byte index(GetIndex());

FontFamily fontFamily(m_fontNames[index]);
Gdiplus::Font font(&fontFamily, m_fontSizes[index], m_fontStyles[index], UnitPixel);
SolidBrush   solidBrush(m_fontColors[index]);
int offset(0);
if (m_state == MOUSE_DOWN)
{
  offset = m_hitOffset;
}
PointF      pointF(static_cast (m_textRect.left + offset), static_cast (m_textRect.top + offset));
graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
graphics.DrawString(m_text, -1, &font, pointF, &solidBrush);
}

void CButtonIT::DrawRoundRectange(Graphics& graphics, LPRECT lpRect, Color& color)
{
// 设置画图时的滤波模式为消除锯齿现象
graphics.SetSmoothingMode(SmoothingModeAntiAlias);

GraphicsPath graphicspath;
graphicspath.AddArc(lpRect->right - ROUND_RADIUS - 1, lpRect->top, ROUND_RADIUS, ROUND_RADIUS, 270, 90);
graphicspath.AddArc(lpRect->right - ROUND_RADIUS - 1, lpRect->bottom - ROUND_RADIUS - 1, ROUND_RADIUS, ROUND_RADIUS, 0, 90);
graphicspath.AddArc(lpRect->left, lpRect->bottom - ROUND_RADIUS - 1, ROUND_RADIUS, ROUND_RADIUS, 90, 90);
graphicspath.AddArc(lpRect->left, lpRect->top, ROUND_RADIUS, ROUND_RADIUS, 180, 90);
graphicspath.AddLine(lpRect->left + ROUND_RADIUS, lpRect->top, lpRect->right - ROUND_RADIUS/2, lpRect->top);

// 创建一个红色的画笔
Pen pen(color);
graphics.DrawPath(&pen, &graphicspath);
}

void CButtonIT::FillRoundRectangle(Graphics& graphics, LPRECT lpRect, Color& color)
{
// 用路径渐变画笔填充
GraphicsPath graphicspath;
//graphicspath.AddArc(lpRect->right - ROUND_RADIUS - 1, lpRect->top, ROUND_RADIUS, ROUND_RADIUS, 270, 90);
graphicspath.AddArc(lpRect->right - ROUND_RADIUS - 1, lpRect->bottom - ROUND_RADIUS - 1, ROUND_RADIUS, ROUND_RADIUS, 0, 90);
graphicspath.AddArc(lpRect->left, lpRect->bottom - ROUND_RADIUS - 1, ROUND_RADIUS, ROUND_RADIUS, 90, 90);
graphicspath.AddArc(lpRect->left, lpRect->top, ROUND_RADIUS, ROUND_RADIUS, 180, 90);
graphicspath.AddLine(lpRect->left + ROUND_RADIUS, lpRect->top, lpRect->right - ROUND_RADIUS/2, lpRect->top);

// Use the path to construct a brush.
PathGradientBrush pthGrBrush(&graphicspath);

// Set the color at the center of the path to blue.
pthGrBrush.SetCenterColor(color);

// Set the color along the entire boundary of the path to aqua.
Color colors[] = {color};
int count = 1;
pthGrBrush.SetSurroundColors(colors, &count);

// Fill the path with the path gradient brush.
graphics.FillPath(&pthGrBrush, &graphicspath);

}

void CButtonIT::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

CClientDC parentDC(GetParent());

CRect rcClient;
CRect rcWindow;

GetClientRect(rcClient);
GetWindowRect(rcWindow);

GetParent()->ScreenToClient(rcWindow);

// 得到透明背景memdc
if (m_bgDC.m_hDC == NULL)
{
  m_bgDC.CreateCompatibleDC(&parentDC);
  m_bgBmp.CreateCompatibleBitmap(&parentDC, rcClient.Width(), rcClient.Height());
  m_bgDC.SelectObject(&m_bgBmp);
  m_bgDC.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &parentDC, rcWindow.left, rcWindow.top, SRCCOPY);
}

// 是否禁用或有焦点
if (lpDrawItemStruct->itemState & ODS_DISABLED)
{
  m_state = MOUSE_DISABLE;
}
else
{
  if (m_type == CHECKBOX)
  {
   // checked
   if ((lpDrawItemStruct->itemState & ODS_SELECTED) || (m_state == MOUSE_FOCUS))
   {
    m_isFocus = true;
   }
  }
}

pDC->SetBkMode(TRANSPARENT);

LONG width  = m_frameRect.Width();
LONG height = m_frameRect.Height();

CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SetBkMode(TRANSPARENT);

CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, width, height);
memDC.SelectObject(&bmp);
memDC.BitBlt(0,0, width, height, &m_bgDC, 0, 0, SRCCOPY);

Gdiplus::Graphics graphics(memDC);

byte index(GetIndex());
FillRoundRectangle(graphics, m_frameRect, m_bgColors[index]);

// Draw the image
if (m_pImgs[0])
{
  DrawImage(graphics, m_imgRect);
}

if (!m_text.IsEmpty())
{
  DrawText(graphics, m_textRect);
}

DrawRoundRectange(graphics, m_frameRect, m_frameColors[index]);
CRect rect(m_frameRect);
rect.DeflateRect(1, 1, 1, 1);
DrawRoundRectange(graphics, rect, Color(47, 255, 255, 255));

pDC->BitBlt(0, 0, width, height, &memDC, 0, 0, SRCCOPY);
bmp.DeleteObject();
}

void CButtonIT::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_state != MOUSE_IN)
{
  m_state = MOUSE_IN;

  Invalidate(FALSE);
}

CButton::OnMouseMove(nFlags, point);

if (!m_isTracking)
{
  TRACKMOUSEEVENT tm;
  tm.cbSize = sizeof(TRACKMOUSEEVENT);
  // 注册 消息
  tm.dwFlags = TME_HOVER|TME_LEAVE;  
  tm.dwHoverTime = HOVER_DEFAULT;
  tm.hwndTrack = m_hWnd;
  m_isTracking = _TrackMouseEvent(&tm);

}

void CButtonIT::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_state != MOUSE_DOWN)
{
  m_state = MOUSE_DOWN;

  Invalidate(FALSE);
}

CButton::OnLButtonDown(nFlags, point);
}

void CButtonIT::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_state != MOUSE_IN || !m_isFocus)
{
  m_state = MOUSE_IN;
  m_isFocus = true;

  Invalidate(FALSE);
}

CButton::OnLButtonUp(nFlags, point);
}

LRESULT CButtonIT::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
if (m_state != MOUSE_OUT)
{
  m_state = MOUSE_OUT;

  Invalidate(FALSE);
}

m_isTracking = FALSE;

return S_OK;
}

void CButtonIT::OnKillFocus(CWnd* pNewWnd)
{
CButton::OnKillFocus(pNewWnd);

if (m_isFocus)
{
  m_isFocus = false;

  Invalidate(FALSE);

}

你可能感兴趣的:(自己写的GDI+ 图片文字按钮 ButtonIT)