VC带图标的程序菜单
带图标的程序菜单
本文介绍在基於单文档程序中,如何实现带图标的程序菜单。如下:
1.
创建一个单文档工程:AddIconMenu
2.
这个工程里面用到了一个类来实现对程序菜单图标的添加以及颜色的设定等等。添加到工程。头文件如下:IconMenu.h
// IconMenu1.h: interface for the CIconMenu class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_)
#define AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
constintMAX_MENUCOUNT = 60,ITEMHEIGHT
= 26,ITEMWIDTH= 120;
//菜单项数量
/*************************************
CMenuItemInfo结构用于记录菜单项信息
*************************************/
structCMenuItemInfo
{
CStringm_ItemText;//菜单项文本
intm_IconIndex;//菜单项索引
intm_ItemID;//菜单标记
-2顶层菜单,-1弹出式菜单,0分隔条,其他普通菜单
};
classCIconMenu :
publicCMenu
{
public:
CMenuItemInfom_ItemLists[MAX_MENUCOUNT];
//菜单项信息
intm_index;
//临时索引
intm_iconindex;
CImageListm_imagelist;//存储菜单项图标
CIconMenu();
BOOLChangeMenuItem(CMenu*
m_menu,BOOLm_Toped
= FALSE);
BOOL AttatchMenu(HMENUm_hmenu);
voidDrawItemText(CDC*
m_pdc,LPSTRstr,CRectm_rect);
voidDrawTopMenu(CDC*
m_pdc,CRectm_rect,BOOLm_selected
= FALSE);
//绘制顶层菜单
voidDrawSeparater(CDC*
m_pdc,CRectm_rect);//绘制分隔条
voidDrawComMenu(CDC*
m_pdc,CRectm_rect,COLORREFm_fromcolor,COLORREFm_tocolor,
BOOLm_selected =
FALSE);
voidDrawMenuIcon(CDC*
m_pdc,CRectm_rect,intm_icon
);
//override memu's viutual method
virtual ~CIconMenu();
virtualvoidMeasureItem(
LPMEASUREITEMSTRUCTlpStruct );//设置菜单项大小
virtualvoidDrawItem(
LPDRAWITEMSTRUCTlpStruct );//重绘菜单项
};
#endif // !defined(AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_)
实现文件如下:
// IconMenu1.cpp: implementation of the CIconMenu class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "IconMenu.h"
//#include "IconMenu1.h"
#include "AddIconMenu.h"
#include "IconMenu.h"
#ifdef _DEBUG
#undef THIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#define newDEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CIconMenu::CIconMenu()
{
m_index= 0;
m_iconindex= 0;
//创建图像列表
m_imagelist.Create(16,16,ILC_COLOR24|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));
m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON7));
m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON8));
m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON9));
m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON10));
}
CIconMenu::~CIconMenu()
{
m_imagelist.Detach();
}
BOOL CIconMenu::AttatchMenu(HMENUm_hmenu)
{
this->Attach(m_hmenu);
returnTRUE;
}
BOOLCIconMenu::ChangeMenuItem(CMenu*
m_menu,BOOLm_Toped)
{
if (m_menu
!= NULL)
{
intm_itemcount =
m_menu->GetMenuItemCount();
for (inti=0;i<m_itemcount;i++)
{
m_menu->GetMenuString(i,m_ItemLists[m_index].m_ItemText,MF_BYPOSITION);
intm_itemID =
m_menu->GetMenuItemID(i);
if (m_itemID==-1
&& m_Toped)
{
m_itemID = -2;//顶层菜单
};
m_ItemLists[m_index].m_ItemID
= m_itemID;
if (m_itemID>0)
{
m_ItemLists[m_index].m_IconIndex=
m_iconindex;
m_iconindex+=1;
}
m_menu->ModifyMenu(i,MF_OWNERDRAW|MF_BYPOSITION
|MF_STRING,m_ItemLists[m_index].m_ItemID,(LPSTR)&(m_ItemLists[m_index]));
m_index+=1;
CMenu*
m_subMenu =
m_menu->GetSubMenu(i);
if (m_subMenu)
{
ChangeMenuItem(m_subMenu);
}
}
}
returnTRUE ;
}
voidCIconMenu::MeasureItem(
LPMEASUREITEMSTRUCTlpStruct )
{
if (lpStruct->CtlType==ODT_MENU)
{
lpStruct->itemHeight
= ITEMHEIGHT;
lpStruct->itemWidth
= ITEMWIDTH;
CMenuItemInfo*
m_iteminfo;
m_iteminfo = (CMenuItemInfo*)lpStruct->itemData;
lpStruct->itemWidth
= ((CMenuItemInfo*)lpStruct->itemData)->m_ItemText.GetLength()*10;
switch(m_iteminfo->m_ItemID)
{
case 0:
//分隔条
{
lpStruct->itemHeight = 1;
break;
}
}
}
}
voidCIconMenu::DrawItem(
LPDRAWITEMSTRUCTlpStruct )
{
if (lpStruct->CtlType==ODT_MENU)
{
if(lpStruct->itemData
== NULL)
return;
unsignedintm_state
= lpStruct->itemState;
CDC*
m_dc =
CDC::FromHandle(lpStruct->hDC);
//m_dc.Attach(lpStruct->hDC);
CStringstr = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemText;
LPSTRm_str =
str.GetBuffer(str.GetLength());
intm_itemID = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemID;
intm_itemicon = ((CMenuItemInfo*)(lpStruct->itemData))->m_IconIndex;
CRectm_rect =
lpStruct->rcItem;
m_dc->SetBkMode(TRANSPARENT);
switch(m_itemID)
{
case -2:
{
DrawTopMenu(m_dc,m_rect,(m_state&ODS_SELECTED)||(m_state&0x0040));
//0x0040 ==ODS_HOTLIGHT
DrawItemText(m_dc,m_str,m_rect);
break;
}
case -1:
{
DrawItemText(m_dc,m_str,m_rect);
break;
}
case 0:
{
DrawSeparater(m_dc,m_rect);
break;
}
default:
{
DrawComMenu(m_dc,m_rect,0xfaa0,0xf00ff,m_state&ODS_SELECTED);
DrawItemText(m_dc,m_str,m_rect);
DrawMenuIcon(m_dc,m_rect,m_itemicon);
break;
}
}
}
}
/*************************************************************
功能描述:
绘制菜单项文本
参数说明: m_pdc标识画布对象,str标识菜单文本,m_rect标识菜单区域
*************************************************************/
voidCIconMenu::DrawItemText(CDC*
m_pdc,LPSTRstr,CRectm_rect)
{
m_rect.DeflateRect(20,0);
m_pdc->DrawText(str,m_rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);
}
voidCIconMenu::DrawTopMenu(CDC*
m_pdc,CRectm_rect,BOOLm_selected
)
{
if (m_selected)
{
m_pdc->SelectStockObject(BLACK_PEN);
m_pdc->Rectangle(&m_rect);
m_rect.DeflateRect(1,1);
m_pdc->FillSolidRect(m_rect,RGB(150,
185, 255));
}
else
{
CRectrect;
AfxGetMainWnd()->GetClientRect(rect);
rect.top
= m_rect.top;
rect.bottom
= m_rect.bottom;
rect.left=
360;
rect.right
+=4;
//CRect c_rect(m_rect);
m_pdc->FillSolidRect(&rect,RGB(200,187,
255));
m_pdc->FillSolidRect(&m_rect,RGB(200,187,
255));
//m_pdc->SelectStockObject(BLACK_PEN);
//m_pdc->FillSolidRect(m_rect,RGB(100, 185, 255));
}
}
voidCIconMenu::DrawSeparater(CDC*
m_pdc,CRectm_rect)
{
if (m_pdc
!= NULL)
{
m_pdc->Draw3dRect(m_rect,RGB(255,0,0),RGB(0,0,255));
}
}
voidCIconMenu::DrawComMenu(CDC*
m_pdc,CRectm_rect,COLORREFm_fromcolor,COLORREFm_tocolor,
BOOLm_selected )
{
if (m_selected)
{
m_pdc->Rectangle(m_rect);
m_rect.DeflateRect(1,1);
intr1,g1,b1;
//读取渐变起点的颜色值
r1 =
GetRValue(m_fromcolor);
g1 =
GetGValue(m_fromcolor);
b1 =
GetBValue(m_fromcolor);
intr2,g2,b2;
//读取渐变终点的颜色值
r2 =
GetRValue(m_tocolor);
g2 =
GetGValue(m_tocolor);
b2 =
GetBValue(m_tocolor);
float r3,g3,b3;//菜单区域水平方向每个点RGB值应该变化的度(范围)
r3 = ((float)(r2-r1))
/ (float)(m_rect.Height());
g3 = (float)(g2-g1)/(float)(m_rect.Height());
b3 = (float)(b2-b1)/(float)(m_rect.Height());
COLORREFr,g,b;//菜单区域水平方向每个点的颜色值
CPen*
m_oldpen ;
for (inti
= m_rect.top;i<m_rect.bottom;i++)
{
r =
r1+(int)r3*(i-m_rect.top);
g =
g1+(int)g3*(i-m_rect.top);
b =
b1+ (int)b3*(i-m_rect.top);
CPenm_pen (PS_SOLID,1,RGB(r,g,b));
m_oldpen =
m_pdc->SelectObject(&m_pen);
m_pdc->MoveTo(m_rect.left,i);
m_pdc->LineTo(m_rect.right,i);
}
m_pdc->SelectObject(m_oldpen);
}
else
{
m_pdc->FillSolidRect(m_rect,RGB(0x000000F9,
0x000000F8, 0x000000F7));
}
}
voidCIconMenu::DrawMenuIcon(CDC*
m_pdc,CRectm_rect,intm_icon
)
{
m_imagelist.Draw(m_pdc,m_icon,CPoint(m_rect.left+2,m_rect.top+4),ILD_TRANSPARENT);
}
当然这里面需要的图标资源,自己拷贝到res目录下即可。
3.
然后在文档类中添加SetTitle消息,可以修改标题栏信息,如下:
lpszTitle =
"基於单文档结构的带图标的程序菜单";
4. CMainFrame中添加一个上述类的变量:
CIconMenum_Menu;
CMainFrame的OnCreate函数中,添加经过上述类设置的菜单,代码如下:
m_Menu.AttatchMenu(this->GetMenu()->GetSafeHmenu());
m_Menu.ChangeMenuItem(&m_Menu,TRUE);
this->SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1),TRUE);
this->SetTitle("IconMenuExample");
5.
分别为CMainFrame添加,如下两个消息函数WM_DRAWITEM()和WM_MEASUREITEM(),不知道为什么,我的消息函数中没有,所以就手工添加了。在消息映射中添加如下:
ON_WM_DRAWITEM()
ON_WM_MEASUREITEM()
然后添加函数及实现如下:
voidCMainFrame::OnDrawItem(intnIDCtl,
LPDRAWITEMSTRUCTlpDrawItemStruct)
{
m_Menu.DrawItem(lpDrawItemStruct);
}
voidCMainFrame::OnMeasureItem(intnIDCtl,
LPMEASUREITEMSTRUCTlpMeasureItemStruct)
{
m_Menu.MeasureItem(lpMeasureItemStruct);
}
OK,好了,直接运行,即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.