子視窗的透明

來源:互聯網
上載者:User

由於項目中要實現子視窗的透明的功能,在網上找到了這一段提示:

子視窗的透明和主視窗完全不同,   主視窗是通過layeredwindow實現的,   而子視窗則必須自己實現,   尤其是半透明,   必須自己對擷取的透明背景圖進行操作。   要實現子視窗的透明需要做到下面幾步:

1.   windows的ExStyle中需要包含WS_EX_TRANSPARENT屬性
2.   windows的Style中要去掉WS_CLIPSIBLING屬性
3.   對繼承自windows標準控制項的子視窗(   比如edit,   scrollbar等等   ),   需要截獲WM_CTLCOLORxxx訊息並返回一個style為BS_HOLLOW的brush的handle(即一個透明畫刷的handle)
4.   需要截獲WM_ERASEBKGND訊息並不要清除背景(如果做到了3,   則這一步可以省略)
5.   最關鍵的一點(也是很多人沒有想到或不知道的),   必須將parent視窗style中的WS_CLIPCHILDREN標誌去掉,   否則PARENT視窗重畫時不會重畫被子視窗覆蓋的部分.
6.   做到以上各步後,   在子視窗收到WM_PAINT訊息時就可以獲得完整的背景圖了,   接下去對這背景進行處理就可以實現半透明效果.

    另外一點,   最好同時截獲parent窗的WM_PAINT訊息,   在parent窗重畫前調用InvalidateRect讓本子視窗顯示實效,   這樣子視窗才能同樣也收到一個WM_PAINT訊息(   這樣做是為了保險,   因為我不是很確定主視窗重畫系統是否會自動給具有WS_EX_TRANSPARENT屬性的子視窗同樣發WM_PAINT   ).

 

 

如果誰更好的實現方法,請告訴我

 

實現過程中,我沒處理第二和第五提示。

我的部分代碼如下:

void CWndTool::AlphaCompositeBmp(const HBITMAP& bmpFront,const HBITMAP& bmpBKGround, HBITMAP& bmpDest, int nAlpha)
{
 ASSERT(bmpFront);
 ASSERT(bmpBKGround);

 CBitmap* pBmpFront = CBitmap::FromHandle(bmpFront);
 CBitmap* pBmpBkGround = CBitmap::FromHandle(bmpBKGround);

 
 CDC memDcFront;
 CDC memDcBkGround;
 CDC memDcDest;
 
 BITMAP bmFront;

 CDC* pDc = GetDC();

 memDcFront.CreateCompatibleDC(pDc);
 memDcDest.CreateCompatibleDC(pDc);
 memDcBkGround.CreateCompatibleDC(pDc);

 CBitmap* pOldBmpFront = memDcFront.SelectObject(pBmpFront);
 pBmpFront->GetBitmap(&bmFront);
 
 CBitmap* pOldBmpBkGround = memDcBkGround.SelectObject(pBmpBkGround);

 if (m_pTmpDest)
 {
  delete m_pTmpDest;
  m_pTmpDest = NULL;
 }
 m_pTmpDest = new CBitmap();
 m_pTmpDest->CreateCompatibleBitmap(pDc, bmFront.bmWidth, bmFront.bmHeight);
 CBitmap* pBmpDest = memDcDest.SelectObject(m_pTmpDest);

 
 for (int i=0; i<bmFront.bmHeight; i++)
  for (int j=0; j<bmFront.bmWidth; j++)
  {
   int rFront,gFront,bFront;
   int rBkGround,gBkGround,bBkGround;
   int rDest,gDest,bDest;

   COLORREF crFront = memDcFront.GetPixel(j, i);
   COLORREF bkRgb = memDcBkGround.GetPixel(j, i);

   rFront = GetRValue(crFront);
   gFront = GetGValue(crFront);
   bFront = GetBValue(crFront);

   rBkGround = GetRValue(bkRgb);
   gBkGround = GetGValue(bkRgb);
   bBkGround = GetBValue(bkRgb);

   rDest = (rBkGround*nAlpha+rFront*(256-nAlpha))/256;
   gDest = (gBkGround*nAlpha+gFront*(256-nAlpha))/256;
   bDest = (bBkGround*nAlpha+bFront*(256-nAlpha))/256;

   COLORREF crDest = RGB(rDest, gDest, bDest);
   COLORREF crRet = memDcDest.SetPixel(j, i, crDest); 
  }

 memDcFront.SelectObject(pOldBmpFront);
 memDcBkGround.SelectObject(pOldBmpBkGround);
 memDcDest.SelectObject(pBmpDest);

 bmpDest = (HBITMAP)(m_pTmpDest->m_hObject);
}

 

void CWndTool::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 // TODO: Add your message handler code here
 // Do not call CUIWnd::OnPaint() for painting messages

  CRect rt;
  GetClientRect(&rt);
 
  CDC memDc;
  memDc.CreateCompatibleDC(&dc);
  CBitmap* pBmp = memDc.SelectObject(CBitmap::FromHandle(m_bmpDest));
  dc.BitBlt(0, 0, rt.Width(), rt.Height(), &memDc, 0, 0, SRCCOPY);
  memDc.SelectObject(pBmp);
}

 

void CWndTool::OnMouseMove(UINT nFlags, CPoint point)
{
 if (m_isOverWnd == FALSE)
 {
  TRACKMOUSEEVENT tme;
  tme.cbSize = sizeof(tme);
  tme.hwndTrack = m_hWnd;
  tme.dwFlags = TME_HOVER|TME_LEAVE;
  tme.dwHoverTime = 1;
  _TrackMouseEvent(&tme);
  m_isOverWnd = TRUE;
 }
 CUIWnd::OnMouseMove(nFlags, point);
}

void CWndShowHeaderTool::OnTimer(UINT_PTR id)
{
 if (id == TIMER_OVER_TOOLWND)
 {
  if (m_nTransparent < 55)
  {
   KillTimer(TIMER_OVER_TOOLWND);
   return;
  }

  if (m_bmpDest)
  {
   DeleteObject(m_bmpDest);
   m_bmpDest = NULL;
  }

  AlphaCompositeBmp(m_bmpFront, m_bmpBKGround, m_bmpDest, m_nTransparent);
  Invalidate(FALSE);
  UpdateWindow();
  m_nTransparent -= 50;
 }
 if (id == TIMER_LEAVE_TOOLWND)
 {
  if (m_nTransparent > 255)
  {
   KillTimer(TIMER_LEAVE_TOOLWND);
   return;
  }

  AlphaCompositeBmp(m_bmpFront, m_bmpBKGround, m_bmpDest, m_nTransparent);
  Invalidate(FALSE);
  UpdateWindow();
  m_nTransparent += 50;
 }
}
int CWndTool::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CUIWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

 // TODO:  Add your specialized creation code here
 DWORD dwExStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
 dwExStyle |= WS_EX_TRANSPARENT;
 SetWindowLong(m_hWnd, GWL_EXSTYLE, dwExStyle);

 m_bmpFront = LoadBITMAPOBJ(CUIMgr::GetUIPathWithoutTitle()+_T("IDB_CHATWND_TOOL.bmp"));
 m_bmpBKGround = LoadBITMAPOBJ(CUIMgr::GetUIPathWithoutTitle()+_T("IDW_CHAT_RIGHT_SHOW_HEADER.bmp"));

 AlphaCompositeBmp(m_bmpFront, m_bmpBKGround, m_bmpDest, m_nTransparent);

 return 0;
}

LRESULT CWndTool::OnMouseHover( WPARAM wParam, LPARAM lParam )
{
 TRACE(_T("CWndShowHeaderTool::OnMouseHover %d/n"), IsMouseOver()?1:0);
 if (m_bHaveOverTimer == TRUE)
 {
  return 0;
 }

 m_isOverWnd   = true;
 m_bHaveOverTimer = TRUE;
 m_nTransparent  = 255;
 
 KillTimer(TIMER_LEAVE_TOOLWND);
 SetTimer(TIMER_OVER_TOOLWND, 50, NULL);

 return 0;
}

LRESULT CWndTool::OnMouseLeave( WPARAM wParam, LPARAM lParam )
{
 TRACE(_T("CWndShowHeaderTool::OnMouseLeave %d/n"), IsMouseOver()?1:0);

 KillTimer(TIMER_OVER_TOOLWND);
 SetTimer(TIMER_LEAVE_TOOLWND, 50, NULL);

 m_isOverWnd   = false;
 m_bHaveOverTimer = FALSE;
 m_nTransparent  = 55;

 return 0;
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.