求高手,封装了两个个透明PNG按钮类,效果都不是很好!!!
第一个是GDI+自绘按钮类
效果稳定,但有缺陷:
1.要获取父窗口的背景图片,再将该区域绘制到本窗口
2.鼠标多点几下PNG图片就会叠加显示
代码如下:
[code=C/C++][/code]// PNGButton.cpp : 实现文件
//
#include "stdafx.h"
#include "PNGButton.h"
// CPNGButton
IMPLEMENT_DYNAMIC(CPNGButton, CButton)
CPNGButton::CPNGButton()
{
m_bHover=FALSE;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
CPNGButton::~CPNGButton()
{
GdiplusShutdown(gdiplusToken);
}
BEGIN_MESSAGE_MAP(CPNGButton, CButton)
ON_WM_MOUSEMOVE()
ON_WM_ERASEBKGND()
ON_WM_TIMER()
//ON_WM_MOUSEHOVER()
//ON_WM_MOUSELEAVE()
//ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// CPNGButton 消息处理程序
void CPNGButton::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0,BS_OWNERDRAW);
CButton::PreSubclassWindow();
}
void CPNGButton::DrawItem(LPDRAWITEMSTRUCT lp)
{
UINT state=lp->itemState;
CRect rcitem=lp->rcItem;
CDC* pDC = CDC::FromHandle(lp-> hDC);
Graphics graphics(pDC->m_hDC);
Image imageNor(strPath,FALSE);
int x,y;
x=(rcitem.Width()-imageNor.GetWidth())/2;
y=(rcitem.Height()-imageNor.GetHeight())/2;
graphics.DrawImage(&imageNor,x,y,imageNor.GetWidth(),imageNor.GetHeight());
//Invalidate();
/*}*/
if(state&ODS_FOCUS)
{
if(state&ODS_SELECTED)
{
Image imageSel(_T("res\\chatdlg\\toolbarn.PNG"));
graphics.DrawImage(&imageSel,0,0);
}
else
{
if(m_bHover)
{
Image imageHov(_T("res\\chatdlg\\toolbarn.PNG"),FALSE);
graphics.DrawImage(&imageHov,0,0);
}
}
}
// TODO: 添加您的代码以绘制指定项(rcitem.Width()-imageNor.GetWidth())/2(rcitem.Height()-imageNor.GetHeight())/2
}
void CPNGButton::OnMouseMove(UINT nFlags, CPoint point)
{
CClientDC dc(this);
Graphics graphics(dc.m_hDC);
if(!m_bHover)
{
m_bHover=TRUE;
Image imageSel(_T("res\\chatdlg\\toolbarn.PNG"));
graphics.DrawImage(&imageSel,0,0);
SetTimer(1,10,NULL);
}
CButton::OnMouseMove(nFlags, point);
}
BOOL CPNGButton::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rc=GetRectInParent();
//ScreenToClient(rc);
Image imageBK(strBKPath);
Graphics graphics(pDC->m_hDC);
Bitmap membmp(200,200);
Graphics *graph=Graphics::FromImage(&membmp);
//graph->Clear(0xffffffff);
Unit srcunit = UnitPixel;
graph->DrawImage(&imageBK,0,0,rc.left,rc.top,45,45,srcunit);
graphics.DrawImage(&membmp,0,0);
//graphics.FillRectangle(&SolidBrush(Color(0,0,0,0)),0,0,rc.Width(),rc.Height());
return TRUE;
}
void CPNGButton::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CPoint point;
GetCursorPos(&point);
CRect rcitem;
GetWindowRect(&rcitem);
if(!PtInRect(&rcitem,point))
{
KillTimer(1);
m_bHover=FALSE;
Invalidate();
}
CButton::OnTimer(nIDEvent);
}
CRect CPNGButton::GetRectInParent()
{ ////适用于无边框窗口
CRect rcWindowParent;
GetParent()->GetWindowRect(rcWindowParent);//client
CRect rcWindow;
GetWindowRect(&rcWindow);
CRect rect;
rect.left = rcWindow.left-rcWindowParent.left;
rect.top = rcWindow.top-rcWindowParent.top;
rect.right = rcWindow.right-rcWindowParent.left;
rect.bottom = rcWindow.bottom-rcWindowParent.top;
return rect;
}
void CPNGButton::SetImagePath(CString str,CString strbk)
{
strPath=str;
strBKPath=strbk;
}
/////
第二个基于CWnd的类,虽然没有一中的问题。
但鼠标移动在上面会闪烁:
代码如下:
[code=C/C++][/code]// EnPNGButton.cpp : 实现文件
//
#include "stdafx.h"
#include "EnPNGButton.h"
// CEnPNGButton
IMPLEMENT_DYNAMIC(CEnPNGButton, CWnd)
CEnPNGButton::CEnPNGButton()
{
m_bHover=FALSE;
m_bTracked=FALSE;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
CEnPNGButton::~CEnPNGButton()
{
GdiplusShutdown(gdiplusToken);
}
BEGIN_MESSAGE_MAP(CEnPNGButton, CWnd)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEHOVER()
ON_WM_MOUSELEAVE()
ON_WM_LBUTTONUP()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
// CEnPNGButton 消息处理程序
BOOL CEnPNGButton::Create(UINT x,UINT y, CWnd* pParentWnd, UINT nID,CString strN,CString strH,CCreateContext* pContext)
{
// 在此添加专用代码和/或调用基类
strNor=strN;
strHov=strH;
LPCTSTR lpszClassName=AfxRegisterWndClass( CS_HREDRAW|CS_VREDRAW,AfxGetApp()->LoadStandardCursor(IDC_ARROW),(HBRUSH)GetStockObject(TRANSPARENT), NULL) ;
Image imageHov(strH,FALSE);
nWidth=imageHov.GetWidth();
nHeight=imageHov.GetHeight();
BOOL OK=CWnd::Create(lpszClassName,NULL,WS_CHILDWINDOW|WS_VISIBLE, CRect(x,y,x+nWidth,y+nHeight),pParentWnd, nID, pContext);
ModifyStyleEx(0, WS_EX_TRANSPARENT);// WS_EX_LAYERED||WS_EX_TRANSPARENT
return OK;
}
void CEnPNGButton::PaintParent()
{
CRect rect;
GetWindowRect(&rect);
GetParent()->ScreenToClient(&rect);
//Invalidate();
GetParent()->InvalidateRect(&rect);
}
void CEnPNGButton::Draw(CDC *pDC)
{
Graphics graphics(pDC->m_hDC);
Bitmap Membmp(this->nWidth,this->nHeight);
Graphics* graphicBuf=Graphics::FromImage(&Membmp);
Image ImageN(strNor,false);
int x,y;
x=(nWidth-ImageN.GetWidth())/2;
y=(nHeight-ImageN.GetHeight())/2;
graphicBuf->DrawImage(&ImageN,x,y,ImageN.GetWidth(),ImageN.GetHeight());
if(m_bHover)
{
Image imageH(strHov,false);
graphicBuf->DrawImage(&imageH,0,0,nWidth,nHeight);
}
graphics.DrawImage(&Membmp,0,0,nWidth,nHeight);
delete graphicBuf;
graphics.ReleaseHDC(pDC->m_hDC);
}
void CEnPNGButton::OnPaint()
{
CPaintDC dc(this); // device context for painting
Draw(&dc);
}
void CEnPNGButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bHover=TRUE;
if(!m_bTracked)
{
TRACKMOUSEEVENT tme;
tme.cbSize= sizeof(TRACKMOUSEEVENT);
tme.dwFlags= TME_LEAVE|TME_HOVER; //
tme.hwndTrack = GetSafeHwnd();
tme.dwHoverTime= 80;
_TrackMouseEvent(&tme);
m_bTracked=TRUE;
}
CWnd::OnMouseMove(nFlags, point);
}
void CEnPNGButton::OnMouseHover(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
PaintParent();
CWnd::OnMouseHover(nFlags, point);
}
void CEnPNGButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bHover=FALSE;
m_bTracked=FALSE;
PaintParent();
//Invalidate(FALSE);
CWnd::OnMouseLeave();
}
void CEnPNGButton::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
GetParent()->SendMessage(WM_COMMAND,GetDlgCtrlID()|0,(LONG)GetSafeHwnd());
CWnd::OnLButtonUp(nFlags, point);
}
BOOL CEnPNGButton::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
Graphics graphics(pDC->m_hDC);
Image ImageN(strNor,false);
int x,y;
x=(nWidth-ImageN.GetWidth())/2;
y=(nHeight-ImageN.GetHeight())/2;
graphics.DrawImage(&ImageN,x,y,ImageN.GetWidth(),ImageN.GetHeight());
graphics.ReleaseHDC(pDC->m_hDC);
return TRUE;
}
[解决办法]
图片闪烁是没缓冲原因吧
[解决办法]
楼主自己学习还是项目用?
项目用果断CButtonST啊
[解决办法]
图片重叠的原因:因为没有擦除。
而擦除了就会闪烁。所以需要保存parent的这部分dc。
[解决办法]
..............Invalidate()
[解决办法]
指定刷新的区域是吗?
不要全部刷