1. 程式人生 > >MFC-自繪控制元件(checkbox篇)

MFC-自繪控制元件(checkbox篇)

示例圖

一、公共檔案

二、checkbox部分

標頭檔案

#pragma once
#include "Public.h"
//////////////////////////////////////////////////////////////////////////

#define DEF_TEXT_FRAME_COLOR			RGB(255,255,255)				//預設顏色
#define DEF_TEXT_COLOR					RGB(10,10,10)					//預設顏色
#define TOOLTIP_ID						100								//提示 ID

//////////////////////////////////////////////////////////////////////////
class CPngCheckBox : public CButton
{
public:
	CPngCheckBox();
	virtual ~CPngCheckBox();

public:
	BOOL GetChecked() { return m_bChecked; }
	void SetChecked(BOOL bChecked = TRUE) { m_bChecked = bChecked; Invalidate(FALSE); }

public:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

protected:
	virtual void PreSubclassWindow();

public:
	// 初始化
	void Init(UINT nBkImg, UINT nCkImg);
	void SetCheckBoxTextColor(COLORREF crTextColor);
	void SetBackColor(COLORREF crBack) { m_crBack = crBack; }
	//設定顏色
	bool SetTextColor(COLORREF crTextColor, COLORREF crTextFrameColor = DEF_TEXT_FRAME_COLOR, bool bShowFrame = false);
	//設定字型大小及型別
	void SetFontType(int fontSize, CString fontType);
	Image *ImageFromResource(HINSTANCE hInstance, UINT uImgID, LPCTSTR lpType);
	void DrawTextString(CDC * pDC, LPCTSTR pszString, COLORREF crText, COLORREF crFrame, LPRECT lpRect);
	void DrawTextString(CDC * pDC, LPCTSTR pszString, COLORREF crText, COLORREF crFrame, int nXPos, int nYPos);
	void PaintParent();

protected:
	BOOL								m_bChecked;
	Image*								m_ImageCheck;
	Image*								m_ImageBack;
	COLORREF							m_crBack;
	COLORREF							m_crTextColor;
	CFont								m_font;
	BOOL								m_bShowTextFrame;
	COLORREF							m_crTextFrameColor;
	BOOL								m_bSetBack;

	afx_msg BOOL OnClicked();
	afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);

	DECLARE_MESSAGE_MAP()
	DECLARE_DYNAMIC(CPngCheckBox)
};

原始檔
#include "stdafx.h"
#include "PngCheckBox.h"


IMPLEMENT_DYNAMIC(CPngCheckBox, CButton)

BEGIN_MESSAGE_MAP(CPngCheckBox, CButton)
	ON_WM_CREATE()
	ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
	ON_WM_ERASEBKGND()
	ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()


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

CPngCheckBox::CPngCheckBox()
{
	m_bChecked		= FALSE;
	m_crTextColor	= RGB(0, 0, 0);
	m_crBack		= RGB(255, 255, 255);
	m_bSetBack		= FALSE;
	m_bShowTextFrame = FALSE;
	m_crTextColor		= DEF_TEXT_COLOR;
	m_crTextFrameColor	= DEF_TEXT_FRAME_COLOR;
}

CPngCheckBox::~CPngCheckBox()
{
}


void CPngCheckBox::PreSubclassWindow()
{
	ModifyStyle(0, BS_OWNERDRAW);
	CButton::PreSubclassWindow();
}

void CPngCheckBox::Init(UINT nBkImg, UINT nCkImg) {
	m_ImageCheck = ImageFromResource(AfxGetResourceHandle(), nCkImg, L"PNG");
	m_ImageBack	 = ImageFromResource(AfxGetResourceHandle(), nBkImg, L"PNG");

	if (m_ImageBack != NULL) {
		m_bSetBack = TRUE;
	}

	CRect rcButton;
	rcButton = CRect(0, 0, m_ImageCheck->GetWidth() / 4, m_ImageCheck->GetHeight());
	
	SetWindowPos(NULL, 0, 0, rcButton.Width(), rcButton.Height(), SWP_NOACTIVATE | SWP_NOMOVE);
}
HBRUSH CPngCheckBox::CtlColor(CDC* pDC, UINT nCtlColor)
{
	pDC->SetBkMode(TRANSPARENT);
	return (HBRUSH)GetStockObject(NULL_BRUSH);
}
void CPngCheckBox::SetFontType(int fontSize, CString fontType) {
	LOGFONT lf;
	memset(&lf, 0, sizeof(LOGFONT));
	lf.lfHeight = fontSize;
	_tcsncpy_s(lf.lfFaceName, LF_FACESIZE, fontType, fontType.GetLength());
	VERIFY(m_font.CreateFontIndirect(&lf));
}
void CPngCheckBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	CDC dc;
	dc.Attach(lpDIS->hDC);
	CRect rcItem(lpDIS->rcItem);

	if (m_bSetBack)
	{
		Graphics graph(lpDIS->hDC);
		graph.DrawImage(m_ImageBack, RectF(0, 0, rcItem.Width(), rcItem.Height()), rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height(), UnitPixel);
		graph.ReleaseHDC(lpDIS->hDC);
	}
	if (m_ImageCheck != NULL)
	{
		CRect rcButton;
		int imgWidth = m_ImageCheck->GetWidth() / 4;
		int imgHeight = m_ImageCheck->GetHeight();
		if (m_bChecked && IsWindowEnabled())
			rcButton = CRect(0, 0, imgWidth, imgHeight);
		else if (m_bChecked && !IsWindowEnabled())
			rcButton = CRect(2* imgWidth, 0, 3*imgWidth, imgHeight);
		else if (!m_bChecked && IsWindowEnabled())
			rcButton = CRect(imgWidth, 0, 2*imgWidth, imgHeight);
		else
			rcButton = CRect(3* imgWidth, 0, 4*imgWidth, imgHeight);
		
		Graphics graph(dc.GetSafeHdc());
		graph.DrawImage(m_ImageCheck, 0, 0, rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), UnitPixel);
		graph.ReleaseHDC(dc.GetSafeHdc());
		//繪畫字型
		CString szText;
		GetWindowText(szText);
		dc.SetBkMode(TRANSPARENT);
		CFont* oldFont = dc.SelectObject(m_font.GetSafeHandle() ? &m_font : GetFont());

		DrawTextString(&dc, szText, m_crTextColor, m_crTextFrameColor, imgWidth + 4, 0);
		dc.SelectObject(oldFont);
	}
	dc.Detach();
}

void CPngCheckBox::SetCheckBoxTextColor(COLORREF crTextColor)
{
	m_crTextColor = crTextColor;
}
//設定顏色
bool CPngCheckBox::SetTextColor(COLORREF crTextColor, COLORREF crTextFrameColor, bool bShowFrame)
{
	m_crTextColor = crTextColor;
	m_bShowTextFrame = bShowFrame;
	m_crTextFrameColor = crTextFrameColor;

	if (GetSafeHwnd()) Invalidate(FALSE);
	return true;
}
Image * CPngCheckBox::ImageFromResource(HINSTANCE hInstance, UINT uImgID, LPCTSTR lpType)
{
	HRSRC hResInfo = ::FindResource(hInstance, MAKEINTRESOURCE(uImgID), lpType);
	if (hResInfo == NULL)
		return NULL; //fail  
	DWORD dwSize;
	dwSize = SizeofResource(hInstance, hResInfo); //get resource size(bytes)   
	HGLOBAL hResData;
	hResData = ::LoadResource(hInstance, hResInfo);
	if (hResData == NULL)
		return NULL; //fail  
	HGLOBAL hMem;
	hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
	if (hMem == NULL) {
		::FreeResource(hResData);
		return NULL;
	}
	LPVOID lpResData, lpMem;
	lpResData = ::LockResource(hResData);
	lpMem = ::GlobalLock(hMem);
	::CopyMemory(lpMem, lpResData, dwSize); //copy memory  
	::GlobalUnlock(hMem);
	::FreeResource(hResData); //free memory  

	IStream *pStream;
	HRESULT hr;
	hr = ::CreateStreamOnHGlobal(hMem, TRUE, &pStream);//create stream object  
	Image *pImage = NULL;
	if (SUCCEEDED(hr)) {
		pImage = Image::FromStream(pStream);//get GDI+ pointer  
		pStream->Release();
	}
	::GlobalFree(hMem);
	return pImage;
}

BOOL CPngCheckBox::OnClicked()
{
	if (!m_bChecked)
		m_bChecked = TRUE;
	else
		m_bChecked = FALSE;

	PaintParent();
	return FALSE;
}

BOOL CPngCheckBox::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}
void CPngCheckBox::PaintParent()
{
	CRect   rect;
	GetWindowRect(&rect);
	GetParent()->ScreenToClient(&rect);
	GetParent()->InvalidateRect(&rect);
}
//藝術字體
void CPngCheckBox::DrawTextString(CDC * pDC, LPCTSTR pszString, COLORREF crText, COLORREF crFrame, LPRECT lpRect)
{
	//變數定義
	int nStringLength = lstrlen(pszString);
	int nXExcursion[8] = { 1,1,1,0,-1,-1,-1,0 };
	int nYExcursion[8] = { -1,0,1,1,1,0,-1,-1 };

	CRect rcDraw;
	if (m_bShowTextFrame)
	{
		//繪畫邊框
		pDC->SetTextColor(crFrame);
		for (int i = 0; i < sizeof(nXExcursion) / sizeof(nXExcursion[0]); ++i)
		{
			rcDraw.CopyRect(lpRect);
			rcDraw.OffsetRect(nXExcursion[i], nYExcursion[i]);
			pDC->DrawText(pszString, nStringLength, &rcDraw, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
		}
	}
	
	//繪畫字型
	rcDraw.CopyRect(lpRect);
	pDC->SetTextColor(crText);
	pDC->DrawText(pszString, nStringLength, &rcDraw, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
	return;
}

//藝術字體
void CPngCheckBox::DrawTextString(CDC * pDC, LPCTSTR pszString, COLORREF crText, COLORREF crFrame, int nXPos, int nYPos)
{
	if (nYPos == 0) {
		LOGFONT lf;
		if (m_font.GetSafeHandle()) {
			m_font.GetLogFont(&lf);
		}
		else {
			GetFont()->GetLogFont(&lf);
		}
		nYPos = (m_ImageCheck->GetHeight()-abs(lf.lfHeight))/2;
	}
	//變數定義
	int nStringLength = lstrlen(pszString);
	int nXExcursion[8] = { 1,1,1,0,-1,-1,-1,0 };
	int nYExcursion[8] = { -1,0,1,1,1,0,-1,-1 };

	if (m_bShowTextFrame)
	{
		//繪畫邊框
		pDC->SetTextColor(crFrame);
		for (int i = 0; i < sizeof(nXExcursion) / sizeof(nXExcursion[0]); i++)
		{
			pDC->TextOut(nXPos + nXExcursion[i], nYPos + nYExcursion[i], pszString, nStringLength);
		}
	}
	//繪畫字型
	pDC->SetTextColor(crText);
	pDC->TextOut(nXPos, nYPos, pszString, nStringLength);
	return;
}

呼叫方法
m_checkb1.Init(IDB_PNG_CRBACK, IDB_PNG_CHECK);
	m_checkb1.SetBackColor(RGB(0, 200, 200));
	m_checkb1.SetFontType(16, L"黑體");
	m_checkb1.SetTextColor(RGB(0, 200, 0), RGB(100, 100, 0), TRUE);