| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #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(); |
| | | } |
| | | |
| | | |
| | | ::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); |
| | | } |
| | | |
| | | |
| | | // æ¯å¦æå°åç¹ |
| | | 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(hBrush); |
| | | ::DeleteObject(hPen); |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | } |