VC++实现切换按钮

VC++实现切换按钮

有时候要实现两个选项的切换,常规做法1是放两个Radio按钮控件,并设置这两个按钮为一组。2是放一个Check按钮控件。但感觉都不是那么理想和直观。有没有更好的实现方式呢?下面将给你介绍一种我自绘的控件,我把它命名为“切换控件”(SwitchButton)。实现的效果如下图实现,给你一个多的选择,以供参考。

VC++实现切换按钮_第1张图片

下面是实现源码:

/////////////////////////////// 说明文件/////////////////////////////////////////////
//文件:SwitchBtn.h                                                                //
//功能:切换按钮类,实现两个选项一个按钮实现,自绘实现。                          //
//作者:cbNotes(http://blog.csdn.net/cbnotes)                                    //
//版本:1.0.0                                                                      //
//时间:2013-01-23                                                                 //
//备注:该控件类免费开源,欢迎大家使用和改进。但请保持该说明文件的完整和原创性     //
/////////////////////////////////////////////////////////////////////////////////////

#pragma once

// CSwitchBtn

class CSwitchBtn : public CWnd
{
	DECLARE_DYNAMIC(CSwitchBtn)

public:
	CSwitchBtn();
	virtual ~CSwitchBtn();
private:
	int m_nID;          //控件ID
	CWnd *m_pParentWnd; //父窗口指针
	BOOL m_bAnimation;  //是否动画标记
	BOOL m_bLeft;       //是否选择左边标记
	CString m_szLeftText,m_szRightText;
	COLORREF m_clrNorText,m_clrHotText;//文字颜色
	COLORREF m_clrNorBG,m_clrHotBG;    //背景颜色
	COLORREF m_clrNorBorder,m_clrHotBorder;//边框颜色
	int      m_ngap;//间隔

protected:
	DECLARE_MESSAGE_MAP()
public:
	//自绘按钮
	afx_msg void OnPaint();
	//按钮按钮释放消息处理,主要是发送消息
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	//设置按钮上的文字
	void SetText(CString szLeft,CString szRight);
	// 选择哪个选项
	void SetSelect(bool bLeft);
	// 设置背景色
	void SetBKColor(COLORREF clrBackGround);
	// 设置滑块的颜色
	void SetSliderColor(COLORREF clrSider);
	// 设置文本的颜色
	void SetTextColor(COLORREF clrText);
	//设置选择文本的颜色
	void SetHotTextColor(COLORREF clrHotText);
	//设置外边框的颜色
	void SetBorderColor(COLORREF clrBorder);
	//设置滑块边框的颜色
	void SetSliderBorderColor(COLORREF clrSliderBorder);
	// 动态创建按钮
	bool CreateButton(CRect rt,CWnd *pParentWnd,int nID);
	// 初始化按钮
	void InitButton(CString szLeft,CString szRight,bool bLeft = true);
};

/////////////////////////////// 说明文件/////////////////////////////////////////////
//文件:SwitchBtn.cpp                                                                //
//功能:切换按钮类,实现两个选项一个按钮实现,自绘实现。                          //
//作者:cbNotes(http://blog.csdn.net/cbnotes)                                    //
//版本:1.0.0                                                                      //
//时间:2013-01-23                                                                 //
//备注:该控件类免费开源,欢迎大家使用和改进。但请保持该说明文件的完整和原创性     //
/////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SwitchBtnTest.h"
#include "SwitchBtn.h"


// CSwitchBtn

IMPLEMENT_DYNAMIC(CSwitchBtn, CWnd)

CSwitchBtn::CSwitchBtn()
{
	m_pParentWnd = NULL;
	m_bAnimation = FALSE;
	m_bLeft = TRUE;
	m_szLeftText = "左边";
	m_szRightText = "右边";

	m_clrNorText = RGB(0,0,0);//文字颜色
	m_clrHotText = RGB(255,255,255);
	m_clrNorBG = RGB(200,200,200);//背景颜色
    m_clrHotBG = RGB(254,184,66);
	m_clrNorBorder = RGB(128,128,128);//边框颜色
	m_clrHotBorder = RGB(0,0,255);
	m_ngap =10;//间隔
}

CSwitchBtn::~CSwitchBtn()
{
}


BEGIN_MESSAGE_MAP(CSwitchBtn, CWnd)
	ON_WM_PAINT()
	ON_WM_LBUTTONUP()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()



// CSwitchBtn 消息处理程序


// 初始化按钮
void CSwitchBtn::InitButton(CString szLeft,CString szRight,bool bLeft)
{
	m_szLeftText = szLeft;
	m_szRightText = szRight;
	m_bLeft = bLeft;
}

// 动态创建按钮
bool CSwitchBtn::CreateButton(CRect rt,CWnd *pParentWnd,int nID)
{
	if (!pParentWnd)
	{
		return false;
	}
	m_pParentWnd = pParentWnd;
	m_nID = nID;//用于消息的标识
	return Create(NULL,NULL,WS_CHILD|WS_VISIBLE,rt,pParentWnd,nID);
}

void CSwitchBtn::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CWnd::OnPaint()
	CRect winrt;
	GetClientRect(&winrt);
	CDC memDC;
	memDC.CreateCompatibleDC(&dc);
	CBitmap bmp;
	bmp.CreateCompatibleBitmap(&dc,winrt.Width(),winrt.Height());
	memDC.SelectObject(&bmp);
	memDC.FillSolidRect(winrt,RGB(240,240,240));//
	//背景
	CBrush norbgbrush,hotbgbrush;//
	norbgbrush.CreateSolidBrush(m_clrNorBG);
	hotbgbrush.CreateSolidBrush(m_clrHotBG);
	CBrush* pOldBrush = memDC.SelectObject(&norbgbrush);
	//边框
	CPen norborderpen,hotborderpen;
	norborderpen.CreatePen(PS_SOLID, 2, m_clrNorBorder);
	hotborderpen.CreatePen(PS_SOLID, 1, m_clrHotBorder);
	CPen* pOldPen = memDC.SelectObject(&norborderpen);
	CFont font;
	font.CreatePointFont(160,"宋体");
	memDC.SelectObject(&font);
	memDC.SetBkMode(TRANSPARENT);
	CRect leftrt,rightrt;
	leftrt = rightrt = winrt;
	leftrt.right=leftrt.left+winrt.Width()/2-m_ngap/2;
	leftrt.DeflateRect(3,3,2,2);

	rightrt.left=rightrt.right-winrt.Width()/2+m_ngap/2;
	rightrt.DeflateRect(3,3,2,2);
	//
	CRect rt = winrt;
	rt.DeflateRect(2,2,0,0);
	if(!m_bAnimation)
	{
		//画背景
		memDC.RoundRect(&rt,CPoint(17,17));
		//焦点背景
		pOldBrush = memDC.SelectObject(&hotbgbrush);
		pOldPen = memDC.SelectObject(&hotborderpen);
		if (m_bLeft)
		{//
			memDC.RoundRect(&leftrt,CPoint(17,17));
		} 
		else
		{
			memDC.RoundRect(&rightrt,CPoint(17,17));
		}
		//写文字
		if (m_bLeft)
		{   //左边文字
			memDC.SetTextColor(m_clrHotText);
			memDC.DrawText(m_szLeftText,m_szLeftText.GetLength(),&leftrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
			//右边文字
			memDC.SetTextColor(m_clrNorText);
			memDC.DrawText(m_szRightText,m_szRightText.GetLength(),&rightrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
		}
		else
		{
			memDC.SetTextColor(m_clrNorText);
			memDC.DrawText(m_szLeftText,m_szLeftText.GetLength(),&leftrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);

			memDC.SetTextColor(m_clrHotText);
			memDC.DrawText(m_szRightText,m_szRightText.GetLength(),&rightrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
		}
		dc.BitBlt(0,0,winrt.Width(),winrt.Height(),&memDC,0,0,SRCCOPY);
	}
	else
	{//动画切换
		CRect rr= winrt;
		rr.DeflateRect(2,2,0,0);
		if (m_bLeft)
		{//往左
			rt = rightrt;
			while(rt.left>winrt.left+3)
			{
				pOldBrush =memDC.SelectObject(&norbgbrush);
				pOldPen = memDC.SelectObject(&norborderpen);
				memDC.RoundRect(&rr,CPoint(17,17));
				rt.OffsetRect(CPoint(-5,0));
				pOldPen = memDC.SelectObject(&hotborderpen);
				pOldBrush = memDC.SelectObject(&hotbgbrush);
				memDC.RoundRect(&rt,CPoint(17,17));
				//写文字
			    //左边文字
				memDC.SetTextColor(m_clrHotText);
				memDC.DrawText(m_szLeftText,m_szLeftText.GetLength(),&leftrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
				//右边文字
				memDC.SetTextColor(m_clrNorText);
				memDC.DrawText(m_szRightText,m_szRightText.GetLength(),&rightrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
				dc.BitBlt(0,0,winrt.Width(),winrt.Height(),&memDC,0,0,SRCCOPY);
				Sleep(10);
			}
		} 
		else
		{//往右
			rt = leftrt;
			while(rt.right<winrt.right-3)
			{	
				pOldBrush =memDC.SelectObject(&norbgbrush);
			    pOldPen = memDC.SelectObject(&norborderpen);
				memDC.RoundRect(&rr,CPoint(17,17));
				rt.OffsetRect(CPoint(5,0));
				pOldPen = memDC.SelectObject(&hotborderpen);
				pOldBrush = memDC.SelectObject(&hotbgbrush);
				memDC.RoundRect(&rt,CPoint(17,17));
				//写文字
				memDC.SetTextColor(m_clrNorText);
				memDC.DrawText(m_szLeftText,m_szLeftText.GetLength(),&leftrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
   
				memDC.SetTextColor(m_clrHotText);
				memDC.DrawText(m_szRightText,m_szRightText.GetLength(),&rightrt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
				dc.BitBlt(0,0,winrt.Width(),winrt.Height(),&memDC,0,0,SRCCOPY);
				Sleep(10);
			}
		}
		m_bAnimation = FALSE;
	}
	bmp.DeleteObject();
	norbgbrush.DeleteObject();
	hotbgbrush.DeleteObject();
	norborderpen.DeleteObject();
	hotborderpen.DeleteObject();
    font.DeleteObject();
	memDC.DeleteDC();
}

void CSwitchBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect rt;
	GetClientRect(&rt);
	CRect leftrt,rightrt;
	leftrt = rightrt =rt;
	leftrt.right=leftrt.left+rt.Width()/2-m_ngap/2;
	leftrt.DeflateRect(2,2,2,2);

	rightrt.left=rightrt.right-rt.Width()/2+m_ngap/2;
	rightrt.DeflateRect(2,2,2,2);

	if (m_bLeft)
	{
		if (rightrt.PtInRect(point))
		{
			m_bLeft = FALSE;
			m_bAnimation = TRUE;
			m_pParentWnd->SendMessage(m_nID,1,0);
		    Invalidate();
		}
	} 
	else
	{
		if (leftrt.PtInRect(point))
		{
			m_bLeft = TRUE;
			m_bAnimation = TRUE;
			m_pParentWnd->SendMessage(m_nID,0,0);
			Invalidate();
		}
	}
	CWnd::OnLButtonUp(nFlags, point);
}

BOOL CSwitchBtn::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
    return FALSE;
	//return CWnd::OnEraseBkgnd(pDC);
}

void CSwitchBtn::SetText(CString szLeft,CString szRight)
{
	m_szLeftText = szLeft;
	m_szRightText = szRight;
}

// 选择哪个选项
void CSwitchBtn::SetSelect(bool bLeft)
{
	m_bLeft = bLeft;
}

// 设置背景色
void CSwitchBtn::SetBKColor(COLORREF clrBackGround)
{
	m_clrNorBG = clrBackGround;
}
// 设置滑块的颜色
void CSwitchBtn::SetSliderColor(COLORREF clrSider)
{
	m_clrHotBG = clrSider;
}

// 设置文本的颜色
void CSwitchBtn::SetTextColor(COLORREF clrText)
{
	m_clrNorText = clrText;
}

//设置选择文本的颜色
void CSwitchBtn::SetHotTextColor(COLORREF clrHotText)
{
	m_clrHotText = clrHotText;
}

//设置外边框的颜色
void CSwitchBtn::SetBorderColor(COLORREF clrBorder)
{
	m_clrNorBorder = clrBorder;
}

//设置滑块边框的颜色
void CSwitchBtn::SetSliderBorderColor(COLORREF clrSliderBorder)
{
	m_clrHotBorder = clrSliderBorder;
}

测试代码如下:

CSwitchBtn m_btn1;
CSwitchBtn m_btn2;
 //按钮1
m_btn1.CreateButton(CRect(20,10,200,50),this,WM_SWITCHBTN1);
m_btn1.SetText("打开","关闭");
 //按钮2
m_btn2.CreateButton(CRect(20,65,200,105),this,WM_SWITCHBTN2);
m_btn2.InitButton("选项一","选项二",false);
//设置颜色
m_btn2.SetBKColor(RGB(111,222,20));
m_btn2.SetSliderColor(RGB(250,0,0));
m_btn2.SetBorderColor(RGB(0,250,250));
m_btn2.SetSliderBorderColor(RGB(200,200,200));
m_btn2.SetTextColor(RGB(100,100,100));
m_btn2.SetHotTextColor(RGB(255,2550,0));

控件源码(包括测试源码)打包下载地址:http://download.csdn.net/detail/cbnotes/5022058

欢迎大家多多批评指正,有任何意见和改进请留言,谢谢。

===========================================

转载请标明出处,谢谢。http://blog.csdn.net/cbNotes

===========================================

你可能感兴趣的:(按钮,button,button,VC,VC,切换,自绘)