7.VC(ui)-无边框/有边框菜单自绘

菜单自绘分为两类,一类为无边框,一类为有边框,无边框是通过hook实现的,有边框菜单:7.VC(ui)-无边框/有边框菜单自绘_第1张图片

无边框菜单:7.VC(ui)-无边框/有边框菜单自绘_第2张图片

实现菜单自绘原理很简单:

1.给每一项都加上MF_OWNERDRAW属性

实现代码:void CMyMenu::ChangeToOwnerDraw(CMyMenu *pMyMenu) { CString str; CMyMenu* pMenu; int iMenuCount = pMyMenu->GetMenuItemCount(); UINT nID; for (int i=0; i<iMenuCount; i++) { pMyMenu->GetMenuString(i, str, MF_BYPOSITION); pMenu = 0; if (pMyMenu->GetSubMenu(i)) { pMyMenu->ModifyMenu(i, MF_BYPOSITION | MF_OWNERDRAW, 0,(LPCTSTR)str); pMenu = new CMyMenu; HMENU hMenu = pMyMenu->GetSubMenu(i)->GetSafeHmenu(); pMenu->Attach(hMenu); m_pMenuList.push_back(pMenu); ChangeToOwnerDraw(pMenu); } else { nID = pMyMenu->GetMenuItemID(i); pMyMenu->ModifyMenu(i, MF_BYPOSITION | MF_OWNERDRAW, (UINT)nID,(LPCTSTR)str); } } }

这里如果有二级菜单,就要把new出来的menu最后释放掉,我用了个pstd::vector<CMyMenu*>   m_pMenuList ;来存储,最后在析构函数中统一释放掉

2.重载MeasureItem确定菜单项的宽度和高度

实现代码:void CMyMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight =m_MenuHight; lpMeasureItemStruct->itemWidth=m_MenuWidth; }

3.重载DrawItem自绘菜单

实现代码:

void CMyMenu::DrawItem(LPDRAWITEMSTRUCT lpDIS) { CDC* pDC = CDC::FromHandle(lpDIS->hDC); CRect rc(lpDIS->rcItem); CRect rcBgFrameLeft; rcBgFrameLeft.SetRect(rc.left,rc.top,rc.left+1,rc.bottom); CRect rcBgFrameRight; rcBgFrameRight.SetRect(rc.right-1,rc.top,rc.right,rc.bottom); CRect rcIsSelected; rcIsSelected.SetRect(rc.left+1,rc.top+1,rc.right-1,rc.bottom-1); CRect rcBgTop; rcBgTop.SetRect(rc.left,rc.top,rc.right,rc.top+1); CRect rcBgBottom ; rcBgBottom.SetRect(rc.left,rc.bottom-1,rc.right+1,rc.bottom) ; pDC->FillSolidRect(&rcBgFrameLeft,RGB(159,160,157)); pDC->FillSolidRect(&rcBgFrameRight,RGB(159,160,157)); pDC->FillSolidRect(&rcBgTop,RGB(169,169,169)); pDC->FillSolidRect(&rcBgBottom,RGB(169,169,169)); CString str; GetMenuString(lpDIS->itemID,str,MF_BYCOMMAND); //str = (LPCTSTR)lpDIS->itemData; CFont *pOldFont=pDC->SelectObject(&font); if ((lpDIS->itemState & ODS_SELECTED) && (lpDIS->itemAction & (ODA_SELECT | ODA_DRAWENTIRE))) { UINT nFlags = GetMenuState(lpDIS->itemID,MF_BYCOMMAND) ; if (nFlags&MF_GRAYED) { //..... } else if (nFlags&MF_DISABLED) { pDC->FillSolidRect(&rcIsSelected,RGB(188,237,79)); pDC->SetTextColor(RGB(182,183,182)); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(str,&rcIsSelected,DT_VCENTER|DT_SINGLELINE|DT_CENTER); } else { pDC->FillSolidRect(&rcIsSelected,RGB(188,237,79)); pDC->SetTextColor(RGB(120,167,47)); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(str,&rcIsSelected,DT_VCENTER|DT_SINGLELINE|DT_CENTER); } } else { UINT nFlags = GetMenuState(lpDIS->itemID,MF_BYCOMMAND) ; if ((nFlags&MF_GRAYED)|(nFlags&MF_DISABLED)) { pDC->FillSolidRect(&rcIsSelected,RGB(224,224,224)); pDC->SetTextColor(RGB(182,183,182)); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(str,&rcIsSelected,DT_VCENTER|DT_SINGLELINE|DT_CENTER); } else { pDC->FillSolidRect(&rcIsSelected,RGB(224,224,224)); pDC->SetTextColor(RGB(138,157,119)); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(str,&rcIsSelected,DT_VCENTER|DT_SINGLELINE|DT_CENTER); } } }

注意:如果你不想调用ChangeToOwnerDraw来统一添加MF_OWNERDRAW,你可以直接在AppendMenu时就直接加入这一属性,

如:m_pMenu->AppendMenu( MF_STRING|MF_OWNERDRAW,IDM_PHONE_PUP0,_T("0000000"));

如果你发现不能显示字体,请把DrawItem中的GetMenuString(lpDIS->itemID,str,MF_BYCOMMAND);用str = (LPCTSTR)lpDIS->itemData;代替.

下面说说怎么去掉边框,

在App中加入类IntMenu,在应用程序创建前调用

IntMenu menu ;

 menu.UnInstallHook();
 menu.InstallHook();
 menu.Lapha=0;

即可

本人小菜,随手写的,很多不周,别拍砖,3Q。

====〉源代码下载

你可能感兴趣的:(String,存储,menu,hook)