#include "stdafx.h"
|
#include "BlButton.h"
|
|
|
#define BADGE_HIDE 0
|
#define BADGE_DOT 1
|
#define BADGE_NUMBER 2
|
#define BADGE_DOT_WIDTH 12
|
#define BADGE_NUMBER_WIDTH 20
|
|
CBlButton::CBlButton()
|
{
|
m_nState = BS_NORMAL;
|
m_crFrame[BS_NORMAL] = RGB(225, 225, 225);
|
m_crFrame[BS_HOVER] = RGB(0, 120, 215);
|
m_crFrame[BS_PRESS] = RGB(0, 84, 153);
|
m_crFrame[BS_FOCUS] = RGB(0, 120, 215);
|
m_crFrame[BS_DISABLE] = RGB(191, 191, 191);
|
m_crBkgnd[BS_NORMAL] = RGB(225, 225, 225);
|
m_crBkgnd[BS_HOVER] = RGB(229, 241, 251);
|
m_crBkgnd[BS_PRESS] = RGB(204, 228, 247);
|
m_crBkgnd[BS_FOCUS] = RGB(225, 225, 225);
|
m_crBkgnd[BS_DISABLE] = RGB(204, 204, 204);
|
m_crText[BS_NORMAL] = RGB(0, 0, 0);
|
m_crText[BS_HOVER] = RGB(0, 0, 0);
|
m_crText[BS_PRESS] = RGB(0, 0, 0);
|
m_crText[BS_FOCUS] = RGB(0, 0, 0);
|
m_crText[BS_DISABLE] = RGB(131, 131, 131);
|
m_bHover = FALSE;
|
m_bSelected = FALSE;
|
m_bTracking = FALSE;
|
memset(&m_badge, 0, sizeof(BADGE));
|
m_nRoundWidth = 0;
|
m_hMenu = nullptr;
|
m_hIcon[0] = nullptr;
|
m_hIcon[1] = nullptr;
|
m_nIconWidth = 0;
|
m_nFlashState = 0;
|
}
|
|
|
CBlButton::~CBlButton()
|
{
|
}
|
|
void CBlButton::SetFrameColor(int index, COLORREF color)
|
{
|
if (BS_NORMAL <= index && index <= BS_DISABLE) {
|
m_crFrame[index] = color;
|
}
|
}
|
|
void CBlButton::SetFrameColor(COLORREF color)
|
{
|
m_crFrame[BS_NORMAL] = color;
|
m_crFrame[BS_HOVER] = color;
|
m_crFrame[BS_PRESS] = color;
|
m_crFrame[BS_FOCUS] = color;
|
Invalidate();
|
}
|
|
void CBlButton::SetRoundWidth(int width)
|
{
|
m_nRoundWidth = width;
|
}
|
|
void CBlButton::SetBkgndColor(int index, COLORREF color)
|
{
|
if (BS_NORMAL <= index && index <= BS_DISABLE) {
|
m_crBkgnd[index] = color;
|
}
|
}
|
|
void CBlButton::SetTextColor(int index, COLORREF color)
|
{
|
if (BS_NORMAL <= index && index <= BS_DISABLE) {
|
m_crText[index] = color;
|
}
|
}
|
|
void CBlButton::SetFaceColor(COLORREF color)
|
{
|
m_crBkgnd[BS_NORMAL] = color;
|
m_crBkgnd[BS_HOVER] = color;
|
m_crBkgnd[BS_PRESS] = color;
|
m_crBkgnd[BS_FOCUS] = color;
|
Invalidate();
|
}
|
|
void CBlButton::SetTextColor(COLORREF color)
|
{
|
m_crText[BS_NORMAL] = color;
|
m_crText[BS_HOVER] = color;
|
m_crText[BS_PRESS] = color;
|
m_crText[BS_FOCUS] = color;
|
Invalidate();
|
}
|
|
void CBlButton::SetBadgeNumber(int number)
|
{
|
m_badge.badgeBackground = RGB(255, 0, 0);
|
m_badge.badgeForeground = RGB(255, 255, 255);
|
m_badge.type = number > 0 ? BADGE_NUMBER : BADGE_HIDE;
|
m_badge.number = number;
|
Invalidate();
|
}
|
|
void CBlButton::ShowDotBadge(BOOL bShow, COLORREF color)
|
{
|
m_badge.badgeBackground = color;
|
m_badge.type = bShow ? BADGE_DOT : BADGE_HIDE;
|
Invalidate();
|
}
|
|
void CBlButton::SetBkgndBmp(const char* pszBmpFile)
|
{
|
m_strBkgndBmp = pszBmpFile;
|
}
|
|
void CBlButton::SetMenu(HMENU hMenu)
|
{
|
m_hMenu = hMenu;
|
}
|
|
void CBlButton::SetCurrentMenuItem(UINT nPosition)
|
{
|
char szTxt[256];
|
GetMenuString(::GetSubMenu(m_hMenu, 0), nPosition, szTxt, 256, MF_BYPOSITION);
|
SetWindowText(szTxt);
|
}
|
|
HMENU CBlButton::GetMenu()
|
{
|
return m_hMenu;
|
}
|
|
void CBlButton::SetIcon(HICON hIcon, HICON hIconGray, int width)
|
{
|
m_hIcon[0] = hIcon;
|
m_hIcon[1] = hIconGray;
|
m_nIconWidth = width;
|
}
|
|
void CBlButton::Flash(int ms)
|
{
|
m_nFlashState = 1;
|
SetTimer(1, ms, nullptr);
|
}
|
|
void CBlButton::StopFlash()
|
{
|
m_nFlashState = 0;
|
KillTimer(1);
|
Invalidate();
|
}
|
|
BOOL CBlButton::IsFlash()
|
{
|
return m_nFlashState != 0;
|
}
|
|
void CBlButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
{
|
HDC hDC = lpDrawItemStruct->hDC;
|
RECT rcClient;
|
GetClientRect(&rcClient);
|
|
|
// ±ß¿ò+±³¾°
|
int state = GetDrawState();
|
if (m_nFlashState != 0) {
|
if (state != BS_DISABLE) {
|
state = m_nFlashState == 1 ? BS_NORMAL : BS_PRESS;
|
}
|
}
|
HBRUSH hBrush = CreateSolidBrush(m_crBkgnd[state]);
|
HPEN hPen = CreatePen(PS_SOLID, state == BS_FOCUS ? 2 : 1, m_crFrame[state]);
|
HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
|
HPEN hOldBrush = (HPEN)::SelectObject(hDC, hBrush);
|
::RoundRect(hDC, state == BS_FOCUS ? rcClient.left + 1 : rcClient.left,
|
state == BS_FOCUS ? rcClient.top + 1 : rcClient.top, rcClient.right,
|
rcClient.bottom, m_nRoundWidth, m_nRoundWidth);
|
::SelectObject(hDC, hOldPen);
|
::SelectObject(hDC, hOldBrush);
|
::DeleteObject(hBrush);
|
::DeleteObject(hPen);
|
|
|
|
// Ìùͼ
|
CustomBitBlt(hDC, &rcClient, m_strBkgndBmp, state, 5, 2, 2, 2, 2, RGB(255,0,255));
|
|
// »ñµÃÎı¾
|
char szText[64];
|
int nTextLen = GetWindowText(szText, 64);
|
|
|
// ͼ±ê
|
RECT rcText = rcClient;
|
HICON hIcon = this->IsWindowEnabled() ? m_hIcon[0] : m_hIcon[01];
|
if (hIcon != nullptr) {
|
int xIcon = (rcClient.right - rcClient.top - m_nIconWidth) / 2;
|
if (m_hMenu != nullptr) xIcon -= 10;
|
int yIcon = (rcClient.bottom - rcClient.top - m_nIconWidth) / 2;
|
if (nTextLen != 0) {
|
yIcon -= 8;
|
}
|
|
DrawIconEx(hDC, xIcon, yIcon,
|
hIcon, m_nIconWidth, m_nIconWidth, 0, 0, DI_NORMAL);
|
rcText.top = yIcon + m_nIconWidth + 2;
|
}
|
|
|
// Îı¾
|
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
CFont* pFont = GetFont();
|
if (pFont != nullptr) {
|
hFont = (HFONT)pFont->GetSafeHandle();
|
}
|
|
HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
|
::SetBkMode(hDC, TRANSPARENT);
|
::SetTextColor(hDC, m_crText[state]);
|
|
if ((BS_MULTILINE & GetStyle()) == BS_MULTILINE) {
|
CRect rcBound;
|
int height = DrawTextA(hDC, szText, (int)strlen(szText), &rcBound, DT_CENTER | DT_CALCRECT | DT_EDITCONTROL);
|
rcText.top = rcBound.top + (rcClient.bottom - rcClient.top - height) / 2;
|
rcText.bottom = rcText.top + height;
|
DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_CENTER | DT_EDITCONTROL);
|
}
|
else {
|
if (m_hMenu != nullptr) {
|
rcText.right -= (10);
|
}
|
DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
|
}
|
::SelectObject(hDC, hOldFont);
|
|
|
// ÊÇ·ñÓÐСԲµã
|
if (m_badge.type == BADGE_DOT) {
|
Gdiplus::Graphics graphics(hDC);
|
graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
|
Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
|
int x = rcClient.right - 8 - BADGE_DOT_WIDTH;
|
int y = rcClient.top + 8;
|
graphics.FillEllipse(&brush, x, y, BADGE_DOT_WIDTH, BADGE_DOT_WIDTH);
|
}
|
else if (m_badge.type == BADGE_NUMBER) {
|
Gdiplus::Graphics graphics(hDC);
|
graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
|
Gdiplus::SolidBrush brush(Gdiplus::Color(GetRValue(m_badge.badgeBackground), GetGValue(m_badge.badgeBackground), GetBValue(m_badge.badgeBackground)));
|
int x = rcClient.right - 8 - BADGE_NUMBER_WIDTH;
|
int y = rcClient.top + 8;
|
graphics.FillEllipse(&brush, x, y, BADGE_NUMBER_WIDTH, BADGE_NUMBER_WIDTH);
|
RECT rcBadge;
|
rcBadge.left = x;
|
rcBadge.right = rcBadge.left + BADGE_NUMBER_WIDTH;
|
rcBadge.top = y;
|
rcBadge.bottom = rcBadge.top + BADGE_NUMBER_WIDTH;
|
::SetTextColor(hDC, m_badge.badgeForeground);
|
char szBuffer[32];
|
sprintf_s(szBuffer, 32, "%d%s", min(m_badge.number, 9), m_badge.number > 9 ? "+" : "");
|
DrawText(hDC, szBuffer, (int)strlen(szBuffer), &rcBadge, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
}
|
|
|
// ²Ëµ¥ÏîСÈý½Ç
|
if (m_hMenu != nullptr) {
|
HPEN hPenDrop = CreatePen(PS_SOLID, 1, m_crText[state]);
|
HBRUSH hbrDrop = CreateSolidBrush(m_crText[state]);
|
HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hbrDrop);
|
HPEN hOldPen = (HPEN)::SelectObject(hDC, hPenDrop);
|
POINT pt[3];
|
pt[0].x = rcClient.right - 20;
|
pt[0].y = rcClient.top + (rcClient.bottom - rcClient.top - 5) / 2;
|
pt[1].x = pt[0].x + 10;
|
pt[1].y = pt[0].y;
|
pt[2].x = pt[0].x + (pt[1].x - pt[0].x) / 2;
|
pt[2].y = pt[0].y + 5;
|
::Polygon(hDC, pt, 3);
|
::SelectObject(hDC, hOldBrush);
|
::SelectObject(hDC, hOldPen);
|
::DeleteObject(hbrDrop); // ÕýÈ·ÊÍ·ÅСÈý½ÇʹÓõĻˢ
|
::DeleteObject(hPenDrop); // ÕýÈ·ÊÍ·ÅСÈý½ÇµÄ±Ê
|
}
|
}
|
|
int CBlButton::GetDrawState()
|
{
|
if (!IsWindowEnabled()) {
|
return BS_DISABLE;
|
}
|
|
//if (GetFocus() == this) {
|
// return BS_FOCUS;
|
//}
|
|
return m_nState;
|
}
|
|
void CBlButton::PreSubclassWindow()
|
{
|
m_bHover = false;
|
m_bSelected = false;
|
m_bTracking = FALSE;
|
ModifyStyle(0, BS_OWNERDRAW);
|
|
CButton::PreSubclassWindow();
|
}
|
|
BEGIN_MESSAGE_MAP(CBlButton, CButton)
|
ON_WM_MOUSEMOVE()
|
ON_WM_MOUSEHOVER()
|
ON_WM_MOUSELEAVE()
|
ON_WM_LBUTTONDOWN()
|
ON_CONTROL_REFLECT_EX(BN_CLICKED, &CBlButton::OnBnClicked)
|
ON_WM_LBUTTONUP()
|
ON_WM_TIMER()
|
END_MESSAGE_MAP()
|
|
|
void CBlButton::OnMouseMove(UINT nFlags, CPoint point)
|
{
|
if (!m_bTracking)
|
{
|
TRACKMOUSEEVENT tme;
|
tme.cbSize = sizeof(tme);
|
tme.dwFlags = TME_HOVER | TME_LEAVE; // ·¢ËÍWM_MOUSEHOVERºÍWM_MOUSELEAVE
|
tme.hwndTrack = m_hWnd; // Ö¸¶¨Òª×·×ٵĴ°¿Ú
|
tme.dwHoverTime = 10; // Êó±êÔÚ°´Å¥ÉÏÍ£Áô³¬¹ý10ms£¬²ÅÈÏΪ״̬ΪHOVER
|
m_bTracking = _TrackMouseEvent(&tme); // ¿ªÆôWindowsµÄWM_MOUSELEAVEWM_MOUSEHOVERʼþÖ§³Ö
|
}
|
|
CButton::OnMouseMove(nFlags, point);
|
}
|
|
|
void CBlButton::OnMouseHover(UINT nFlags, CPoint point)
|
{
|
m_bHover = true;
|
m_nState = BS_HOVER;
|
InvalidateRect(NULL);
|
|
return;
|
|
// CButton::OnMouseHover(nFlags, point);
|
}
|
|
|
void CBlButton::OnMouseLeave()
|
{
|
m_bHover = false;
|
m_bTracking = FALSE; // ÈôÒѾÀ뿪£¬ÔòÍ£Ö¹×·×Ù
|
m_nState = BS_NORMAL;
|
InvalidateRect(NULL);
|
|
CButton::OnMouseLeave();
|
}
|
|
BOOL CBlButton::CustomBitBlt(HDC hDC, LPRECT lprc, CString& strBkgndBmp, int nFrame, int nAllFrame,
|
int nB0, int nB1, int nB2, int nB3, COLORREF crTransparent)
|
{
|
// ÔØÈëBMP
|
HBITMAP hBmpTemp = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
|
strBkgndBmp, IMAGE_BITMAP, 0, 0,
|
LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
|
if (hBmpTemp == NULL)
|
return FALSE;
|
|
HDC hDCTemp = ::CreateCompatibleDC(hDC);
|
::SelectObject(hDCTemp, hBmpTemp);
|
BITMAP bitmap;
|
::GetObject(hBmpTemp, sizeof(BITMAP), &bitmap);
|
|
int nFrameWidth = bitmap.bmWidth / nAllFrame; // ÿ֡µÄ¿í
|
int nFrameX = nFrameWidth*nFrame; // Ö¸¶¨Ö¡ÏàËØÆðµã
|
|
|
// Èç¹û½Ç»ò±ßºñΪ0
|
if (nB0 == 0 && nB1 == 0 &&
|
nB2 == 0 && nB3 == 0) {
|
::TransparentBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
|
hDCTemp, nFrameX, 0, nFrameWidth, bitmap.bmHeight, crTransparent);
|
|
::DeleteObject(hBmpTemp);
|
::DeleteDC(hDCTemp);
|
return TRUE;
|
}
|
|
|
// ÆäËü
|
int x = lprc->left + nB3;
|
int y = lprc->top + nB0;
|
::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), lprc->bottom - lprc->top - (nB0 + nB2),
|
hDCTemp, nFrameX + nB3, nB0, nFrameWidth - (nB1 + nB3), bitmap.bmHeight - (nB0 + nB2), crTransparent);
|
|
x = lprc->left;
|
y = lprc->top;
|
::TransparentBlt(hDC, x, y, nB3, nB0,
|
hDCTemp, nFrameX + 0, 0, nB3, nB0, crTransparent);
|
|
x += nB3;
|
y = lprc->top;
|
::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB0,
|
hDCTemp, nFrameX + nB3, 0, nFrameWidth - (nB1 + nB3), nB0, crTransparent);
|
|
x = lprc->right - nB1;
|
y = lprc->top;
|
::TransparentBlt(hDC, x, y, nB1, nB0,
|
hDCTemp, nFrameX + nFrameWidth - nB1, 0, nB1, nB0, crTransparent);
|
|
x = lprc->right - nB1;
|
y = lprc->top + nB0;
|
::TransparentBlt(hDC, x, y, nB1, lprc->bottom - lprc->top - (nB0 + nB2),
|
hDCTemp, nFrameX + nFrameWidth - nB1, nB0, nB1, bitmap.bmHeight - (nB0 + nB2), crTransparent);
|
|
x = lprc->right - nB1;
|
y = lprc->bottom - nB2;
|
::TransparentBlt(hDC, x, y, nB1, nB2,
|
hDCTemp, nFrameX + nFrameWidth - nB1, bitmap.bmHeight - nB2, nB1, nB2, crTransparent);
|
|
x = lprc->left + nB3;
|
y = lprc->bottom - nB2;
|
::TransparentBlt(hDC, x, y, lprc->right - lprc->left - (nB1 + nB3), nB2,
|
hDCTemp, nFrameX + nB3, bitmap.bmHeight - nB2, nFrameWidth - (nB1 + nB3), nB2, crTransparent);
|
|
x = lprc->left;
|
y = lprc->bottom - nB2;
|
::TransparentBlt(hDC, x, y, nB3, nB2,
|
hDCTemp, nFrameX + 0, bitmap.bmHeight - nB2, nB3, nB2, crTransparent);
|
|
x = lprc->left;
|
y = lprc->top + nB0;
|
::TransparentBlt(hDC, x, y, nB3, lprc->bottom - lprc->top - (nB0 + nB2),
|
hDCTemp, nFrameX + 0, nB0, nB3, bitmap.bmHeight - (nB0 + nB2), crTransparent);
|
|
|
::DeleteObject(hBmpTemp);
|
::DeleteDC(hDCTemp);
|
return TRUE;
|
}
|
|
void CBlButton::OnLButtonDown(UINT nFlags, CPoint point)
|
{
|
m_nState = BS_PRESS;
|
CButton::OnLButtonDown(nFlags, point);
|
}
|
|
void CBlButton::OnLButtonUp(UINT nFlags, CPoint point)
|
{
|
m_nState = BS_HOVER;
|
CButton::OnLButtonUp(nFlags, point);
|
}
|
|
BOOL CBlButton::OnBnClicked()
|
{
|
if (m_hMenu != NULL) {
|
RECT rect;
|
GetWindowRect(&rect);
|
int cmd = ::TrackPopupMenu(::GetSubMenu(m_hMenu, 0),
|
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, rect.left, rect.bottom, 0, m_hWnd, NULL);
|
if (cmd > 0) {
|
int position = cmd - GetMenuItemID(::GetSubMenu(m_hMenu, 0), 0);
|
Notify((int)BLBUTTON_MENU_ITEM_CLICKED, position);
|
}
|
}
|
|
return FALSE;
|
}
|
|
void CBlButton::Notify(int nCode, DWORD_PTR dwData, DWORD_PTR dwData1/* = 0*/, DWORD_PTR dwData2/* = 0*/)
|
{
|
CWnd* pParent;
|
pParent = GetParent();
|
if (pParent != nullptr) {
|
BLBUTTON_NMHDR blbNmhdr;
|
blbNmhdr.nmhdr.code = nCode;
|
blbNmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);
|
blbNmhdr.nmhdr.hwndFrom = m_hWnd;
|
blbNmhdr.dwData = dwData;
|
blbNmhdr.dwData1 = dwData1;
|
blbNmhdr.dwData2 = dwData2;
|
pParent->SendMessage(WM_NOTIFY, (WPARAM)blbNmhdr.nmhdr.idFrom, (LPARAM)&blbNmhdr);
|
}
|
}
|
|
void CBlButton::OnTimer(UINT_PTR nIDEvent)
|
{
|
if (1 == nIDEvent) {
|
m_nFlashState++;
|
if (m_nFlashState > 2) m_nFlashState = 1;
|
Invalidate();
|
}
|
|
CButton::OnTimer(nIDEvent);
|
}
|