WEB开发网
开发学院软件开发VC 利用钩子实现菜单阴影效果 阅读

利用钩子实现菜单阴影效果

 2008-01-19 20:25:26 来源:WEB开发网   
核心提示:#ifndef SPI_GETDROPSHADOW#define SPI_GETDROPSHADOW 0x1024#endif另外还有 GetScreenBitmap 函数用于截取屏幕上指定区域内的图像: HBITMAP WINAPI GetScreenBitmap (LPCRECT pRect){HDC hDC;HD

#ifndef SPI_GETDROPSHADOW

#define SPI_GETDROPSHADOW 0x1024

#endif

另外还有 GetScreenBitmap 函数用于截取屏幕上指定区域内的图像: HBITMAP WINAPI GetScreenBitmap (LPCRECT pRect)
{
  HDC   hDC;
  HDC   hMemDC;
  HBITMAP hNewBitmap = NULL;
  
  if ((hDC = ::GetDC(NULL)) != NULL )
  {
    if ((hMemDC = ::CreateCompatibleDC(hDC)) != NULL)
    {
      if ((hNewBitmap = ::CreateCompatibleBitmap(hDC,
              pRect->right - pRect->left,
              pRect->bottom - pRect->top)) != NULL)
      {
        HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hNewBitmap);
        ::BitBlt(hMemDC, 0, 0, pRect->right - pRect->left, pRect->bottom - pRect->top,
          hDC, pRect->left, pRect->top, SRCCOPY);
        ::SelectObject(hMemDC, (HGDIOBJ)hOldBitmap);
      }
      ::DeleteDC(hMemDC);
    }
    ::ReleaseDC(NULL, hDC);
  }
  return hNewBitmap;
}
下面这两个函数要做的事就差不多了: void CMenuWndHook::OnNcPaint()
{
  CWindowDC dc(CWnd::FromHandle(m_hWnd));
  OnPrint(&dc);
}
void CMenuWndHook::OnPrint(CDC *pDC)
{
  CRect rc;
  GetWindowRect(m_hWnd, &rc);
  rc.OffsetRect(-rc.TopLeft());
  
  // 绘制阴影
  if (!IsShadowEnabled())
  {
    CDC cMemDC;
    cMemDC.CreateCompatibleDC (pDC);
    HGDIOBJ hOldBitmap = ::SelectObject (cMemDC.m_hDC, m_bmpBack);
    pDC->BitBlt (0, rc.bottom - 4, rc.Width() - 4, 4, &cMemDC, 0, rc.bottom - 4, SRCCOPY);
    pDC->BitBlt (rc.right - 4, 0, 4, rc.Height(), &cMemDC, rc.right - 4, 0, SRCCOPY);
    
    DrawShadow(pDC, rc);
    rc.right -= 4;
    rc.bottom -= 4;
  }
  // 绘制边框
  pDC->Draw3dRect(rc, m_crFrame[0], m_crFrame[1]);
  rc.DeflateRect (1, 1);
  pDC->Draw3dRect(rc, m_crFrame[2], m_crFrame[3]);
}
  在指定的矩形区域内绘制阴影的全局函数(当然这些函数不一定都要做成全局函数,我把它们写成了全局函数是因为在好几个类中都用到了它们, 写成全局函数便于调用) 也许你会觉得这不符合面向对象编程的思想,其实面向过程的编程思想,并不一定就比面向对象的思想落后,我把这些比较独立的函数写成全局函数,当作API函数用,还是觉得很方便的,如果硬要将它们塞到一个类里面,反而觉得很郁闷 。:-). void DrawShadow(CDC *pDC, CRect rect);
void DrawShadow(CDC *pDC, CRect rect)
{
  COLORREF oldcolor = RGB(255, 255, 255);
  BYTE newValR, newValG, newValB;
  BYTE AlphaArray[] = {140, 170, 212, 240};
  BYTE AlphaArray2[] = {170, 205, 220, 240, 240, 250, 255};
  
  // 底部的阴影 -----------------------------------------
  int i, j;
  for (j = 0; j < 4; j++)
  {
    for (i = 6; i <= rect.right - 5; i++)
    {
      oldcolor = pDC->GetPixel(i, rect.bottom - (4 - j));
      newValR = GetRValue(oldcolor) * AlphaArray[j] / 255; 
      newValG = GetGValue(oldcolor) * AlphaArray[j] / 255; 
      newValB = GetBValue(oldcolor) * AlphaArray[j] / 255; 
      pDC->SetPixel(i, rect.bottom - (4 - j), RGB(newValR, newValG, newValB));
    }
  }
  
  // 右边的阴影 -----------------------------------------
  for (i = 0; i < 4; i++)
  {
    for (j = 6; j <= rect.bottom - 5; j++)
    {
      oldcolor = pDC->GetPixel(rect.right - (4 - i), j);
      newValR = GetRValue(oldcolor) * AlphaArray[i] / 255; 
      newValG = GetGValue(oldcolor) * AlphaArray[i] / 255; 
      newValB = GetBValue(oldcolor) * AlphaArray[i] / 255; 
      pDC->SetPixel(rect.right - (4 - i), j, RGB(newValR, newValG, newValB));
    }
  }
  
  // 角上的阴影 --------------------------------------
  for (i = 0; i < 4; i++)
  {
    for (j = 0; j < 4; j++)
    {
      if ((i + j) > 6) break;
      
      oldcolor = pDC->GetPixel(rect.right - 4 + i, rect.bottom - 4 + j);
      newValR = GetRValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValG = GetGValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValB = GetBValue(oldcolor) * AlphaArray2[i + j] / 255; 
      pDC->SetPixel(rect.right - 4 + i,
            rect.bottom - 4 + j,
            RGB(newValR,
            newValG,
            newValB));
      
      oldcolor = pDC->GetPixel(rect.right - 4 + i, rect.top + 5 - j);
      newValR = GetRValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValG = GetGValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValB = GetBValue(oldcolor) * AlphaArray2[i + j] / 255; 
      pDC->SetPixel(rect.right - 4 + i,
             rect.top + 5 - j,
             RGB(newValR,
             newValG,
             newValB));
      
      oldcolor = pDC->GetPixel(rect.left - i + 5, rect.bottom - 4 + j);
      newValR = GetRValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValG = GetGValue(oldcolor) * AlphaArray2[i + j] / 255; 
      newValB = GetBValue(oldcolor) * AlphaArray2[i + j] / 255; 
      pDC->SetPixel(rect.left - i + 5,
             rect.bottom - 4 + j,
             RGB(newValR,
             newValG,
             newValB));
    }
  }
}
这么复杂? 唉! 还不是想让它把阴影画得更好看一点, 速度?...在我机子上还过得去。毕竟菜单是不会被频繁地重画的. 这样实现阴影确实有点笨拙,且在意外的时候可能会出现一些不愉快的绘图上的bug. 但是要实现Windows XP 那样完美的菜单阴影还是很难的。我希望已经知道的高手,能指点指点! 谢了先。

上一页  1 2 3 4 5  下一页

Tags:利用 钩子 实现

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接