VC 创建一个图标菜单
2013-02-07 12:56
309 查看
步骤如下:
(1)创建一个基于对话框的应用程序
(2)在工作区选择资源视图选项卡,右击节点,选择Insert命令,插入一个对话框资源
(3)打开类向导,创建一个新类,类名为CMenuIcon,打开CMenuIcon的头文件,为该类添加一个基类CMenu;
(4)在CMenuIcon头文件定义一个数据结构,用来保存菜单项信息
(5)在CMenuItem 头文件声明成员变量
(6)像程序导入六个图标资源,并且在CMenIcon类构造函数中,初始化图像列表
(7)在CMenuIcon类中添加AttachMenu方法
(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::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);
}
运行结果如下:
(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);
}
运行结果如下:
相关文章推荐
- VC++创建一个自定义桌面图标
- 我创建了一个托盘图标,可以正常使用,点击右键打开菜单。问题是如果点击右键后不选择其中一个菜单项进行操作的话,它就总不消失。
- 【VC编程】笔记1--创建一个Win32的应用程序,并显示创建的窗口和菜单
- [转]使用VC/MFC创建一个线程池
- VC++ 如何创建一个线程并传递参数
- Creating Dialogbased Windows Application (3) / 创建基于对话框的Windows应用程序(三)Checkbox的应用、窗体置顶、设置图标 / VC++, Windows
- WPF 创建通知栏图标和菜单选项
- 14. 13 TrayIcon 创建一个托盘图标
- 使用VC++/ATL创建一个Office2K AddIn Com 组件
- QT 创建托盘图标和右键菜单
- VC如何对新创建的一个线程暂停或重启
- VC菜菜鸟-创建一个简单的多线程任务
- 使用VC/MFC创建一个线程池
- 创建一个VC把它变成导航器控制的根视图
- Android创建一个选项菜单
- TrayIcon 创建一个托盘图标
- MFC创建一个菜单弹到对话框
- 利用html+css创建一个二级导航菜单
- 2.1 创建一个 菜单命令的 插件
- VC 动态创建菜单