自写PNGButton类,实现透明按钮

主要通过GDIPlus的Image类来加载图片资源,使之支持bmp以外的图片。

GDIPlus的初始化方式网上都是用的如下方法:

1、在stdafx.h中添加以下声明:
//引入GDI+头文件 
#include <GdiPlus.h> 
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib" )

2、在应用程序类初始化的地方(最好是InitInstance中)添加以下代码:
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
并在相应的头文件中声明:
GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;

3、改写应用程序类的ExitInstance函数:
int CXXXApp::ExitInstance() 

GdiplusShutdown(m_gdiplusToken); 
return CWinApp::ExitInstance(); 

说明:VS2005及以上版本不需要添加GdiPlus.lib,否则手动添加

初始化的地方并不固定,下面是MSDN的例子:

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;

INT main()
{
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR gdiplusToken;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

   Image* image = new Image(L"FakePhoto.jpg");
   printf("The width of the image is %u.\n", image->GetWidth());
   printf("The height of the image is %u.\n", image->GetHeight()); 

   delete image;
   GdiplusShutdown(gdiplusToken);
   return 0;
}


下面是主要内容:建立PNGButton类的实现方法一:
该类继承与Cwnd类,首先是重载Create函数,获取图片资源,并建立窗口

下面是通过FromStream的方式获取资源,也可通过FromFile获取(详见另一种方法)

static bool ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * &pImg)
{
	bool ret = false;
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // sTR:type
	if (!hRsrc)
		return FALSE;
	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	//HGLOBAL lpRsrc = LoadResource(hInst, hRsrc);
	if (!lpRsrc)
		return FALSE;
	LPVOID pBuffer = LockResource(lpRsrc);
	if ( !pBuffer )
		return false;
	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	//HGLOBAL m_hMem = GlobalAlloc(GMEM_ZEROINIT, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	if ( S_OK == CreateStreamOnHGlobal(m_hMem,FALSE,&pstm) )
	{
		// load from stream
		pImg = Gdiplus::Image::FromStream(pstm);
		if ( pImg )
			ret = true;
	}
	
	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);
	//GlobalFree()
	return ret;
}

然后建立该控件:

BOOL PNGButton::Create(UINT x,UINT y, CWnd* pParentWnd, UINT nID, \
					   UINT PngID,UINT PngID_hOver, UINT PngID_hDisable, UINT PngID_hClick, CCreateContext* pContext)
{
	LPCTSTR lpszClassName=AfxRegisterWndClass( CS_HREDRAW|CS_VREDRAW ,  \
		AfxGetApp()->LoadStandardCursor(IDC_ARROW), (HBRUSH)GetStockObject(TRANSPARENT), NULL);
	ImageFromIDResource(PngID,_T("PNG"),this->m_bg);
	ImageFromIDResource(PngID_hOver,L"PNG",this->m_hoverBg);
	if ( 0 == PngID_hClick)
		ImageFromIDResource(PngID,L"PNG", this->m_clickBg);
	else
		ImageFromIDResource(PngID_hClick,L"PNG", this->m_clickBg);
	ImageFromIDResource(PngID_hDisable,L"PNG" ,this->m_DisableBg);
	if ( !m_bg || !m_hoverBg || !m_clickBg ||!m_DisableBg)
	{
		return false;
	}
	m_Width=m_bg->GetWidth();
	m_Height=m_bg->GetHeight(); 
	BOOL OK=CWnd::Create(NULL,NULL,WS_CHILDWINDOW|WS_VISIBLE, CRect(x,y,x+m_Width,m_Height+y),pParentWnd, nID, pContext);
	ModifyStyleEx(0, WS_EX_TRANSPARENT);// WS_EX_LAYERED||WS_EX_TRANSPARENT  
	//SetLayeredWindowAttributes(TRANSPARENT, (byte)(255 * 1), LWA_COLORKEY); //LWA_ALPHA LWA_COLORKEY
	
	return OK;
}


然后只需重载Onpaint,根据不同的需要,画不同的图片即可

void PNGButton::OnPaint()
{  
	CPaintDC dc(this);    
	Graphics g(dc.m_hDC);   
	
	Bitmap bmp(this->m_Width,this->m_Height);
	Graphics* gBuf=Graphics::FromImage(&bmp);


	gBuf->DrawImage(this->m_bg,0,0); 
	//不同状态的显示 
	if ( !m_bIsEnable )
	{
		gBuf->DrawImage(m_DisableBg,0,0,0,0,m_Width,m_Height,Gdiplus::UnitPixel); 
		TRACE(L"m_bIsDisable\r\n"); 
	}
	else
	{
		if( m_bIsMouseHover )
		{
			gBuf->DrawImage(m_hoverBg,0,0,0,0,m_Width,m_Height,Gdiplus::UnitPixel); 
			TRACE(L"m_bIsMouseHover\r\n");   
		}
		if ( m_bIsChecked )
		{
			gBuf->DrawImage(m_clickBg,0,0,0,0,m_Width,m_Height,Gdiplus::UnitPixel); 
			TRACE(L"m_bIsMouseClick\r\n");  
		}
	}
	
	delete gBuf;
	g.DrawImage(&bmp,0,0);
	g.ReleaseHDC(dc.m_hDC);
	 
}


另一种方法继承自CButton类,因此可以不用动态创建,调用个方法加载图片资源就行,这里便是用FormFile来加载:

void CPngButton::SetButtonImage(CString str)
{
	strImage = str;

	m_pImage = Image::FromFile(str);

	if ( !m_pImage )
	{
		return;
	}
	m_nWidth = m_pImage->GetWidth();
	m_nHeight = m_pImage->GetHeight();

	m_nSliceWidth = m_nWidth;
	m_nSliceHeight = m_nHeight;
	CWnd *pWnd = this -> GetParent();
	GetWindowRect( &m_rectButton );
	pWnd -> ScreenToClient(m_rectButton);
	m_rectButton.right	= m_rectButton.left + m_nSliceWidth;
	m_rectButton.bottom	= m_rectButton.top  + m_nHeight;

	//MoveWindow(m_rectButton);      //调整按钮大小以适应图片
	SetWindowPos(NULL,0,0,m_rectButton.Width(),m_rectButton.Height(),SWP_NOMOVE);
	nWidth = m_rectButton.Width();
	nHeight = m_rectButton.Height();
	m_pGraphics = new Graphics(GetWindowDC()->m_hDC);
}

然后重载DrawItem,和第一个方法其实差不多:

CDC* pDC = CDC::FromHandle(lpDrawItemStruct -> hDC);
	CRect rect = lpDrawItemStruct->rcItem;
	UINT state = lpDrawItemStruct->itemState;
	m_rcText   = rect;
	m_rcText.DeflateRect(1,1);

	if(m_pGraphics == NULL)
		return;
	if(m_pImage == NULL)
		return;

	if( m_bDisable == TRUE )//RECT里面的参数是图片在控件中的大小、位置
	{						//外面的参数是指定取图的范围、位置
		m_pGraphics->DrawImage(m_pImage,Rect(0,0,m_nWidth,m_nSliceHeight),0,
		0,m_nWidth, m_nSliceHeight,UnitPixel);
	}

	else
	{
		// click state
		if( lpDrawItemStruct -> itemState & ODS_SELECTED )//m_pImage根据需要修改
		{
			m_pGraphics->DrawImage(m_pImage,Rect(0,0,m_nWidth,m_nHeight),0,
			0,m_nWidth, m_nSliceHeight,UnitPixel);
		}
		// hover state
		else if ( m_bHover )
		{
			m_pGraphics->DrawImage(m_pImage,Rect(0,0,m_nWidth,m_nHeight),0,
			0,m_nWidth, m_nSliceHeight,UnitPixel);
		}
		// enable state
		else
		{
			m_pGraphics->DrawImage(m_pImage,Rect(0,0,m_nWidth,m_nHeight),0,
			0,m_nSliceWidth, m_nSliceHeight,UnitPixel);
		}
	}



有兴趣的话可以去下载这两个类:

http://download.csdn.net/detail/c__allen/4327358


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFC是微软基于C++的编程框架,主要用于Windows平台应用程序的开发。它提供了一套丰富的和函数库,方便开发者进行界面设计、事件处理、数据操作等。MFC能够有效地简化Windows应用程序的开发过程,提高开发效率。 PNGButton是MFC中的一个自定义按钮控件。与普通按钮相比,PNGButton可以使用PNG格式的图片作为按钮的背景,使按钮具有更丰富的效果和视觉效果。开发者可以通过设置不同的PNG图片来实现按钮的不同状态,如正常状态、鼠标悬停状态、按钮按下状态等。同时,PNGButton还提供了丰富的事件处理,可以根据按钮的不同状态触发相应的事件响应,满足不同的功能需求。 CSDN是中国最大的IT社区和技术分享平台。CSDN汇集了大量的技术专家和开发者,提供了丰富的技术文章、教程、问答、博客等资源,涵盖了计算机科学、软件开发、网络安全、大数据、人工智能等各个领域。开发者可以通过CSDN获取到各种技术资讯、学习经验和解决方案,提升自己的技术水平。 综上所述,MFC是用于Windows平台应用程序开发的编程框架,PNGButton是MFC中的一个自定义按钮控件,CSDN是一个汇集技术资源和分享经验的IT社区和平台。通过MFC和PNGButton,开发者可以在Windows平台上开发出具有各种效果的应用程序,而CSDN则为开发者提供了一个学习和交流的平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值