VC++利用GDI+实现自定义控件——CheckBoxEx

Home / C++ MrLee 2015-8-4 2562

基本上实现和CButtonEx差不多,稍微改进了一下绘制的算法。不会有重影。
CheckBoxEx.h
#pragma once
#include "atltypes.h"

// CCheckBoxEx
class CCheckBoxEx : public CButton
{
	DECLARE_DYNAMIC(CCheckBoxEx)
public:
	char szTitle[MAX_PATH];
	UINT m_frameCount;
	Image *m_pImage;
	Image* m_pTemp;
	CSize m_sizeImage;
	enumButtonState m_buttonState;
	BOOL m_bCheck;
	CCheckBoxEx();
	virtual ~CCheckBoxEx();
	BOOL GetCheck();
	void SetCheck(BOOL bCheck, BOOL bRepaint=TRUE);
protected:
	DECLARE_MESSAGE_MAP()
	virtual void PreSubclassWindow();
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	CRect m_rc;
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	void DrawContent(CDC& MemDC);
	void SetBitmap(UINT nResourceID=IDB_PNG_CHECKBOX, UINT nFrameCount=6);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMouseLeave();
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
protected:
	afx_msg LRESULT OnBmGetcheck(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnBmSetcheck(WPARAM wParam, LPARAM lParam);
public:
	afx_msg void OnBnClicked();
};

CheckBoxEx.cpp
// CheckBoxEx.cpp : 实现文件
//
#include "stdafx.h"
#include "QQRobot.h"
#include "CheckBoxEx.h"

// CCheckBoxEx
IMPLEMENT_DYNAMIC(CCheckBoxEx, CButton)
CCheckBoxEx::CCheckBoxEx()
: m_pTemp(NULL)
{
	m_buttonState = bsNormal;
	m_pImage = NULL;
}
CCheckBoxEx::~CCheckBoxEx()
{
}

BEGIN_MESSAGE_MAP(CCheckBoxEx, CButton)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSELEAVE()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(BM_GETCHECK, &CCheckBoxEx::OnBmGetcheck)
	ON_MESSAGE(BM_SETCHECK, &CCheckBoxEx::OnBmSetcheck)
	ON_CONTROL_REFLECT(BN_CLICKED, &CCheckBoxEx::OnBnClicked)
END_MESSAGE_MAP()

// CCheckBoxEx 消息处理程序


void CCheckBoxEx::PreSubclassWindow()
{
	// TODO: 在此添加专用代码和/或调用基类
	SetButtonStyle(GetButtonStyle()|BS_OWNERDRAW);//修改为自绘模式
	GetClientRect(&m_rc);
	GetWindowTextA(szTitle,sizeof(szTitle));//复制内容
	SetBitmap();
	CButton::PreSubclassWindow();
}

void CCheckBoxEx::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
{
	// TODO:  添加您的代码以绘制指定项
	CDC *pDc = GetDC();
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CButton::OnPaint()
	CRect rcClient;
	GetClientRect(&rcClient);
	CDC MemDC;
	MemDC.CreateCompatibleDC(pDc);
	MemDC.SetBkMode(TRANSPARENT);//不设置透明文字会有背景
	CBitmap memBmp;
	memBmp.CreateCompatibleBitmap(pDc, rcClient.Width(), rcClient.Height());
	CBitmap *pOldmap =  MemDC.SelectObject(&memBmp);
	//先填充一下原先的背景
	//MemDC.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), pDc, 0, 0, SRCCOPY);
	//绘制内容
	DrawContent(MemDC);
	//复制到原来的CDC
	pDc->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY);
	//MemDC.SelectObject(pOldmap);
	//旧图应该是不存在的,直接删除
	pOldmap->DeleteObject();
	MemDC.DeleteDC();
	memBmp.DeleteObject();
	ReleaseDC(pDc);
}

BOOL CCheckBoxEx::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CDC MemDC;
	CBitmap memBmp;
	MemDC.CreateCompatibleDC(pDC);
	memBmp.CreateCompatibleBitmap(pDC, m_rc.Width(), m_rc.Height());
	CBitmap *pOldmap =  MemDC.SelectObject(&memBmp);
	//先填充一下原先的背景
	MemDC.BitBlt(m_rc.left, m_rc.top, m_rc.Width(), m_rc.Height(), pDC, 0, 0, SRCCOPY);
	//绘制内容
	if(m_pTemp == NULL)
		BitmapToImage(&memBmp,m_pTemp);
	//旧图应该是黑的无用,直接删除
	pOldmap->DeleteObject();
	MemDC.DeleteDC();
	memBmp.DeleteObject();
	ReleaseDC(&MemDC);
	return TRUE;
}
void CCheckBoxEx::DrawContent(CDC& MemDC)
{
	Graphics g(MemDC);
	g.DrawImage(m_pTemp,0,0);
	if((UINT)m_buttonState < m_frameCount)
		g.DrawImage(m_pImage, RectF((REAL)m_rc.left,(REAL)m_rc.top,(REAL)m_sizeImage.cx,(REAL)m_sizeImage.cy),
			m_buttonState * (REAL)m_sizeImage.cx, 0, (REAL)m_sizeImage.cx, (REAL)m_sizeImage.cy, UnitPixel);
	COLORREF clrOld = MemDC.SetTextColor(RGB(0, 28, 48));
	CFont *pOldFont = MemDC.SelectObject(GetFont());
	CRect temp_rc = m_rc;
	temp_rc.left += 6;
	temp_rc.top -= 2;
	MemDC.DrawText(szTitle, &temp_rc, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_WORD_ELLIPSIS);
	MemDC.SelectObject(pOldFont);
	MemDC.SetTextColor(clrOld);
}

void CCheckBoxEx::SetBitmap(UINT nResourceID, UINT nFrameCount)
{
	ImageFromID(nResourceID,m_pImage);
	this->m_frameCount = nFrameCount;
	m_sizeImage.SetSize(m_pImage->GetWidth() / m_frameCount, m_pImage->GetHeight());
}

void CCheckBoxEx::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CWnd::OnLButtonUp(nFlags, point);
	if (m_buttonState == bsDown)
	{
		if(GetCheck() == BST_CHECKED)
			m_buttonState = bsHoverDown;
		else
			m_buttonState = bsHover;
		Invalidate();
	}
}

void CCheckBoxEx::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CWnd::OnLButtonDown(nFlags, point);
	if(GetCheck() == BST_CHECKED)
		m_buttonState = bsHoverDown;
	else
		m_buttonState = bsHover;
	Invalidate();
}

void CCheckBoxEx::OnMouseLeave()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CButton::OnMouseLeave();
	if(m_bCheck)
		m_buttonState = bsDown;
	else
		m_buttonState = bsNormal;
	Invalidate();
}

void CCheckBoxEx::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CButton::OnMouseMove(nFlags, point);
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(TRACKMOUSEEVENT);
	tme.hwndTrack = this->m_hWnd;
	tme.dwFlags = TME_LEAVE | TME_HOVER;
	_TrackMouseEvent(&tme);
	if(m_bCheck)
		m_buttonState = bsHoverDown;
	else
		m_buttonState = bsHover;
	Invalidate();
}
afx_msg LRESULT CCheckBoxEx::OnBmGetcheck(WPARAM wParam, LPARAM lParam)
{
	return GetCheck();
}

afx_msg LRESULT CCheckBoxEx::OnBmSetcheck(WPARAM wParam, LPARAM lParam)
{
	if(wParam == BST_CHECKED)
		SetCheck(BST_CHECKED);
	else
		SetCheck(BST_UNCHECKED);
	return 0;
}
BOOL CCheckBoxEx::GetCheck()
{
	return m_bCheck;
}
void CCheckBoxEx::SetCheck(BOOL bCheck, BOOL bRepaint/* =TRUE */)
{
	this->m_bCheck = bCheck;
	if(m_bCheck)
		m_buttonState = bsDown;
	else
		m_buttonState = bsNormal;
	if(bRepaint)
		Invalidate();
}
void CCheckBoxEx::OnBnClicked()
{
	// TODO: 在此添加控件通知处理程序代码
	this->m_bCheck = !this->m_bCheck;
}

本文链接:https://www.it72.com/3973.htm

推荐阅读
最新回复 (0)
返回