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

时间:2022-03-23 19:11:49
用C++实现半透明按钮控件(PNG,GDI+)
用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图片
用C++实现半透明按钮控件(PNG,GDI+)用C++实现半透明按钮控件(PNG,GDI+)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类代码下载