VC 创建一个图标菜单

来源:互联网 发布:数据结构查找算法总结 编辑:程序博客网 时间:2024/05/16 14:48

步骤如下:

(1)创建一个基于对话框的应用程序

(2)在工作区选择资源视图选项卡,右击节点,选择Insert命令,插入一个对话框资源

(3)打开类向导,创建一个新类,类名为CMenuIcon,打开CMenuIcon的头文件,为该类添加一个基类CMenu;

(4)在CMenuIcon头文件定义一个数据结构,用来保存菜单项信息

struct CMenuItem {CString m_ItemText;//菜单项文本int     m_IconIndex;//菜单项索引int     m_ItemID;//菜单标记,-1为顶层菜单,0为分割条,其他为普通菜单项};const int MAX_MENUCOUNT = 60,ITEMHEIGHT = 30,ITEMWIDTH= 80; //菜单项数量(图标数,高度,宽度增量)

(5)在CMenuItem 头文件声明成员变量

CMenuItemm_ItemLists[MAX_MENUCOUNT];//菜单项信息intm_Index;//临时索引intm_IconIndex;//菜单项图标索引CImageListm_ImageList;//存储菜单项图标

(6)像程序导入六个图标资源,并且在CMenIcon类构造函数中,初始化图像列表

CMenuIcon::CMenuIcon(){m_Index = 0;m_IconIndex = 0;m_ImageList.Create(26,26,ILC_COLOR32|ILC_MASK,0,0);//创建图像列表m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//添加图标m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));//添加图标m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON3));//添加图标m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON4));//添加图标m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON5));//添加图标m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON6));//添加图标}

(7)在CMenuIcon类中添加AttachMenu方法

BOOL CMenuIcon::AttatchMenu(UINT m_uID){LoadMenu(m_uID);//加载菜单资源return TRUE;}
(8)在CMenuIcon类中添加MenuItem方法,该方法用来修改菜单项信息

// 该方法用于修改菜单项信息,使其包含MF_OWNERDRAW风格,并将菜单项信息存储在m_ItenLists成员变量中BOOL CMenuIcon::MenuItem(CMenu* pMenu){if (pMenu!=NULL)//判断菜单句柄是否为空{int m_Count = pMenu->GetMenuItemCount();//获得菜单数for (int i = 0 ; i < m_Count ; i++){//获得菜单文本pMenu->GetMenuString(i,m_ItemLists[m_Index].m_ItemText,MF_BYPOSITION);int m_itemID = pMenu->GetMenuItemID(i);//获得菜单IDm_ItemLists[m_Index].m_ItemID = m_itemID;//将菜单ID保存在变量中if (m_itemID > 0){m_ItemLists[m_Index].m_IconIndex = m_IconIndex;//将图标索引值赋给变量m_IconIndex++;//下一个图标索引}//修改菜单信息pMenu->ModifyMenu(i , MF_OWNERDRAW|MF_BYPOSITION|MF_STRING ,m_ItemLists[m_Index].m_ItemID , (LPCTSTR)&(m_ItemLists[m_Index]));m_Index++;CMenu* m_SubMenu = pMenu->GetSubMenu(i);//获取弹出式菜单项if (m_SubMenu){MenuItem(m_SubMenu);//递归调用MenuItem方法}}}return  TRUE;}
(9)重载CMenIcon类的MeasureItem虚拟方法,计算菜单项的大小

void CMenuIcon::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct){// TODO:  添加您的代码以确定指定项的大小if (lpMeasureItemStruct->CtlType == ODT_MENU)//是否是自绘菜单{lpMeasureItemStruct->itemHeight = ITEMHEIGHT;//菜单项高度//lpMeasureItemStruct->itemWidth = ITEMWIDTH;//菜单项的宽度CMenuItem* m_item;m_item = (CMenuItem*)lpMeasureItemStruct->itemData;//获得菜单项数据//设置菜单项宽度lpMeasureItemStruct->itemWidth = ((CMenuItem*)lpMeasureItemStruct->itemData)->m_ItemText.GetLength()*10+ITEMWIDTH;if (m_item->m_ItemID == 0)//判断是否为分割条{lpMeasureItemStruct->itemHeight = 2;//将分割条的高度设为2}}}

(10)在CMenuIcon类中添加DrawItemText成员,用于绘制菜单项文本

void CMenuIcon::DrawItemText(CDC* pDC, LPCTSTR Str, CRect Rect){pDC->DrawText(Str,Rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);//绘制菜单项文本}

(11)在CMenuIcon类中添加DrawItemIcon函数,用于绘制图标

void CMenuIcon::DrawItemIcon(CDC* pDC, CRect Rect, int Icon){m_ImageList.Draw(pDC,Icon,CPoint(Rect.left+2,Rect.top+4),ILD_TRANSPARENT);//绘制菜单项图标}
(12)在CMenuIcon类中添加DrawSeparater,用户绘制分割条
void CMenuIcon::DrawSeparater(CDC* pDC, CRect Rect){pDC->Draw3dRect(Rect,RGB(255,0,255),RGB(255,0,255));//使用紫色绘制分割条}
(13)在CMenuIcon类中添加DrawTopMenu,用于绘制顶层菜单

void CMenuIcon::DrawTopMenu(CDC* pDC, CRect Rect, bool Selected){if (Selected)//判断菜单项是否选中{pDC->Rectangle(&Rect);//绘制矩形区域Rect.DeflateRect(1,1);//设置区域大小pDC->FillSolidRect(Rect,RGB(190,170,220));//填充矩形区域}else{pDC->FillSolidRect(&Rect,RGB(192,192,192));//用另一种颜色填充矩形}}
(14)在CMenIcon类中添加DrawComMenu成员函数,绘制普通菜单项

void CMenuIcon::DrawComMenu(CDC* pDC, CRect Rect, bool Selected){if (Selected){pDC->Rectangle(Rect);//绘制矩形区域Rect.DeflateRect(1,1);//设置区域大小pDC->FillSolidRect(Rect,RGB(255,0,0));//填充矩形区域}else{pDC->FillSolidRect(Rect,RGB(255,255,255));//用另一种颜色填充矩形}}

(15)重载CMenuIcon类的DrawItem方法,根据菜单项不不同状态绘制菜单项

void CMenuIcon::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){// TODO:  添加您的代码以绘制指定项if (lpDrawItemStruct->CtlType == ODT_MENU)//判断是否重绘菜单{if (lpDrawItemStruct->itemData == NULL) {return;//如果数据为空则结束}}unsigned int m_state = lpDrawItemStruct->itemState;//菜单项状态CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);//获得设备上下文DCCString str = ((CMenuItem*)(lpDrawItemStruct->itemData))->m_ItemText;//菜单项文本LPCTSTR m_str = str.GetBuffer(str.GetLength());//获得文本长度int m_itemID = ((CMenuItem*)(lpDrawItemStruct->itemData))->m_ItemID;//获得菜单索引int m_itemicon = ((CMenuItem*)(lpDrawItemStruct->itemData))->m_IconIndex;  //获得图标索引CRect m_rect = lpDrawItemStruct->rcItem;//获得菜单区域pDC->SetBkMode(TRANSPARENT);//设置文本背景透明switch (m_itemID){case -1://顶层菜单//绘制顶层菜单DrawTopMenu(pDC,m_rect,(m_state&ODS_SELECTED)||(m_state&0x0040));DrawItemText(pDC,m_str,m_rect);//绘制菜单文本break;case 0:DrawSeparater(pDC,m_rect);//绘制分割条break;default:DrawComMenu(pDC,m_rect,m_state&ODS_SELECTED);//绘制菜单项DrawItemText(pDC,m_str,m_rect);//绘制菜单文本DrawItemIcon(pDC,m_rect,m_itemicon);//绘制菜单图标break;}}
(16)在对话框头文件中声明CMenuIcon类对象m_Menu;

(17)在对话框OnInitDialog方法中加载菜单资源,并设置菜单项

// TODO: 在此添加额外的初始化代码m_Menu.AttatchMenu(IDR_MENU1);//加载菜单资源m_Menu.MenuItem(&m_Menu);//修改菜单项this->SetMenu(&m_Menu);//将菜单关联到窗口

(18)重载对话框的OnDrawItem方法,在方法中调用菜单类中的DrawItem()方法

void CMy83Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct){// TODO: 在此添加消息处理程序代码和/或调用默认值m_Menu.DrawItem(lpDrawItemStruct);CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct);}

(19)重载对话框的OnMeasureItem方法,在该方法中调用菜单栏的MeasureItem方法

void CMy83Dlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct){// TODO: 在此添加消息处理程序代码和/或调用默认值m_Menu.MeasureItem(lpMeasureItemStruct);CDialogEx::OnMeasureItem(nIDCtl, lpMeasureItemStruct);}

运行结果如下:








原创粉丝点击