WTL 按钮自绘,加载资源库中的png图片

此类是基于
WTL 自定义 Button类-自绘 改写的
这个类是用来做软键盘按键的,所以有大小写的切换,可以从资源库中加载png资源作为按钮的背景图,如果需要加载本地文件,参考参考文章1 :WTL 自定义 Button类-自绘

注意按钮要是 自绘类型的,否则无法实现按钮自绘

参考文章
WTL 自定义 Button类-自绘
CImage从资源中加载图片文件

//PngButton.cpp
#pragma  once

#include "PngButton.h"
#include "resource.h"
#include 
#pragma comment(lib, "gdiplus.lib")
static ULONG_PTR s_gdiplusToken2=0;


using namespace std;
PngButton::PngButton()
{
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&s_gdiplusToken2, &gdiplusStartupInput, NULL);
    m_nState = btn_state_normal;
    m_bBtnDown = false;
	pNormalBitmap = NULL;
	pDownBitmap  = NULL;
	m_nBtnID = -1;
}
PngButton::~PngButton()
{
    GdiplusShutdown(s_gdiplusToken2);
}

LRESULT PngButton::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    CRect winRect;
    GetWindowRect(winRect);
    SetWindowPos(HWND_TOPMOST,winRect,SWP_SHOWWINDOW);
    return TRUE;
}
LRESULT PngButton::OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    return TRUE;
}
HBITMAP PngButton::GetBitmapFromFile( LPCTSTR pFile )
{
    std::auto_ptr<Bitmap> pBmp(new Bitmap(pFile));
    if(!pBmp.get())
        return NULL;

    HBITMAP hBmp = NULL;
    Color backColor = Color(209,214,220);  
    if(Ok!=pBmp->GetHBITMAP(backColor,&hBmp))
        return NULL;
    return hBmp;
}

HBITMAP PngButton::GetBitmapFromResID( UINT  ResID)//,BOOL  isDown = TRUE  )
{
	Bitmap * pbm = NULL;
	LoadImageFromResource(ResID,_T("PNG"),pbm);
	std::auto_ptr<Bitmap> pBmp(pbm);
	
	if(!pBmp.get())
		return NULL;

	HBITMAP hBmp = NULL;
	Color backColor = Color(209,214,220);  //用于设置png透明色的背景颜色
	if(Ok!=pBmp->GetHBITMAP(backColor,&hBmp))
		return NULL;
	//delete pbm;
	return hBmp;

}
void PngButton::SetBtnBmp(UINT  CapResID,UINT LowResID,UINT DownResID)
{
		if(CapResID && m_btmCap.IsNull())
			m_btmCap.Attach(GetBitmapFromResID(CapResID));
		if(LowResID && m_btmLow.IsNull())
			m_btmLow.Attach(GetBitmapFromResID(LowResID));
		if(DownResID && m_btmDown.IsNull())
			m_btmDown.Attach(GetBitmapFromResID(DownResID));
		RefreshButton();
}

void PngButton::RefreshButton(){
	InvalidateRect(NULL);
}
BOOL  PngButton::DrawBmp( HDC hdc, CRect rect, HBITMAP hBitmap )
{
    BITMAP bm;
    GetObject(hBitmap,sizeof(bm),(VOID*)&bm);
    INT nWidth = bm.bmWidth;
    INT nHeight = bm.bmHeight;
    CDC memdc;
    memdc.CreateCompatibleDC(hdc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(hdc,nWidth,nHeight);
    memdc.SelectBitmap(hBitmap);

    BLENDFUNCTION bf = {AC_SRC_OVER,0,255,1};
    return ::AlphaBlend(hdc,rect.left,rect.top,nWidth,nHeight,memdc,0,0,nWidth,nHeight,bf);
}

LRESULT PngButton::OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    if(!m_bBtnDown)
    {
        m_nState = btn_state_over;
        InvalidateRect(NULL);
        TRACKMOUSEEVENT   t_MouseEvent;
        t_MouseEvent.cbSize       =     sizeof(TRACKMOUSEEVENT);
        t_MouseEvent.dwFlags      =     TME_LEAVE|TME_HOVER;
        t_MouseEvent.hwndTrack    =     m_hWnd;
        t_MouseEvent.dwHoverTime  =     30;
        ::_TrackMouseEvent(&t_MouseEvent);

    }

    return TRUE;
}
LRESULT PngButton::OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    m_nState = btn_state_normal;
    m_bBtnDown = false;
    InvalidateRect(NULL);
    return TRUE;
}
LRESULT PngButton::OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    m_nState = btn_state_normal;
    m_bBtnDown  = false;
    InvalidateRect(NULL);
    ::PostMessage(GetParent(),WM_COMMAND,m_nBtnID,NULL);
    return TRUE;
}
LRESULT PngButton::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    m_bBtnDown = true;
    m_nState = btn_state_down;
    InvalidateRect(NULL);
    return TRUE;
}
LRESULT PngButton::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{

    return TRUE;
}
void PngButton::SetBtnText(CString strText)
{
    m_strText = strText;

}
void PngButton::SetBtnID(int nID)
{
    m_nBtnID = nID;
}


void PngButton::DrawItem(LPDRAWITEMSTRUCT lpdis){
	CDCHandle dc(lpdis->hDC);
	CDC dcMem;
	dcMem.CreateCompatibleDC ( dc );
	dc.SaveDC();
	dcMem.SaveDC();
	CRect btnRect;
	GetWindowRect(btnRect);
	dc.FillSolidRect ( &lpdis->rcItem,NEWKEYBOARDCOLOR );

	dcMem.SelectBitmap (m_btmCap);
/*	以下注释代码用于实现大小写图片的切换,不在正常流程中,放在外部更合适
	if(m_nState == btn_state_down  && !m_btmDown.IsNull()){						//优先显示按下状态
		dcMem.SelectBitmap (m_btmDown);
	}
	else{
		SHORT capState = (GetKeyState(VK_CAPITAL)&0x000F);
		if(capState){								//大写状态
			if(!m_btmCap.IsNull()){
				dcMem.SelectBitmap (m_btmCap);		
			}
		}  
		if(!capState){
			if(!m_btmLow.IsNull()){
				dcMem.SelectBitmap (m_btmLow);
			}
		}
	}
*/
	if (m_nState == btn_state_down ){
		dc.BitBlt ( 2, 2, btnRect.Width(), btnRect.Height(), dcMem, 0, 0, SRCCOPY );
	}
	else{
		dc.BitBlt ( 0, 0,  btnRect.Width(), btnRect.Height(), dcMem, 0, 0, SRCCOPY );
	}
	

	dcMem.RestoreDC(-1);
	dc.RestoreDC(-1);
}


BOOL PngButton::SubclassWindow(HWND hWnd)
{
	ATLASSERT(m_hWnd == NULL);
	ATLASSERT(::IsWindow(hWnd));
	BOOL bRet = CWindowImpl<PngButton, CButton>::SubclassWindow(hWnd);
	if(bRet)
	{
	}

	return bRet;
}


BOOL PngButton::LoadImageFromResource(UINT nResID,LPCTSTR lpTyp,Bitmap* &pbm)
{
	// 查找资源
	HRSRC hRsrc=::FindResource(g_hInst, MAKEINTRESOURCE(nResID), lpTyp);
	if(hRsrc ==NULL)
		return false;

	// 加载资源
	HGLOBAL hImgData=::LoadResource(g_hInst, hRsrc);
	if(hImgData ==NULL)
	{
		::FreeResource(hImgData);
		return false;
	}

	// 锁定内存中的指定资源
	LPVOID lpVoid   =::LockResource(hImgData);

	LPSTREAM pStream =NULL;
	DWORD dwSize   =::SizeofResource(g_hInst, hRsrc);
	HGLOBAL hNew   =::GlobalAlloc(GHND, dwSize);
	LPBYTE lpByte   =(LPBYTE)::GlobalLock(hNew);
	::memcpy(lpByte, lpVoid,dwSize);

	// 解除内存中的指定资源
	::GlobalUnlock(hNew);

	// 从指定内存创建流对象
	HRESULT ht=::CreateStreamOnHGlobal(hNew,TRUE,&pStream);
	if( ht != S_OK )
	{
		GlobalFree(hNew);
	}
	else
	{
		// 加载图片
		pbm = new Bitmap(pStream);
		GlobalFree(hNew);
	}
	// 释放资源
	::FreeResource(hImgData);
	return true;
}

//PngButton.h
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#ifdef __ATLMISC_H__
#define __ATLTYPES_H__
#endif
#include 

using namespace Gdiplus;
enum
{
	btn_state_normal = 0,
	btn_state_over   = 1,
	btn_state_down  = 2
};

class PngButton:public CWindowImpl<PngButton,CButton>, public COwnerDraw<PngButton>
{
public:
	PngButton();
	~PngButton();
		void DrawItem(LPDRAWITEMSTRUCT lpdis);
protected:
	BEGIN_MSG_MAP(PngButton)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 
		MESSAGE_HANDLER(WM_LBUTTONDOWN,OnLButtonDown)
		MESSAGE_HANDLER(WM_LBUTTONUP,OnLButtonUp)
 		MESSAGE_HANDLER(WM_ERASEBKGND,OnEraseBkgnd)
		CHAIN_MSG_MAP_ALT(COwnerDraw<PngButton>, 1)
		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	HBITMAP GetBitmapFromFile( LPCTSTR pFile );
	HBITMAP GetBitmapFromResID( UINT  ResID);// ,BOOL  isNormal);
	void SetBtnBmp(UINT  CapResID,UINT LowResID,UINT DownResID);
	void SetBtnBmp(UINT  NormalResID);
	BOOL  DrawBmp( HDC hdc, CRect rect, HBITMAP hBitmap );
	LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	BOOL SubclassWindow(HWND hWnd);
	void SetBtnText(CString strText);
	void SetBtnID(int nID);
	BOOL LoadImageFromResource(UINT nResID,LPCTSTR lpTyp,Bitmap * &pism);
    void RefreshButton();

private:
	CBitmap m_btmCap;//大写状态的图片
	CBitmap m_btmLow;//小写状态的图片
	CBitmap m_btmDown;//按下状态的图片

	int m_nState;
	bool m_bBtnDown;
	CString m_strText;
	INT     m_nBtnID;
	Bitmap* pNormalBitmap;
	Bitmap* pDownBitmap;
};

使用方法

//容器的头文件
	PngButton m_btn_CapLock;
	BEGIN_DDX_MAP(CNewSoftKeyboard)
		DDX_CONTROL(IDC_BUTTON_CAPLOCK, m_btn_CapLock)
	END_DDX_MAP()


//容器cpp的 init里
	DoDataExchange(false);

你可能感兴趣的