您的位置:首页 > 其它

VC 创建一个图标菜单

2013-02-07 12:56 309 查看
步骤如下:

(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 头文件声明成员变量

CMenuItem	m_ItemLists[MAX_MENUCOUNT];		//菜单项信息
int			m_Index;						//临时索引
int			m_IconIndex;					//菜单项图标索引
CImageList	m_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);		//获得菜单ID
m_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); //获得设备上下文DC
CString 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);
}

运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: