if (!bIsEnabled) //如果是禁用状态 { m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*3/4,0,m_imgPngButton.GetWidth()*4/4,m_imgPngButton.GetHeight()));
return; } if (m_bIsHoverPng) { if (m_bIsDownPng) { //按下状态 m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*2/4,0,m_imgPngButton.GetWidth()*3/4,m_imgPngButton.GetHeight()));
void CPngImageButton::OnPaint()
{
CPaintDC dc(this); // device context for painting
if(m_imgPngButton.IsNull()) return;
CRect rcClient;
GetClientRect(rcClient); HWND hwnd = GetSafeHwnd(); //获取窗口的HWND
::UpdateWindow(hwnd);
CDC *pDC = GetDC();
if (m_imgPngButton.IsNull())
{
MessageBox(_T("没加载成功"));
return;
}
/*if (m_imgPngButton.GetBPP() == 32) //确认该图像包含Alpha通道
{
for (int i=0; i<m_imgPngButton.GetWidth(); ++i)
{
for (int j=0; j<m_imgPngButton.GetHeight(); ++j)
{
byte *pByte = (byte *)m_imgPngButton.GetPixelAddress(i, j);
pByte[0] = pByte[0] * pByte[3] / 255;
pByte[1] = pByte[1] * pByte[3] / 255;
pByte[2] = pByte[2] * pByte[3] / 255;
}
}
} */ BOOL bIsEnabled = IsWindowEnabled(); //看按钮是不是禁用状态
if (!bIsEnabled) //如果是禁用状态
{
m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*3/4,0,m_imgPngButton.GetWidth()*4/4,m_imgPngButton.GetHeight()));
return;
} if (m_bIsHoverPng)
{
if (m_bIsDownPng)
{ //按下状态 m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*2/4,0,m_imgPngButton.GetWidth()*3/4,m_imgPngButton.GetHeight()));
}
else
{ //经过状态 m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*1/4,0,m_imgPngButton.GetWidth()*2/4,m_imgPngButton.GetHeight()));
}
}
else
{ //正常状态
//CBrush br(0xB22222);
//pDC->FillRect(rcClient,&br);
m_imgPngButton.Draw(dc.m_hDC,rcClient,CRect(m_imgPngButton.GetWidth()*0/4,0,m_imgPngButton.GetWidth()*1/4,m_imgPngButton.GetHeight()));
}
}
不能是透明的是什么意思啊,我看安全卫士类的软件都是PNG透明的按钮啊
2、解决思路:每次重画PNG图时先把BUTTON在父窗口上对应的那一小块区域刷新一下即可解决,也就是刷新父窗口的一块区域。
大致代码如下:
void CPngImageButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if( !m_bIsMouseOver )
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE;
m_bIsMouseOver = ( _TrackMouseEvent(&tme) == TRUE ); CWnd * pWndParent = this->GetParent();
CRect rc;
GetWindowRect( rc );
pWndParent->ScreenToClient( rc );
pWndParent->InvalidateRect( rc );
this->Invalidate();
} CButton::OnMouseMove(nFlags, point);
}void CPngImageButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bIsMouseOver = false; CWnd * pWndParent = this->GetParent();
CRect rc;
GetWindowRect( rc );
pWndParent->ScreenToClient( rc );
pWndParent->InvalidateRect( rc );
this->Invalidate(); CButton::OnMouseLeave();
}
{
CPaintDC dc(this); // device context for painting
if(m_imgPngButton.IsNull()) return;
CPngImageButton: 与 m_imgPngButton 什么关系 ?
CImage m_imgPngButton 是变量。CPngImageButton 是自己建的类啊,
GetClientRect(rcClient);
pDC->FillSolidRect(&rcClient,RGB(255,255,255));
CPaintDC dc;
我写了个工程又测试了一遍,请看图:这是注释掉相关代码之后的图片切换效果:
这是完整代码的图片切换效果:
PNG图片按钮的完整代码如下:#pragma once//头文件//GDI+ 包含 这个我没记错的话安装的是 Microsoft Platform SDK 2003 这个 SDK包里包含的。
#include "C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Include\\GdiPlus.h"
#pragma comment(lib,"C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Lib\\GdiPlus.lib")// CPngImageButtonclass CPngImageButton : public CButton
{
DECLARE_DYNAMIC(CPngImageButton)public:
CPngImageButton();
virtual ~CPngImageButton(); Gdiplus::Image * m_pPngNormal; // 菜单按钮
Gdiplus::Image * m_pPngOver ;
Gdiplus::Image * m_pPngDown ; BOOL LoadImage(Gdiplus::Image* &pImage,LPCTSTR lpName,LPCTSTR lpType);
bool m_bIsPressed, m_bIsFocus, m_bIsMouseOver;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
protected:
virtual void PreSubclassWindow();
public:
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
protected:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};// PngImageButton.cpp : 实现文件
//#include "stdafx.h"
#include "PngImageButton.h"
#include "Resource.h"// CPngImageButtonIMPLEMENT_DYNAMIC(CPngImageButton, CButton)CPngImageButton::CPngImageButton()
{
m_bIsPressed = m_bIsFocus = m_bIsMouseOver = false;
this->LoadImage( m_pPngNormal,MAKEINTRESOURCE(IDB_PNG1),_T("PNG") );
this->LoadImage( m_pPngOver,MAKEINTRESOURCE(IDB_PNG2),_T("PNG") );
this->LoadImage( m_pPngDown,MAKEINTRESOURCE(IDB_PNG3),_T("PNG") );
}CPngImageButton::~CPngImageButton()
{
}BEGIN_MESSAGE_MAP(CPngImageButton, CButton)
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()// CPngImageButton 消息处理程序void CPngImageButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if( !m_bIsMouseOver )
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE;
m_bIsMouseOver = ( _TrackMouseEvent(&tme) == TRUE ); // 可测试:将下面5行代码注释起来:图片切换时会有上次图片残留。
CWnd * pWndParent = this->GetParent();
CRect rc;
GetWindowRect( rc );
pWndParent->ScreenToClient( rc );
pWndParent->InvalidateRect( rc ); this->Invalidate();
} CButton::OnMouseMove(nFlags, point);
}void CPngImageButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bIsMouseOver = false; // 可测试:将下面5行代码注释起来:图片切换时会有上次图片残留。
CWnd * pWndParent = this->GetParent();
CRect rc;
GetWindowRect( rc );
pWndParent->ScreenToClient( rc );
pWndParent->InvalidateRect( rc );
this->Invalidate(); CButton::OnMouseLeave();
}void CPngImageButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
CDC * pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
int nSavedDC = pDC->SaveDC(); CRect rc = lpDrawItemStruct->rcItem; Gdiplus::Graphics graphics( pDC->m_hDC );
Gdiplus::Image * m_pImage = m_pPngNormal; if( m_bIsMouseOver )
m_pImage = m_pPngOver;
else if( m_bIsPressed )
m_pImage = m_pPngDown; graphics.DrawImage( m_pImage,0,0,m_pImage->GetWidth(),m_pImage->GetHeight() );
}void CPngImageButton::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0,BS_OWNERDRAW);
SetWindowPos( NULL,0,0,m_pPngNormal->GetWidth(),m_pPngNormal->GetHeight(),SWP_NOMOVE );
CButton::PreSubclassWindow();
}// 载入图片
BOOL CPngImageButton::LoadImage(Gdiplus::Image* &pImage,LPCTSTR lpName,LPCTSTR lpType)
{
//------------------------------
HINSTANCE hIns=::GetModuleHandle(NULL);
HRSRC hRsrc = ::FindResource (hIns,lpName,lpType); // type
if (!hRsrc)
return FALSE;
// load resource into memory
DWORD len = SizeofResource(hIns, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hIns, hRsrc);
if (!lpRsrc)
return FALSE;
// Allocate global memory on which to create stream
HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
CreateStreamOnHGlobal(hMem,FALSE,&pstm);
// load from stream
pImage=Gdiplus::Image::FromStream(pstm);
//------------------------------
if(!pImage)
return FALSE; GlobalUnlock(hMem);
pstm->Release();
FreeResource(lpRsrc);
return TRUE;
}BOOL CPngImageButton::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值 return TRUE;//CButton::OnEraseBkgnd(pDC);
}LRESULT CPngImageButton::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
switch( message )
{
case BM_SETSTATE:
if( (UINT)m_bIsPressed != wParam )
{
m_bIsPressed = ( wParam == TRUE );
}
break;
default:
break;
} return CButton::WindowProc(message, wParam, lParam);
}
完整工程下载地址:http://download.csdn.net/detail/zhllxt/4843162
哥们,我想要TransPNG的工程文件,就是上面给我代码的那个例子,可以吗,万分感谢
哥们,我想要TransPNG的工程文件,就是上面给我代码的那个例子,可以吗,万分感谢我这不是已经提供了TransPNG的工程文件的下载地址了么。
下面的代码不行
graphics.DrawImage( m_pImage,Rectangle(m_pImage->GetWidth()*0/4,0,m_pImage->GetWidth()*1/4,m_pImage->GetHeight()) );
{
// TODO: 添加您的代码以绘制指定项
CDC * pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
int nSavedDC = pDC->SaveDC(); CRect rc = lpDrawItemStruct->rcItem; Gdiplus::Graphics graphics( pDC->m_hDC );
Gdiplus::Image * m_pImage = m_pPngNormal; if( m_bIsMouseOver )
//m_pImage = m_pPngOver;
graphics.DrawImage( m_pImage,Gdiplus::Rect(0,0,m_pImage->GetWidth()/4,m_pImage->GetHeight()),m_pImage->GetWidth()/4,0,m_pImage->GetWidth()/4,m_pImage->GetHeight(),Gdiplus::Unit::UnitPixel );
else if( m_bIsPressed )
//m_pImage = m_pPngDown;
graphics.DrawImage( m_pImage,0,0,m_pImage->GetWidth(),m_pImage->GetHeight() );
else
//graphics.DrawImage( m_pImage,m_pImage->GetWidth()*0/4,0,m_pImage->GetWidth()*1/4,m_pImage->GetHeight() );
graphics.DrawImage( m_pImage,Gdiplus::Rect(0,0,m_pImage->GetWidth()/4,m_pImage->GetHeight()),0,0,m_pImage->GetWidth()/4,m_pImage->GetHeight(),Gdiplus::Unit::UnitPixel );
}发现绘制的图片很宽,好像是连右边的一起都绘制出来了,导致鼠标向右只有移动到窗体外,图标才会发生改变。另外,为什么点一下图片程序就退出了呢。谢谢兄弟这些天对贴子的关注,愿兄弟新年发大财,万事如意。
鼠标移动到窗体右边,图标才会发生改变:这和绘制没有关系,我猜测你是完全复制我的代码,包括其中如下的代码:void CPngImageButton::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0,BS_OWNERDRAW);
SetWindowPos( NULL,0,0,m_pPngNormal->GetWidth(),m_pPngNormal->GetHeight(),SWP_NOMOVE );
CButton::PreSubclassWindow();
}
将上面代码修改一下,也就是改变一下按钮的宽度,你试试,是不是这个原因。void CPngImageButton::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0,BS_OWNERDRAW);
SetWindowPos( NULL,0,0,m_pPngNormal->GetWidth()/4,m_pPngNormal->GetHeight(),SWP_NOMOVE );
CButton::PreSubclassWindow();
}
最好用DRAWITEM绘制,ONPAINT在有些情况下不可靠。
我工程中的pngimagebutton继承的是CWND类,而兄弟你的工程中的继承的是CBUTTON类,我的那个继承CWND类的pngimagebutton里面没有重写DRAWITEM,怎么办呢
我工程中的pngimagebutton继承的是CWND类,而兄弟你的工程中的继承的是CBUTTON类,我的那个继承CWND类的pngimagebutton里面没有重写DRAWITEM,怎么办呢如果是继承CWND类就用ONPAINT,没有任何问题,只是WINDWOS的控件如BUTTON等重载ONPAINT不可靠。
子图的位置 计算 有 问题,
另外 那个 空的 是不是 可以 用来 涮背景 ?
如果在onpaint中自绘的,那六行代码应该加在哪呢。我试着加在ONPAINT里面,出现一直刷的效果
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
// return TRUE;
CButton::OnEraseBkgnd(pDC);
}
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return TRUE;
return CWnd::OnEraseBkgnd(pDC);
}我的CPngImageButton是CWND添加后,还是重叠。哥们怎么办,
void CWindowPNG::OnClickedPngBtn()
{
CWnd * pWndParent = this->GetParent();
CRect rc;
GetWindowRect( rc );
pWndParent->ScreenToClient( rc );
pWndParent->InvalidateRect( rc );
this->Invalidate();
}
我把这几行代码加到图片区域的单击事件中,可以实现不重叠,但加到别的地方不好使,应该加到什么地方合适呢?谢谢兄弟解答,万分感谢。
{
// TODO: Add your message handler code here and/or call default
static float j=0;
CClientDC dc(this); // device context for painting
if(! m_pImage) return; Gdiplus::Graphics graphics( dc.m_hDC );
CRect rcClient;
GetClientRect(rcClient);
dc.FillSolidRect(&rcClient,RGB(196,196,196));
graphics.DrawImage(m_pImage, RectF(0,0,300,300),j*300,0,300,300,UnitPixel);//
j++;
if(j>2) j=0;
// CDialog::OnTimer(nIDEvent);
}