{
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]);
}
在指定的矩形區(qū)域內(nèi)繪制陰影的全局函數(shù)(當(dāng)然這些函數(shù)不一定都要做成全局函數(shù),我把它們寫成了全局函數(shù)是因?yàn)樵诤脦讉€(gè)類中都用到了它們, 寫成全局函數(shù)便于調(diào)用) 也許你會(huì)覺(jué)得這不符合面向?qū)ο缶幊痰乃枷?,其?shí)面向過(guò)程的編程思想,并不一定就比面向?qū)ο蟮乃枷肼浜?,我把這些比較獨(dú)立的函數(shù)寫成全局函數(shù),當(dāng)作API函數(shù)用,還是覺(jué)得很方便的,如果硬要將它們?nèi)揭粋€(gè)類里面,反而覺(jué)得很郁悶 。:-). 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));
}
}
}
這么復(fù)雜? 唉! 還不是想讓它把陰影畫得更好看一點(diǎn), 速度?...在我機(jī)子上還過(guò)得去。畢竟菜單是不會(huì)被頻繁地重畫的. 這樣實(shí)現(xiàn)陰影確實(shí)有點(diǎn)笨拙,且在意外的時(shí)候可能會(huì)出現(xiàn)一些不愉快的繪圖上的bug. 但是要實(shí)現(xiàn)Windows XP 那樣完美的菜單陰影還是很難的。我希望已經(jīng)知道的高手,能指點(diǎn)指點(diǎn)! 謝了先。
下面是處理清理工作了: void CMenuWndHook::OnNcDestroy()
{
delete this; // 自殺!
}
void CMenuWndHook::OnShowWindow(BOOL bShow)
{
if (!bShow)
{
delete this; // 自殺2!
}
}
... ..., 好狠哦! 嘿嘿!
掃尾工作還由是~CMenuWndHook它老人家做, 在delete自己的時(shí)候會(huì)自動(dòng)調(diào)用它的:
CMenuWndHook::~CMenuWndHook()
{
WNDPROC oldWndProc = (WNDPROC)::GetProp(m_hWnd, CoolMenu_oldProc);
if (oldWndProc != NULL)
{
::SetWindowLong(m_hWnd, GWL_WNDPROC,(DWORD)(ULONG)oldWndProc);
::RemoveProp(m_hWnd, CoolMenu_oldProc);
}
m_WndMenuMap.RemoveKey(m_hWnd);
if (m_bmpBack.m_hObject != NULL)
{
m_bmpBack.DeleteObject();
}
}
這個(gè)類基本上寫完了,如果我還有什么沒(méi)講清的地方,你就再去看看我的源代碼吧。我們可以在APP類里面調(diào)用它: ............
#include "MenuWndHook.h"
...........
BOOL CNewmenuApp::InitInstance()
{
.......
CMenuWndHook::InstallHook();
}
int CNewmenuApp::ExitInstance()
{
CMenuWndHook::UnInstallHook();
return CWinApp::ExitInstance();
}
使用這個(gè)類,再加上一個(gè)自繪菜單類,你一定可以做出一個(gè)非常的精美的菜單來(lái)??纯次易龅淖詈蟪善返慕貓D: