📄 menuxp.cpp
字号:
{
DrawMenuText(*pDC, rect + CPoint(1, 1), strText, m_clrSelectedText);
}
if (bDisabled)
{
DrawMenuText(*pDC, rect, strText, m_clrDisabledText);
}
else
{
DrawMenuText(*pDC, rect, strText, bSelected? m_clrSelectedText : m_clrText);
}
pDC->SelectObject(pOldFont);
if (bBold)
fontBold.DeleteObject();
}
//set menu font
BOOL CMenuXP::SetMenuFont(LOGFONT lgfont)
{
m_fontMenu.DeleteObject();
return m_fontMenu.CreateFontIndirect(&lgfont);
}
//clear all memory and handles
void CMenuXP::Clear(void)
{
UINT nCount = GetMenuItemCount();
for (UINT i=0; i<nCount; i++)
{
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_DATA | MIIM_TYPE;
GetMenuItemInfo(i, &info, TRUE);
CMenuXPItem *pData = (CMenuXPItem *)info.dwItemData;
if ((info.fType & MFT_OWNERDRAW) && pData && pData->IsMyData())
{
delete pData;
}
CMenu *pSubMenu = GetSubMenu(i);
if (pSubMenu && pSubMenu->IsKindOf(RUNTIME_CLASS(CMenuXP)))
delete pSubMenu;
}
}
//draw embossed icon for the disabled item
const DWORD MAGICROP = 0xb8074a;
const COLORREF CWHITE = RGB(255,255,255);
void CMenuXP::DrawEmbossed(CDC *pDC, HICON hIcon, CRect rect, BOOL bColor)
{
CDC memdc;
memdc.CreateCompatibleDC(pDC);
int cx = rect.Width();
int cy = rect.Height();
// create mono or color bitmap
CBitmap bm;
if (bColor)
bm.CreateCompatibleBitmap(pDC, cx, cy);
else
bm.CreateBitmap(cx, cy, 1, 1, NULL);
// draw image into memory DC--fill BG white first
CBitmap* pOldBitmap = memdc.SelectObject(&bm);
//FillRect(&memdc, CRect(0, 0, cx, cy), m_clrBackGround);
memdc.PatBlt(0, 0, cx, cy, WHITENESS);
::DrawIconEx(memdc.m_hDC, 0, 0, hIcon, cx, cy, 1, NULL, DI_NORMAL);
// This seems to be required. Why, I don't know. ???
COLORREF colorOldBG = pDC->SetBkColor(CWHITE);
// Draw using hilite offset by (1,1), then shadow
CBrush brShadow(GetSysColor(COLOR_3DSHADOW));
CBrush brHilite(GetSysColor(COLOR_3DHIGHLIGHT));
CBrush* pOldBrush = pDC->SelectObject(&brHilite);
pDC->BitBlt(rect.left+1, rect.top+1, cx, cy, &memdc, 0, 0, MAGICROP);
pDC->SelectObject(&brShadow);
pDC->BitBlt(rect.left, rect.top, cx, cy, &memdc, 0, 0, MAGICROP);
pDC->SelectObject(pOldBrush);
pDC->SetBkColor(colorOldBG); // restore
memdc.SelectObject(pOldBitmap); // ...
bm.DeleteObject();
brShadow.DeleteObject();
brHilite.DeleteObject();
}
//////////////////
// Shorthand to fill a rectangle with a solid color.
//
void CMenuXP::FillRect(CDC *pDC, const CRect& rc, COLORREF color)
{
CBrush brush(color);
CBrush* pOldBrush = pDC->SelectObject(&brush);
pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
brush.DeleteObject();
}
HBITMAP CMenuXP::CreateGradientBMP(HDC hDC,COLORREF cl1,COLORREF cl2,int nWidth,int nHeight,int nDir,int nNumColors)
{
if(nNumColors > 256)
nNumColors = 256;
COLORREF PalVal[256];
int nIndex;
BYTE peRed,peGreen,peBlue;
int r1=GetRValue(cl1);
int r2=GetRValue(cl2);
int g1=GetGValue(cl1);
int g2=GetGValue(cl2);
int b1=GetBValue(cl1);
int b2=GetBValue(cl2);
for (nIndex = 0; nIndex < nNumColors; nIndex++)
{
peRed = (BYTE) r1 + MulDiv((r2-r1),nIndex,nNumColors-1);
peGreen = (BYTE) g1 + MulDiv((g2-g1),nIndex,nNumColors-1);
peBlue = (BYTE) b1 + MulDiv((b2-b1),nIndex,nNumColors-1);
PalVal[nIndex]=(peRed << 16) | (peGreen << 8) | (peBlue);
}
int x,y,w,h;
w=nWidth;
h=nHeight;
LPDWORD pGradBits;
BITMAPINFO GradBitInfo;
pGradBits=(DWORD*) malloc(w*h*sizeof(DWORD));
memset(&GradBitInfo,0,sizeof(BITMAPINFO));
GradBitInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
GradBitInfo.bmiHeader.biWidth=w;
GradBitInfo.bmiHeader.biHeight=h;
GradBitInfo.bmiHeader.biPlanes=1;
GradBitInfo.bmiHeader.biBitCount=32;
GradBitInfo.bmiHeader.biCompression=BI_RGB;
if(nDir==0)
{
for(y=0;y<h;y++)
{
for(x=0;x<w;x++)
{
*(pGradBits+(y*w)+x)=PalVal[MulDiv(nNumColors,y,h)];
}
}
}
else if(nDir==1)
{
for(y=0;y<h;y++)
{
int l,r;
l=MulDiv((nNumColors/2),y,h);
r=l+(nNumColors/2)-1;
for(x=0;x<w;x++)
{
*(pGradBits+(y*w)+x)=PalVal[l+MulDiv((r-l),x,w)];
}
}
}
else if(nDir==2)
{
for(x=0;x<w;x++)
{
for(y=0;y<h;y++)
{
*(pGradBits+(y*w)+x)=PalVal[MulDiv(nNumColors,x,w)];
}
}
}
else if(nDir==3)
{
for(y=0;y<h;y++)
{
int l,r;
r=MulDiv((nNumColors/2),y,h);
l=r+(nNumColors/2)-1;
for(x=0;x<w;x++)
{
*(pGradBits+(y*w)+x)=PalVal[l+MulDiv((r-l),x,w)];
}
}
}
HBITMAP hBmp = CreateDIBitmap(hDC,&GradBitInfo.bmiHeader,CBM_INIT,
pGradBits,&GradBitInfo,DIB_RGB_COLORS);
free(pGradBits);
return hBmp;
}
//static member for keyboard operation, you can used it in you parent window
//it work with shortcut key
LRESULT CMenuXP::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu)
{
UINT iCurrentItem = (UINT)-1; // guaranteed higher than any command ID
CUIntArray arItemsMatched; // items that match the character typed
UINT nItem = pMenu->GetMenuItemCount();
for (UINT i=0; i< nItem; i++)
{
MENUITEMINFO info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
::GetMenuItemInfo(*pMenu, i, TRUE, &info);
CMenuXPItem *pData = (CMenuXPItem *)info.dwItemData;
if ((info.fType & MFT_OWNERDRAW) && pData && pData->IsMyData())
{
CString text = pData->m_strText;
int iAmpersand = text.Find('&');
if (iAmpersand >=0 && toupper(nChar)==toupper(text[iAmpersand+1]))
arItemsMatched.Add(i);
}
if (info.fState & MFS_HILITE)
iCurrentItem = i; // note index of current item
}
// arItemsMatched now contains indexes of items that match the char typed.
//
// * if none: beep
// * if one: execute it
// * if more than one: hilite next
//
UINT nFound = arItemsMatched.GetSize();
if (nFound == 0)
return 0;
else if (nFound==1)
return MAKELONG(arItemsMatched[0], MNC_EXECUTE);
// more than one found--return 1st one past current selected item;
UINT iSelect = 0;
for (i=0; i < nFound; i++) {
if (arItemsMatched[i] > iCurrentItem) {
iSelect = i;
break;
}
}
return MAKELONG(arItemsMatched[iSelect], MNC_SELECT);
}
void CMenuXP::DrawMenuText(CDC& dc, CRect rc, CString text,
COLORREF color)
{
CString left = text;
CString right;
int iTabPos = left.Find('\t');
if (iTabPos >= 0) {
right = left.Right(left.GetLength() - iTabPos - 1);
left = left.Left(iTabPos);
}
dc.SetTextColor(color);
dc.DrawText(left, &rc, DT_MYSTANDARD);
if (iTabPos > 0)
dc.DrawText(right, &rc, DT_MYSTANDARD|DT_RIGHT);
}
//find a popupmenu from a menuitem id
CMenuXP *CMenuXP::FindSubMenuFromID(DWORD dwID)
{
CMenuXP *pSubMenu;
CMenuXP *pResult;
for (UINT i=0; i<GetMenuItemCount(); i++)
{
if (GetMenuItemID(i) == dwID)
return this;
}
for (i=0; i<GetMenuItemCount(); i++)
{
pSubMenu = (CMenuXP *)GetSubMenu(i);
if (pSubMenu)
{
pResult = pSubMenu->FindSubMenuFromID(dwID);
if (pResult)
return pResult;
}
}
return NULL;
}
//Add a gradient sidebar, it must be the first item in a popupmenu
BOOL CMenuXP::AddSideBar(CMenuXPSideBar *pItem)
{
ASSERT(pItem);
m_bBreak = TRUE;
m_bBreakBar = FALSE;
return AppendMenu(MF_OWNERDRAW, pItem->m_dwID, (LPCTSTR)pItem);
}
//add a normal menuitem, an accelerator key could be specified, and the accel text will
//be added automatically
BOOL CMenuXP::AppendODMenu(UINT nFlags, CMenuXPItem *pItem, ACCEL *pAccel)
{
ASSERT(pItem);
nFlags |= MF_OWNERDRAW;
if (m_bBreak)
nFlags |= MF_MENUBREAK;
if (m_bBreakBar)
nFlags |= MF_MENUBARBREAK;
m_bBreak = m_bBreakBar = FALSE;
if (pAccel)
{
CBCGKeyHelper keyhelper(pAccel);
CString strAccel;
keyhelper.Format(strAccel);
if (strAccel.GetLength()>0)
{
pItem->m_strText += _T("\t");
pItem->m_strText += strAccel;
}
}
return AppendMenu(nFlags, pItem->m_dwID, (LPCTSTR)pItem);
}
//Add a separator line
BOOL CMenuXP::AppendSeparator(void)
{
m_bBreak = m_bBreakBar = FALSE;
CMenuXPSeparator *pItem = new CMenuXPSeparator;
return AppendMenu(MF_OWNERDRAW | MF_SEPARATOR, 0, (LPCTSTR)pItem);
}
//add a popup menu
BOOL CMenuXP::AppendODPopup(UINT nFlags, CMenuXP *pPopup, CMenuXPItem *pItem)
{
ASSERT(pPopup);
ASSERT(pItem);
nFlags |= MF_OWNERDRAW;
nFlags |= MF_POPUP;
if (m_bBreak)
nFlags |= MF_MENUBREAK;
if (m_bBreakBar)
nFlags |= MF_MENUBARBREAK;
m_bBreak = m_bBreakBar = FALSE;
return AppendMenu(nFlags, (UINT)pPopup->m_hMenu, (LPCTSTR)pItem);
}
//Change column, the next item added will be in the next column
void CMenuXP::Break(void)
{
m_bBreak = TRUE;
}
//same as Break(), except that a break line will appear between the two columns
void CMenuXP::BreakBar(void)
{
m_bBreakBar = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -