此类是基于
WTL 自定义 Button类-自绘 改写的
这个类是用来做软键盘按键的,所以有大小写的切换,可以从资源库中加载png资源作为按钮的背景图,如果需要加载本地文件,参考参考文章1 :WTL 自定义 Button类-自绘
注意按钮要是 自绘类型的,否则无法实现按钮自绘
参考文章
WTL 自定义 Button类-自绘
CImage从资源中加载图片文件
//PngButton.cpp
#pragma once
#include "PngButton.h"
#include "resource.h"
#include <memory>
#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 <Windows.h>
#include <atlbase.h>
#include <atlapp.h>
#include <atlwin.h>
#include <atlmisc.h>
#include <atlframe.h>
#include <atlctrls.h>
#include <atldlgs.h>
#include <atlddx.h>
#include <atlcrack.h>
#include <atlgdi.h>
#include <GdiPlusHeaders.h>
#include <GdiPlus.h>
#ifdef __ATLMISC_H__
#define __ATLTYPES_H__
#endif
#include <atlimage.h>
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);