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


使用MFC实现上面的按钮半透明效果能看到父窗口中的内容,上面是效果图(一个是带背景图片的、另一个是不带的)。
控件继承自CWnd类(彩色的部分是窗口的背景图片、按钮是PNG图片,第二个图标是鼠标指向时的效果)。
图标的绘制使用GDI+绘制PNG图片,在此不多说了(处理WM_PAINT消息):
void PNGButton::OnPaint()
 {  
  CPaintDC dc(this);    
  Graphics g(dc.m_hDC);   
  if(DrawBorder){   
     g.DrawImage(hoverBg,0,0);//画鼠标指向时的亮色背景  
  } 
  g.DrawImage(this->bg,0,0);//画按钮图标
   g.ReleaseHDC(dc.m_hDC);
 }


透明的关键:注意后面调用此方法的代码

关键在于 InvalidateRect函数:通知父窗口重新绘制特定区域,执行此函数后按钮所在区域就被父窗口绘制的内容覆盖.在父窗口绘制完成后,
按钮也会收到WM_PAINT消息,执行上面的一段OnPaint代码.
void PNGButton::PaintParent()
 {  
  CRect   rect; 
  GetWindowRect(&rect); 
  GetParent()-> ScreenToClient(&rect); 
  GetParent()-> InvalidateRect(&rect);
 }
 
捕获鼠标指向或移出事件(处理WM_MOUSEMOVE,WM_MOUSEOVER,WM_MOUSELEAVE消息):
void PNGButton::OnMouseHover(UINT nFlags, CPoint point)
 {    
  DrawBorder=true;
  PaintParent();//通知父窗口重绘特定区域,会引发控件自身的重绘
 }
 
 
  void PNGButton::OnMouseLeave()
 {    
  m_is_mouse_over =   false; 
  m_is_tracked =   false;  
  DrawBorder=false;
  PaintParent();  //通知父窗口重绘特定区域,会引发控件自身的重绘
  CWnd::OnMouseLeave();
 }
 
 
  void PNGButton::OnMouseMove(UINT nFlags, CPoint point)
 {
  m_is_mouse_over   =   true;  
  if(!m_is_tracked) 
  { 
   TRACKMOUSEEVENT   tme; 
   tme.cbSize  =   sizeof(TRACKMOUSEEVENT); 
   tme.dwFlags  =   TME_LEAVE|TME_HOVER;  
   tme.hwndTrack   =   GetSafeHwnd(); 
   tme.dwHoverTime =   80; 
   _TrackMouseEvent(&tme);  
   m_is_tracked   =   true;    
  }   
  CWnd::OnMouseMove(nFlags, point);
 }

附:
从资源加载PNG图片
附:
从资源加载PNG图片

 

View Code 
 #pragma once
 #include "stdafx.h"
  using namespace Gdiplus; 
 
  static bool ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * &pImg)
 {
      HINSTANCE hInst = AfxGetResourceHandle();
      HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
       if (!hRsrc)
       return FALSE;
      // load resource into memory
       DWORD len = SizeofResource(hInst, hRsrc);
      BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
      if (!lpRsrc)
       return FALSE;
      // Allocate global memory on which to create stream
       HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
      BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
      memcpy(pmem,lpRsrc,len);
      IStream* pstm;
      CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
      // load from stream
       pImg=Gdiplus::Image::FromStream(pstm);
      // free/release stuff
       GlobalUnlock(m_hMem);
      pstm->Release();
      FreeResource(lpRsrc);
      return TRUE;
 }

平铺图片的代码

CPaintDC dc(this); 
     CRect rect; 
     GetClientRect(rect);
     CBrush bs(RGB(240,240,240));//窗口背景色
      dc.FillRect(&rect,&bs);        //窗口着色
     //填充背景图片:平铺
      Graphics g(dc.m_hDC);    
     if(has_bg) g.DrawImage(this->bg,0,0); 
     Gdiplus::TextureBrush bbs(this->img);
     g.FillRectangle(&bbs,0,0,rect.Width(),this->img->GetHeight()); 
     g.ReleaseHDC(dc.m_hDC);
     //TRACE(L"CMainFrame::OnPaint\r\n");


 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值