利用钩子实现菜单阴影效果
2008-01-19 20:25:26 来源:WEB开发网#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()
在指定的矩形区域内绘制阴影的全局函数(当然这些函数不一定都要做成全局函数,我把它们写成了全局函数是因为在好几个类中都用到了它们, 写成全局函数便于调用) 也许你会觉得这不符合面向对象编程的思想,其实面向过程的编程思想,并不一定就比面向对象的思想落后,我把这些比较独立的函数写成全局函数,当作API函数用,还是觉得很方便的,如果硬要将它们塞到一个类里面,反而觉得很郁闷 。:-).
{
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]);
}void DrawShadow(CDC *pDC, CRect rect);
这么复杂? 唉! 还不是想让它把阴影画得更好看一点, 速度?...在我机子上还过得去。毕竟菜单是不会被频繁地重画的. 这样实现阴影确实有点笨拙,且在意外的时候可能会出现一些不愉快的绘图上的bug. 但是要实现Windows XP 那样完美的菜单阴影还是很难的。我希望已经知道的高手,能指点指点! 谢了先。
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));
}
}
}
更多精彩
赞助商链接