用C++实现半透明按钮控件(PNG,GDI+)

 
使用MFC实现上面的按钮半透明效果能看到父窗口中的内容,上面是效果图(一个是带背景图片的、另一个是不带的)。
控件继承自CWnd类(彩色的部分是窗口的背景图片、按钮是PNG图片,第二个图标是鼠标指向时的效果)。
图标的绘制使用GDI+绘制PNG图片,在此不多说了(处理WM_PAINT消息):
      
      
1 void PNGButton::OnPaint() 2 { 3 CPaintDC dc( this ); 4 Graphics g(dc.m_hDC); 5 if (DrawBorder){ 6     g.DrawImage(hoverBg, 0 , 0 ); // 画鼠标指向时的亮色背景 7   } 8 g.DrawImage( this -> bg, 0 , 0 ); // 画按钮图标 9   g.ReleaseHDC(dc.m_hDC); 10 }
 
透明的关键:注意后面调用此方法的代码
关键在于 InvalidateRect函数:通知父窗口重新绘制特定区域,执行此函数后按钮所在区域就被父窗口绘制的内容覆盖.在父窗口绘制完成后,
按钮也会收到WM_PAINT消息,执行上面的一段OnPaint代码.
      
      
1 void PNGButton::PaintParent() 2 { 3 CRect rect; 4 GetWindowRect( & rect); 5 GetParent() -> ScreenToClient( & rect); 6 GetParent() -> InvalidateRect( & rect); 7 }
捕获鼠标指向或移出事件(处理WM_MOUSEMOVE,WM_MOUSEOVER,WM_MOUSELEAVE消息):
 
      
      
1 void PNGButton::OnMouseHover(UINT nFlags, CPoint point) 2 { 3 DrawBorder = true ; 4 PaintParent();//通知父窗口重绘特定区域,会引发控件自身的重绘 5 } 6 7 8   void PNGButton::OnMouseLeave() 9 { 10 m_is_mouse_over = false ; 11 m_is_tracked = false ; 12 DrawBorder = false ; 13 PaintParent(); //通知父窗口重绘特定区域,会引发控件自身的重绘 14 CWnd::OnMouseLeave(); 15 } 16 17 18   void PNGButton::OnMouseMove(UINT nFlags, CPoint point) 19 { 20 m_is_mouse_over = true ; 21 if ( ! m_is_tracked) 22 { 23 TRACKMOUSEEVENT tme; 24 tme.cbSize = sizeof (TRACKMOUSEEVENT); 25 tme.dwFlags = TME_LEAVE | TME_HOVER; 26 tme.hwndTrack = GetSafeHwnd(); 27 tme.dwHoverTime = 80 ; 28 _TrackMouseEvent( & tme); 29 m_is_tracked = true ; 30 } 31 CWnd::OnMouseMove(nFlags, point); 32 }
附:
从资源加载PNG图片
View Code
       
       
1 #pragma once 2 #include " stdafx.h " 3 using namespace Gdiplus; 4 5 static bool ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * & pImg) 6 { 7 HINSTANCE hInst = AfxGetResourceHandle(); 8 HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type 9 if ( ! hRsrc) 10 return FALSE; 11 // load resource into memory 12   DWORD len = SizeofResource(hInst, hRsrc); 13 BYTE * lpRsrc = (BYTE * )LoadResource(hInst, hRsrc); 14 if ( ! lpRsrc) 15 return FALSE; 16 // Allocate global memory on which to create stream 17   HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len); 18 BYTE * pmem = (BYTE * )GlobalLock(m_hMem); 19 memcpy(pmem,lpRsrc,len); 20 IStream * pstm; 21 CreateStreamOnHGlobal(m_hMem,FALSE, & pstm); 22 // load from stream 23   pImg = Gdiplus::Image::FromStream(pstm); 24 // free/release stuff 25   GlobalUnlock(m_hMem); 26 pstm -> Release(); 27 FreeResource(lpRsrc); 28 return TRUE; 29 }
平铺图片的代码
      
      
1 CPaintDC dc( this ); 2 CRect rect; 3 GetClientRect(rect); 4 CBrush bs(RGB( 240 , 240 , 240 )); // 窗口背景色 5   dc.FillRect( & rect, & bs); // 窗口着色 6 // 填充背景图片:平铺 7   Graphics g(dc.m_hDC); 8 if (has_bg) g.DrawImage( this -> bg, 0 , 0 ); 9 Gdiplus::TextureBrush bbs( this -> img); 10 g.FillRectangle( & bbs, 0 , 0 ,rect.Width(), this -> img -> GetHeight()); 11 g.ReleaseHDC(dc.m_hDC); 12 // TRACE(L"CMainFrame::OnPaint\r\n");

附:PNGButton类代码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值