www.gusucode.com > 一个VC++ GUI测试程序-源码程序 > 一个VC++ GUI测试程序-源码程序/code/ShadowButton.cpp

    //Download by http://www.NewXing.com
////////////////////////////////////////////////////////////////////
// 类名: CShadowButton
//
// 说明: 类似于原DOS下的阴影效果按钮
//
// 用法:
//       1、把文件shadowbutton.h、shadowbutton.cpp加入工程中
//       2、在使用的对话框中加入头文件,#include shadowbutton.h
//       3、声明要改变的按钮成员变量(可在类向导中进行),如:
//           CShadowButton	m_Cancel;
//       4、在OnInitDialog()中加入下面语句,进行初始化
//           m_Cancel.SetDefaultFace();
//           m_Cancel.SetDefaultButton();
//
// 修改: 徐景周, 加入PreSubclassWindow(),实现按钮构造时自绘属性.
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "shadowbutton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CShadowButton

CShadowButton::CShadowButton()
{
	m_bDefault = FALSE;
}

CShadowButton::~CShadowButton()
{
}


BEGIN_MESSAGE_MAP(CShadowButton, CButton)
	//{{AFX_MSG_MAP(CShadowButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CShadowButton message handlers
// 加入此涵数,不必手工设置按钮为自绘属性,jingzhou xu
void CShadowButton::PreSubclassWindow() 
{
	// 构造默认为自绘按钮属性, jingzhou xu
	ModifyStyle(0, BS_OWNERDRAW);
	CButton::PreSubclassWindow();
}

void CShadowButton::Redraw()
{
	if( m_hWnd != NULL )Invalidate();
}

void CShadowButton::SetBorderSize(int nSize)
{
	m_nBorderSize = nSize;	
}

void CShadowButton::SetColors(COLORREF crColor, COLORREF crBorder, COLORREF crShadow, COLORREF crText)
{
	m_crColor = crColor;
	m_crBorderColor = crBorder;
	m_crShadowColor = crShadow;
	m_crTextColor = crText;

}

BOOL CShadowButton::LoadBitmaps(COLORREF crTransColor, UINT nresNormalBmp, UINT nresDisabledBmp)
{
	if(!this->m_bmpNormal.LoadBitmap(nresNormalBmp))return FALSE;
	if(!this->m_bmpDisabled.LoadBitmap(nresDisabledBmp))return FALSE;

	m_crTransColor = crTransColor;

	
	return TRUE;
}

void CShadowButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	// TODO: Add your code to draw the specified item
	CDC DC, memdc;

	CBitmap MemBmp, *pOldBmp; 
	CPen *pOldPen;
	CBrush *pOldBrush;
	CFont *pOldFont;
	CRect rect(lpDrawItemStruct->rcItem);

	DC.Attach(lpDrawItemStruct->hDC);
	if(!memdc.CreateCompatibleDC(&DC))return;
	if(!MemBmp.CreateCompatibleBitmap(&DC, rect.Width(), rect.Height()))return;
	pOldBmp = memdc.SelectObject(&MemBmp);

	pOldBrush = memdc.SelectObject(DC.GetCurrentBrush());
	pOldPen = memdc.SelectObject(DC.GetCurrentPen());
	pOldFont = memdc.SelectObject(DC.GetCurrentFont());

	CBrush brush;
	brush.CreateSolidBrush(DC.GetBkColor());//dc.GetBkColor());
	memdc.FillRect(&rect, &brush); //FIX
	brush.DeleteObject();
	
	if(lpDrawItemStruct->itemState & ODS_SELECTED)DrawDown(&memdc, &rect);//FIX
	else DrawUp(&memdc, &rect); //FIX

	if(!DC.BitBlt(0, 0, rect.Width(), rect.Height(), &memdc, 0, 0, SRCCOPY))
	{
		TRACE("CShadow::dc.BitBlt error!!!!\n");
		return;
	}

	memdc.SelectObject(pOldPen);
	memdc.SelectObject(pOldBrush);
	memdc.SelectObject(pOldFont);
	memdc.SelectObject(pOldBmp);

	MemBmp.DeleteObject();
	memdc.DeleteDC();

}

void CShadowButton::SetShadowOffset(int x, int y)
{
	this->m_nShadowXOffset = x;
	this->m_nShadowYOffset = y;
}

void CShadowButton::DrawUp(CDC *pDC, CRect *pRect)
{
	
	CBrush brush;

	//画阴影部分
	CRect rectShadow(pRect);
	rectShadow.left = m_nShadowXOffset;
	rectShadow.top = m_nShadowYOffset;
	brush.CreateSolidBrush(m_crShadowColor);	
	pDC->FillRect(&rectShadow, &brush);
	brush.DeleteObject();
	DrawClient(pDC, pRect, pRect->left, pRect->top);
}

void CShadowButton::DrawDown(CDC *pDC, CRect *pRect)
{

	//画边框与客户区
	int x, y;
	if(m_sizeShadow.cx > 0)x = m_sizeShadow.cx - 1;else x = pRect->left;
	if(m_sizeShadow.cy > 0)y = m_sizeShadow.cy - 1;else y = pRect->top;

	DrawClient(pDC, pRect, x, y);
}

void CShadowButton::DrawClient(CDC *pdc, CRect *pRect, int x, int y)
{
	CPen pen;
	CBrush brush;
	CRect rectBorder(*pRect);
	rectBorder.right -= m_sizeShadow.cx;
	rectBorder.bottom -= m_sizeShadow.cy;
	CPen *OldPen;
	CBrush *OldBrush;	

	rectBorder.OffsetRect(x, y);

	brush.CreateSolidBrush(m_crColor);	
	pen.CreatePen(PS_SOLID, m_nBorderSize, m_crBorderColor);
	OldPen = pdc->SelectObject(&pen);
	OldBrush = pdc->SelectObject(&brush);
	pdc->Rectangle(&rectBorder);
	
	pdc->SelectObject(OldPen);
	pdc->SelectObject(OldBrush);

	pen.DeleteObject();
	brush.DeleteObject();

	//画图片

	int strx, stry;
	CString str;
	CSize sizeStr;
	GetWindowText(str);
	pdc->SetTextColor(m_crTextColor);
	pdc->SetBkMode(TRANSPARENT);

	CFont font, *pOldFont;
	LOGFONT logfont;
	if(m_bDefault)
	{
		
		pdc->GetCurrentFont()->GetLogFont(&logfont);
		logfont.lfWeight = FW_BOLD;
		font.CreateFontIndirect(&logfont);
		pOldFont = pdc->SelectObject(&font);
		
	}

	CSize sz;
	sz = pdc->GetOutputTextExtent(str);
	strx = (rectBorder.Width() - sz.cx) / 2 + rectBorder.left;
	stry = (rectBorder.Height() - sz.cy) / 2 + rectBorder.top;
	
	pdc->TextOut(strx, stry, str);

	if(m_bDefault)
	{
		pdc->SelectObject(pOldFont);
		font.DeleteObject();
	}

}

BOOL CShadowButton::SetDefaultButton(BOOL bState)
{
	m_bDefault = bState;
	Redraw();
	return bState;
}

void CShadowButton::SetDefaultFace()
{
	SetBorderSize(1);
	SetShadowSize(CSize(5, 5));
	SetColors(0, RGB(255, 0, 0), ::GetSysColor(COLOR_BTNSHADOW), RGB(0, 255, 0));	
	SetShadowOffset(5, 5);
}