📄 macbuttons.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
//
// MacButtons.cpp : implementation file
//
// Feel free to modifiy and/or distribute this file, but
// do not remove this header.
//
// I would appreciate a notification of any bugs discovered or
// improvements that could be made.
//
// This file is provided "as is" with no expressed or implied warranty.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MacButtons.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// CMacButton class, version 2.0
//
// Copyright (c) 1999 Paul Meidinger (pmmeidinger@yahoo.com)
//
// History:
// PMM 12/13/1999 Initial implementation.
//
// PMM 12/29/1999 Minor changes made.
//
/////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------
//
CMacButton::CMacButton()
//
// Return Value: None.
//
// Parameters : None.
//
// Remarks : Standard constructor.
//
{
m_nType = TYPE_STANDARD;
m_nCheck = 0;
m_bMouseDown = FALSE;
m_bBold = FALSE;
m_hIcon = NULL;
m_hBitmap = NULL;
m_sizeImage = CSize(0, 0);
m_nImageEffect = 0;
GetColors();
CreatePens();
} // CMacButton
//-------------------------------------------------------------------
//
CMacButton::~CMacButton()
//
// Return Value: None.
//
// Parameters : None.
//
// Remarks : Destructor.
//
{
DeletePens();
} // ~CMacButton
BEGIN_MESSAGE_MAP(CMacButton, CButton)
//{{AFX_MSG_MAP(CMacButton)
ON_WM_SYSCOLORCHANGE()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMacButton message handlers
//-------------------------------------------------------------------
//
void CMacButton::PreSubclassWindow()
//
// Return Value: None.
//
// Parameters : None.
//
// Remarks : This member function is called by the framework to
// allow other necessary subclassing to occur before the
// window is subclassed. Adds the BS_OWNERDRAW style.
//
{
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);
} // PreSubclassWindow
//-------------------------------------------------------------------
//
void CMacButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
//
// Return Value: None.
//
// Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
//
// Remarks : Called by the framework when a visual aspect of an
// owner-drawn button has changed.
//
{
DrawButton(lpDIS);
} // DrawItem
//-------------------------------------------------------------------
//
void CMacButton::DrawButton(LPDRAWITEMSTRUCT lpDIS)
//
// Return Value: None.
//
// Parameters : lpDIS - A long pointer to a DRAWITEMSTRUCT structure.
//
// Remarks : Draws a Mac button.
//
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rectItem(lpDIS->rcItem);
UINT nState = lpDIS->itemState;
UINT nStyle = GetStyle();
BOOL bPushLike = BOOL(nStyle & BS_PUSHLIKE);
// Create a mem DC for drawing
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rectItem.Width(), rectItem.Height());
CBitmap *pOldBmp = dcMem.SelectObject(&bmp);
int nSaveDC = dcMem.SaveDC();
CBrush *pOldBrush = (CBrush *)dcMem.SelectStockObject(NULL_BRUSH);
dcMem.FillSolidRect(rectItem, m_crFace);
// If the button is standard or pushlike, draw it now.
// Wait until after drawing the text/image and focus to draw
// the radio button or check box. This way, the text or image
// will not cover the radio or check.
if (m_nType == TYPE_STANDARD)
DrawStandardButton(&dcMem, rectItem, nStyle, nState);
else if (bPushLike)
DrawPushLikeButton(&dcMem, rectItem, nStyle, nState);
CRect rectText(rectItem);
CRect rectImage(rectItem);
CString sText;
GetWindowText(sText);
// Draw an image or the text.
if (m_hIcon || m_hBitmap)
DrawImage(&dcMem, rectImage, nStyle, nState);
else
DrawButtonText(&dcMem, rectText, sText, nStyle, nState);
// Draw the focus rect.
if (nState & ODS_FOCUS)
{
if ((m_nType == TYPE_STANDARD) || bPushLike)
{
rectText = lpDIS->rcItem;
rectText.DeflateRect(4, 4, 4, 4);
dcMem.DrawFocusRect(rectText);
}
else if (m_hIcon || m_hBitmap)
{
rectImage.InflateRect(1, 1, 1, 1);
if (rectImage.top < rectItem.top)
rectImage.top = rectItem.top;
if (rectImage.bottom > rectItem.bottom)
rectImage.bottom = rectItem.bottom;
if (rectImage.left < rectItem.left)
rectImage.left = rectItem.left;
if (rectImage.right > rectItem.right)
rectImage.right = rectItem.right;
dcMem.DrawFocusRect(rectImage);
}
else
{
rectText.InflateRect(1, 1, 1, 2);
if (rectText.top < rectItem.top)
rectText.top = rectItem.top;
if (rectText.bottom > rectItem.bottom)
rectText.bottom = rectItem.bottom;
if (rectText.left < rectItem.left)
rectText.left = rectItem.left;
if (rectText.right > rectItem.right)
rectText.right = rectItem.right;
dcMem.DrawFocusRect(rectText);
}
} // if the button has focus
// Draw the check box or radio button now.
if (!bPushLike)
{
// Determine the rect for the check mark.
CRect rectCheck = GetCheckRect(rectItem, nStyle);
if (m_nType == TYPE_CHECKBOX)
DrawCheckBox(&dcMem, rectCheck, nStyle, nState);
else if (m_nType == TYPE_RADIO)
DrawRadioButton(&dcMem, rectCheck, nStyle, nState);
}
pDC->BitBlt(rectItem.left, rectItem.top, rectItem.Width(), rectItem.Height(), &dcMem, rectItem.left, rectItem.top, SRCCOPY);
// Clean up.
dcMem.SelectObject(pOldBrush);
dcMem.SelectObject(pOldBmp);
dcMem.RestoreDC(nSaveDC);
dcMem.DeleteDC();
bmp.DeleteObject();
} // DrawButton
//-------------------------------------------------------------------
//
void CMacButton::DrawStandardButton(CDC *pDC, const CRect &rect, UINT nStyle, UINT nState)
//
// Return Value: None.
//
// Parameters : pDC - A pointer to the DC to draw on.
// rect - The button rectangle.
// nStyle - The button's style.
// nState - The button's state.
//
// Remarks : Draws the button.
//
{
// Draw a flat button.
if (nStyle & BS_FLAT)
{
COLORREF crFill = ::GetSysColor(COLOR_WINDOW);
CBrush brFill(nState & ODS_SELECTED ? ~crFill : crFill);
CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
CPen pen;
if (nState & ODS_DISABLED)
pen.CreatePen(PS_SOLID, 1, m_crShadow);
else if (m_nCheck || m_bMouseDown)
pen.CreatePen(PS_SOLID, 1, crFill);
else
pen.CreatePen(PS_SOLID, 1, ~crFill);
CPen *pOldPen = (CPen *)pDC->SelectObject(&pen);
pDC->RoundRect(rect, CPoint(6, 6));
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
pen.DeleteObject();
return;
} // if flat
CBrush brFill(nState & ODS_SELECTED ? m_crLiteShadow : m_crFace);
CBrush *pOldBrush = (CBrush *)pDC->SelectObject(&brFill);
CPen penFrame(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME));
CPen *pOldPen = (CPen *)pDC->SelectObject(nState & ODS_DISABLED ? &m_penShadow : &penFrame);
// Draw a 3D button.
if (nState & ODS_DISABLED)
pDC->RoundRect(rect, CPoint(6, 6));
else if (nState & ODS_SELECTED)
DrawPressedPushButton(pDC, rect);
else
DrawUnpressedPushButton(pDC, rect);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
} // DrawStandardButton
//-------------------------------------------------------------------
//
void CMacButton::DrawCheckBox(CDC *pDC, CRect rect, UINT nStyle, UINT nState)
//
// Return Value: None.
//
// Parameters : pDC - A pointer to the DC to draw on.
// rect - The check mark's rectangle.
// nStyle - The button's style.
// nState - The button's state.
//
// Remarks : Draws the check mark.
//
{
BOOL bDisabled = nState & ODS_DISABLED;
// Deflate the rect by two on the right (for the check mark's shadow).
rect.DeflateRect(0, 0, 2, 0);
CPen *pOldPen = pDC->GetCurrentPen();
CBrush *pOldBrush = pDC->GetCurrentBrush();
// Draw a flat checkbox.
if (nStyle & BS_FLAT)
{
COLORREF crFrame = ::GetSysColor(COLOR_WINDOW);
CPen penFrame(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME));
CBrush brFill(crFrame);
pDC->SelectObject(&penFrame);
pDC->SelectObject(&brFill);
pDC->Rectangle(rect);
if (bDisabled)
{
for (int i = rect.left + 1, j = rect.top + 1; i < rect.right; i += 2, j += 2)
{
pDC->SetPixel(i, rect.top, crFrame);
pDC->SetPixel(i - 1, rect.bottom - 1, crFrame);
pDC->SetPixel(rect.left, j, crFrame);
pDC->SetPixel(rect.right - 1, j - 1, crFrame);
}
}
rect.DeflateRect(1, 1, 1, 1);
if (m_bMouseDown)
pDC->Rectangle(rect);
// Inflate the rect by two on the right (for the check mark's shadow).
rect.InflateRect(0, 0, 2, 0);
int nLeft = rect.left;
int nTop = rect.top;
CPen penDkShadow(PS_SOLID, 1, m_crDkShadow);
pDC->SelectObject(&penDkShadow);
// Draw the check, cross, or tri-state mark.
if (m_nCheck == 1)
{
if (m_nCheckStyle == CHECK_STYLE_CHECK)
{
if (!bDisabled)
{
pDC->MoveTo(nLeft + 1, nTop + 4);
pDC->LineTo(nLeft + 4, nTop + 7);
pDC->LineTo(nLeft + 12,nTop - 1);
}
pDC->MoveTo(nLeft + 2, nTop + 4);
pDC->LineTo(nLeft + 4, nTop + 6);
pDC->LineTo(nLeft + 11, nTop -1);
}
else if (m_nCheckStyle == CHECK_STYLE_CROSS)
{
pDC->MoveTo(nLeft, nTop);
pDC->LineTo(nLeft + 10, nTop + 10);
int nAdjust = bDisabled ? 1 : 0;
pDC->MoveTo(nLeft + nAdjust, nTop + 9 - nAdjust);
pDC->LineTo(nLeft + 10 - nAdjust, nTop - 1 + nAdjust);
}
}
else if (m_nCheck == 2)
{
pDC->SelectObject(&m_penDkShadow);
pDC->MoveTo(nLeft + 2, nTop + 4);
pDC->LineTo(nLeft + 8, nTop + 4);
pDC->MoveTo(nLeft + 2, nTop + 5);
pDC->LineTo(nLeft + 8, nTop + 5);
}
} // if flat
// Else draw a 3D checkbox.
else
{
CBrush brFrame(bDisabled ? m_crShadow : ::GetSysColor(COLOR_WINDOWFRAME));
pDC->FrameRect(rect, &brFrame);
rect.DeflateRect(1, 1);
if (m_bMouseDown)
{
CBrush brShadow(m_crLiteShadow);
pDC->FillRect(rect, &brShadow);
pDC->Draw3dRect(rect, m_crShadow, m_crLiteFace);
}
else
{
pDC->FillSolidRect(rect, m_crFace);
if (!bDisabled)
pDC->Draw3dRect(rect, m_crHilight, m_crShadow);
}
pDC->SetPixel(CPoint(rect.right - 1, rect.top), m_crFace);
pDC->SetPixel(CPoint(rect.left, rect.bottom - 1), m_crFace);
// Inflate the rect by two on the right (for the check mark's shadow).
rect.InflateRect(0, 0, 2, 0);
int nLeft = rect.left;
int nTop = rect.top;
// Draw the check, cross, or tri-state mark.
if (m_nCheck == 1)
{
// Draw the check mark's shadow
if (m_nCheckStyle == CHECK_STYLE_CHECK)
{
// Draw the check mark's shadow
pDC->SelectObject(bDisabled ? &m_penLiteShadow : &m_penShadow);
pDC->MoveTo(nLeft + 4, nTop + 8);
pDC->LineTo(nLeft + 9, nTop + 3);
pDC->LineTo(nLeft + 9, nTop + 5);
pDC->SelectObject(&m_penLiteShadow);
pDC->MoveTo(nLeft + 2, nTop + 6);
pDC->LineTo(nLeft + 4, nTop + 8);
pDC->MoveTo(nLeft + 5, nTop + 8);
pDC->LineTo(nLeft + 9, nTop + 4);
pDC->SetPixel(nLeft + 11, nTop + 1, bDisabled ? m_crLiteShadow : m_crShadow);
pDC->SetPixel(nLeft + 12, nTop + 1, m_crLiteShadow);
pDC->SetPixel(nLeft + 11, nTop + 2, m_crLiteShadow);
// Draw the check mark.
pDC->SelectObject(bDisabled ? &m_penShadow : &m_penDkShadow);
pDC->MoveTo(nLeft + 1, nTop + 4);
pDC->LineTo(nLeft + 4, nTop + 7);
pDC->LineTo(nLeft + 12,nTop - 1);
pDC->MoveTo(nLeft + 2, nTop + 4);
pDC->LineTo(nLeft + 4, nTop + 6);
pDC->LineTo(nLeft + 11, nTop -1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -