C++ CTranButton

#pragma once
#include <atlimage.h>

typedef enum TRA_BTNSTATE{//按钮状态
	TRA_BTN_NOR,
	TRA_BTN_HOT,
	TRA_BTN_PRE,
	TRA_BTN_DIS
};

typedef struct _TRATRAPNGINFO_
{
	int nWidth;
	int nHeight;
	CImage*  pImg;
}TRAPNGINFO;


class CTranButton : public CButton
{
	// 标准构造函数
public:
	CTranButton();
	virtual ~CTranButton();

public:
	//作用:载入背景图
	void Load(UINT IDBkGroup,int width=0, int height=0, const CString& resourceType = _T("PNG"));
	//作用:自适应背景图
	void SetAutoSize(bool bAutoSize);
protected:
	//重绘
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
	//{{AFX_MSG(CTranButton)
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
private:
	TRAPNGINFO		m_btninfoNor;				//Normal时的图片
	TRAPNGINFO		m_btninfoHot;				//Hot时的图片
	TRAPNGINFO		m_btninfoPre;				//Press时的图片
	TRAPNGINFO		m_btninfoDis;				//Disable时的图片
	bool			m_bHot;						//是否为Hot
	bool			m_bPress;					//是否按下
	bool			m_bAutoSize;				//自动适应
private:
	//绘图
	void DrawBK(HDC dc, CImage* img,TRA_BTNSTATE btnstate);
	//写字
	void DrawBtnText(HDC dc, const CString& strText, int nMove, TRA_BTNSTATE btnstate);
	//改变按钮风格
	virtual void PreSubclassWindow();
};
// TranButton.cpp : 实现文件
//

#include "stdafx.h"
#include "TranButton.h"


CTranButton::CTranButton()
{
	m_btninfoNor.pImg = m_btninfoHot.pImg = m_btninfoPre.pImg = m_btninfoDis.pImg = NULL;//底图
	m_bHot = false;//是否为Hot
	m_bPress = false;//是否按下
	m_bAutoSize = true;//自适应
}

CTranButton::~CTranButton()
{
	if (m_btninfoNor.pImg != NULL)
	{
		delete m_btninfoNor.pImg;
		m_btninfoNor.pImg = NULL;
	}
	if (m_btninfoHot.pImg != NULL)
	{
		delete m_btninfoHot.pImg; 
		m_btninfoHot.pImg = NULL;
	}
	if (m_btninfoPre.pImg != NULL)
	{
		delete m_btninfoPre.pImg;
		m_btninfoPre.pImg = NULL;
	}
	if (m_btninfoDis.pImg!= NULL)
	{
		delete m_btninfoDis.pImg;
		m_btninfoDis.pImg = NULL;
	}
}


BEGIN_MESSAGE_MAP(CTranButton, CButton)
	//{{AFX_MSG_MAP(CTranButton)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


//作用:载入背景图片
void CTranButton::Load(UINT IDBkGroup,int width, int height, const CString& resourceType)
{
	CImage orgImg;

	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(IDBkGroup),resourceType);
	if (hRsrc == NULL)
		return;

	//讲资源加载到内存中
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (lpRsrc == NULL)
		return;

	//为流申请资源
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

	//加载流
	orgImg.Load(pstm);

	//释放资源
	GlobalUnlock(m_hMem);
	GlobalFree(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);

	if (resourceType == _T("PNG"))
	{
		if (orgImg.GetBPP() == 32)
		{
			//PNG透明
			for(int i = 0; i < orgImg.GetWidth(); i++)  
			{  
				for(int j = 0; j < orgImg.GetHeight(); j++)  
				{  
					unsigned char* pucColor = reinterpret_cast<unsigned char *>(orgImg.GetPixelAddress(i , j));  
					pucColor[0] = pucColor[0] * pucColor[3] / 255;  
					pucColor[1] = pucColor[1] * pucColor[3] / 255;  
					pucColor[2] = pucColor[2] * pucColor[3] / 255;  
				}  
			}
		}
	}

	if (width==0 && height==0)
	{
		width=orgImg.GetHeight();//方形
	}
	if (height==0)
	{
		height = orgImg.GetHeight();
	}

	m_btninfoNor.nWidth = width;
	m_btninfoNor.nHeight = height;
	m_btninfoHot.nWidth = width;
	m_btninfoHot.nHeight = height;
	m_btninfoPre.nWidth = width;
	m_btninfoPre.nHeight = height;
	m_btninfoDis.nWidth = width;
	m_btninfoDis.nHeight = height;
	CImage** imgs[]={&m_btninfoNor.pImg,&m_btninfoHot.pImg,&m_btninfoPre.pImg,&m_btninfoDis.pImg};
	int posX=0;
	for (int i=0;i<4 && posX<=(orgImg.GetWidth()-width);i++,posX+=width)
	{
		CImage* pMap=new CImage();
		if (*imgs[i] != NULL)
		{
			delete *imgs[i];
			*imgs[i] = NULL;
		}
		*imgs[i]=pMap;

		if (resourceType == _T("PNG"))
		{
			BOOL bStat = FALSE;
			if (orgImg.GetBPP() == 32)
			{
				bStat = pMap->CreateEx(width, height,orgImg.GetBPP(),BI_RGB,NULL, CImage::createAlphaChannel);  
			}else
			{
				bStat = pMap->CreateEx(width, height,orgImg.GetBPP(),BI_RGB,NULL);  
			}	
			ASSERT(bStat); 
		}else
		{
			BOOL bStat = pMap->CreateEx(width, height,orgImg.GetBPP(),BI_RGB,NULL);  
			ASSERT(bStat);  
		}

		CImageDC imageDC(*pMap);
		orgImg.Draw(imageDC,0,0,width,height,posX,0,width,height);
	}
}

//重绘
void CTranButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
	ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
	CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
	CRect rect = lpDrawItemStruct->rcItem;
	CString strText = _T("");
	GetWindowText(strText);

	//绘图
	if(lpDrawItemStruct->itemState & ODS_DISABLED)
	{
		DrawBK(*pDC, m_btninfoDis.pImg, TRA_BTN_DIS);
	}
	else if(lpDrawItemStruct->itemState & ODS_SELECTED
		||(m_bHot && m_bPress) )
	{
		DrawBK(*pDC, m_btninfoPre.pImg, TRA_BTN_PRE);
	}
	else if(m_bHot)
	{
		DrawBK(*pDC, m_btninfoHot.pImg, TRA_BTN_HOT);
	}
	else
	{
		DrawBK(*pDC, m_btninfoNor.pImg, TRA_BTN_NOR);
	}
	//写字
	CString strTemp(strText);
	strTemp.Remove(' ');
	if (!strTemp.IsEmpty())
	{
		if(lpDrawItemStruct->itemState & ODS_DISABLED)
		{
			DrawBtnText(*pDC,strText,0, TRA_BTN_DIS);
		}
		else if(lpDrawItemStruct->itemState & ODS_SELECTED
			||(m_bHot && m_bPress) )
		{
			DrawBtnText(*pDC, strText,1, TRA_BTN_PRE);
		}
		else if(m_bHot)
		{
			DrawBtnText(*pDC, strText,0, TRA_BTN_HOT);
		}
		else
		{
			DrawBtnText(*pDC, strText,0, TRA_BTN_NOR);
		}

	}
}

//写字
void CTranButton::DrawBtnText(HDC dc, const CString& strText, int nMove, TRA_BTNSTATE btnstate)
{
	CSize sizeText = CDC::FromHandle(dc)->GetTextExtent(strText);
	CRect rect;
	GetClientRect(&rect);

	rect.DeflateRect(nMove,nMove,0,0);
	CDC::FromHandle(dc)->SetBkMode(TRANSPARENT);

	if (btnstate == TRA_BTN_NOR)
	{
		CDC::FromHandle(dc)->SetTextColor(RGB(30,30,30));
	}else if (btnstate == TRA_BTN_HOT)
	{
		CDC::FromHandle(dc)->SetTextColor(RGB(30,30,30));
	}else if (btnstate == TRA_BTN_PRE)
	{
		CDC::FromHandle(dc)->SetTextColor(RGB(30,30,30));
	}else
	{
		CDC::FromHandle(dc)->SetTextColor(RGB(100,100,100));
	}
	CDC::FromHandle(dc)->DrawText(strText, rect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); 
}

//绘图
void CTranButton::DrawBK(HDC dc, CImage* img, TRA_BTNSTATE btnstate)
{
	if (!img)
		return;

	CRect rc;
	GetClientRect(&rc);
	CRect tmpRect;
	int nX = 0;
	int nY = 0;
	int nW = 0;
	int nH = 0;

	if (m_bAutoSize == true)
	{
		tmpRect.SetRect(0,0,rc.Width(), rc.Height());
		if (img)
			img->Draw(dc,tmpRect);
	}else
	{

		if(btnstate == TRA_BTN_NOR)
		{
			nW = m_btninfoNor.nWidth;
			nH = m_btninfoNor.nHeight;

		}else if (btnstate == TRA_BTN_HOT)
		{
			nW = m_btninfoHot.nWidth;
			nH = m_btninfoHot.nHeight;

		}else if (btnstate == TRA_BTN_PRE)
		{
			nW = m_btninfoPre.nWidth;
			nH = m_btninfoPre.nHeight;

		}else
		{
			nW = m_btninfoDis.nWidth;
			nH = m_btninfoDis.nHeight;
		}

		nX = (rc.Width()-nW)/2;
		nY = (rc.Height()-nH)/2;
		tmpRect.SetRect(nX,nY,nW+nX, nH+nY);
		if (img)
			img->Draw(dc,tmpRect);
	}
}


//鼠标移动
void CTranButton::OnMouseMove(UINT nFlags, CPoint point) 
{
	CRect rect;
	GetClientRect(rect);
	if(rect.PtInRect(point))	
	{
		if(!(nFlags & MK_LBUTTON))
			m_bPress = FALSE;
		if(GetCapture() != this)
		{			
			SetCapture();
		}
		if (m_bHot == TRUE)
		{
			//
		}else
		{
			m_bHot = TRUE;
			SetFocus();
			Invalidate();
			CRect rcTemp(rect);
			ClientToScreen(&rcTemp);
			CPoint pointTemp(rcTemp.left, rcTemp.top);
			::ScreenToClient(GetParent()->GetSafeHwnd(), &pointTemp);
			rcTemp.SetRect(pointTemp.x, pointTemp.y, pointTemp.x+rect.Width(), pointTemp.y+rect.Height());
			GetParent()->InvalidateRect(rcTemp, TRUE);		
		}
	}
	else
	{
		ReleaseCapture();
		m_bHot = FALSE;
		Invalidate();
		CRect rcTemp(rect);
		ClientToScreen(&rcTemp);
		CPoint pointTemp(rcTemp.left, rcTemp.top);
		::ScreenToClient(GetParent()->GetSafeHwnd(), &pointTemp);
		rcTemp.SetRect(pointTemp.x, pointTemp.y, pointTemp.x+rect.Width(), pointTemp.y+rect.Height());
		GetParent()->InvalidateRect(rcTemp, TRUE);
	}
	CButton::OnMouseMove(nFlags, point);
}

//鼠标抬起
void CTranButton::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if(m_bPress)
	{
		CRect rect;
		GetClientRect(rect);
		Invalidate();
		CRect rcTemp(rect);
		ClientToScreen(&rcTemp);
		CPoint pointTemp(rcTemp.left, rcTemp.top);
		::ScreenToClient(GetParent()->GetSafeHwnd(), &pointTemp);
		rcTemp.SetRect(pointTemp.x, pointTemp.y, pointTemp.x+rect.Width(), pointTemp.y+rect.Height());
		GetParent()->InvalidateRect(rcTemp, TRUE);
		m_bPress = FALSE;	
	}
	m_bHot = FALSE;
	CButton::OnLButtonUp(nFlags, point);
}

//鼠标落下
void CTranButton::OnLButtonDown(UINT nFlags, CPoint point) 
{
	/*CRect rect;
	GetClientRect(rect);
	CRect rcTemp(rect);
	ClientToScreen(&rcTemp);
	CPoint pointTemp(rcTemp.left, rcTemp.top);
	::ScreenToClient(GetParent()->GetSafeHwnd(), &pointTemp);
	rcTemp.SetRect(pointTemp.x, pointTemp.y, pointTemp.x+rect.Width(), pointTemp.y+rect.Height());
	GetParent()->InvalidateRect(rcTemp, TRUE);*/
	m_bPress = TRUE;	
	CButton::OnLButtonDown(nFlags, point);
}

//背景
BOOL CTranButton::OnEraseBkgnd(CDC* pDC) 
{
	if(GetButtonStyle() & BS_OWNERDRAW)
		return TRUE;
	return CButton::OnEraseBkgnd(pDC);
}

//自适应背景图
void CTranButton::SetAutoSize(bool bAutoSize)
{
	m_bAutoSize = bAutoSize;
}

//按钮风格
void CTranButton::PreSubclassWindow()
{
	ModifyStyle(0, BS_OWNERDRAW);//设置自绘
	CButton::PreSubclassWindow();
}

 

已标记关键词 清除标记
相关推荐
<p> <span style="color:#337FE5;"><strong>【为什么还需要学习C++?】</strong></span> </p> <p style="margin-left:0cm;"> 你是否接触很多语言,但从来没有了解过编程语言的本质? </p> <p style="margin-left:0cm;text-align:start;"> 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? </p> <p style="margin-left:0cm;text-align:start;"> 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? </p> <p style="margin-left:0cm;text-align:start;">   </p> <p style="margin-left:0cm;text-align:start;"> 那么C++就是你个人能力提升,职业之路进阶的不二之选。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;"> <strong><span style="color:#337FE5;">【课程特色】</span></strong> </p> <p style="margin-left:0cm;text-align:start;"> 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 </p> <p style="margin-left:0cm;text-align:start;"> 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 </p> <p style="margin-left:0cm;text-align:start;"> 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p class="ql-long-24357476"> <span style="color:#337FE5;"><strong>【学完后我将达到什么水平?】</strong></span> </p> <p class="ql-long-24357476"> 1.对C++的各个知识能够熟练配置、开发、部署; </p> <p class="ql-long-24357476"> 2.吊打一切关于C++的笔试面试题; </p> <p class="ql-long-24357476"> 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 </p> <p class="MsoNoSpacing" style="margin-left:18pt;"> <br /> </p> <div> <br /> </div> <p> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#337FE5;"><strong>【面向人群】</strong></span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">1.希望一站式快速入门的C++初学者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">2.希望快速学习 C++、掌握编程要义、修炼内功的开发者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">3.有志于挑战更高级的开发项目,成为资深开发的工程师。</span> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p> <br /> </p> <p> <span style="color:#337FE5;"><strong>【课程设计】</strong></span> </p> <p> 本课程包含3大模块 </p> <p> <strong>基础篇</strong><br /> 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 </p> <p> <br /> <strong>进阶篇</strong><br /> 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 </p> <p> <br /> <strong>提升篇:</strong><br /> 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。 </p> <p> <img src="https://img-bss.csdnimg.cn/202007091130239667.png" alt="" /> </p>
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页