!接下来几章内容将以程序示例Colors来介绍自制菜单、层叠菜单和上下文菜单的有关内容;
1. 为什么选择自制菜单项:
1) 需求:有时候菜单项如果是一张图片,会比文字描述更加直观,接下来的程序Colors就是将“颜色”菜单项变成一条条样本色条显示出来;
2) 以上这种需求就不属于传统的字符串菜单项了,此时菜单项变成了图像,可以用两种方法达到这种效果,一种是AppendMenu还有一个传BitMap的版本,图像直接用位图表示,但是这种方法有一个缺点,那就是位图尺寸固定很难灵活变化,还有一种就是自制菜单项,完全自己画,灵活扩展性强,这里我们介绍后者;
2. 使用自制菜单项的基本步骤:
1) 设置菜单项为自制菜单类型;
2) 设置自制菜单项的尺寸,因为后面的绘画都要局限在该尺寸中进行;
3) 绘制菜单项;
3. 设置菜单项为自制菜单项:
1) 由于CMenu模板不支持自制菜单项,因此不能用CreateMenu等系列函数实现自制菜单项,同样VC++的资源编辑器以及资源脚本也不支持自制菜单项;
2) 设置自制菜单项唯一的办法就是通过ModifyMenu函数来实现,因此还是必须先加载、挂接,然后再设置成自制菜单项;
3) 由于加载和挂接都是在CXxxApp的InitInstance中进行,因此Modify成自制菜单项也要在这个位置进行,看一下Colors程序中的示例:
BOOL CColorsApp::InitInstance()
{
// Standard initialization
// Change the registry key under which our settings are stored.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
CMainFrame* pFrame = new CMainFrame;
m_pMainWnd = pFrame;
// create and load the frame with its resources
pFrame->LoadFrame(IDR_MAINFRAME,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
NULL);
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
//
// Convert the items in the Color menu to owner-draw.
//
CMenu* pMenu = pFrame->GetMenu ();
ASSERT (pMenu != NULL); // 一定不能为空
for (int i=0; i<5; i++) // 第二个参数不设定nPosition的定义则默认为MF_BYCOMMAND
pMenu->ModifyMenu (ID_COLOR_RED + i, MF_OWNERDRAW,
ID_COLOR_RED + i);
return TRUE;
}
4. 设置自制菜单项的尺寸:
1) 自制菜单项中的内容是随意画的,所以在画之前一定要先确定菜单项的尺寸,后面的绘制都将限制在该尺寸当中;
2) 但是尺寸只要确定一次就行了,即在程序打开后第一次画菜单项之前,此时会为每一个自制菜单项产生一个WM_MEASUREITEM消息给主框架窗口(菜单挂接的窗口),用户在该相应函数中定义菜单项的尺寸并保存在MFC内部维护的MEASUREITEMSTRUCT结构中,之后每次重画都不会再产生WM_MEASUREITEM消息要求你设置尺寸,而是直接从该结构中读取尺寸进行绘制,因此设置尺寸只需要一次,这样既节省时间也节省资源;
3) 先看一下Colors程序中的示例是怎么做的:
ON_WM_MEASUREITEM()
void CMainFrame::OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
{
lpmis->itemWidth = ::GetSystemMetrics (SM_CYMENU) * 4;
lpmis->itemHeight = ::G