接下来是重头戏 菜单栏
实现菜单栏的背景,宽度,文字改变
.h文件
#pragma once
#include "afxwin.h"
class CMyMenu : public CMenu {
//自定义结构体
struct ItemInfo {
int m_id; //项id
int m_itemState; //项状态
HICON m_icon; //项图标
CString m_strText; //项文字
CString m_strShortcut; //项快捷键文字
int m_nFlags; //新建项的参数
};
public:
CMyMenu();
~CMyMenu();
//创建菜单
void AppendItem(UINT id, CString strText, CString strShortcut, UINT iconID, UINT nFlags);
//创建子菜单
void AppendSubMenu(UINT id, CMyMenu * subMenu, CString strText, UINT iconID, UINT nFlags);
//创建分隔符
void AppendSeparator(UINT nID, UINT nFlags);
//设定菜单各项的高度与宽度
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
//获取菜单项的Id和内容
void ChangeMenuItem(CString * pText[]);
//画菜单项
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//自定义类容器
CList<ItemInfo, ItemInfo> m_InfoList;
};
.cpp文件
#include "StdAfx.h"
#include "MyMenu.h"
#include "Resource.h"
#define NUM_ITEM_WIDTH 122 //宽
#define NUM_SEPARATOR_SPACE 20 //分隔符大小
#define NUM_ITEM_HEIGHT 25 //子菜单高
#define NUM_SEPARATOR_HEIGHT 20 //分隔符位置
#define COLOR_BK RGB(0,0,0) //菜单项背景颜色
#define COLOR_SEPARAROR RGB(0,0,0) //分隔框颜色
#define COLOR_DISABLE RGB(100,100,100) //不可选状态颜色
#define COLOR_SEL RGB(50,50,50) //点击后颜色
#define COLOR_TEXT RGB(255,255,255) //文字颜色
CMyMenu::CMyMenu(){
}
CMyMenu::~CMyMenu(){
}
class RepaintDlg : public CButton {
};
//创建菜单
void CMyMenu::AppendItem(UINT id, CString strText, CString strShortcut, UINT iconID, UINT nFlags) {
ItemInfo *info = new ItemInfo;
info->m_id = id;
if (iconID == 0){
info->m_icon = NULL;
}else{
info->m_icon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(iconID), IMAGE_ICON, 16, 16, 0);
//info->m_icon = AfxGetApp ()- >LoadIconA(iconID) ;
}
info->m_strText = strText;
info->m_strShortcut = strShortcut;
info->m_itemState = 1;
nFlags |= MF_OWNERDRAW;
info->m_nFlags = nFlags;
m_InfoList.AddTail(*info);
CMenu::AppendMenu(nFlags, info->m_id, (LPCTSTR)info);
}
//创建子菜单
void CMyMenu::AppendSubMenu(UINT id, CMyMenu* subMenu, CString strText, UINT iconID, UINT nFlags) {
ItemInfo *info = new ItemInfo;
info->m_id = id;
if (iconID == 0){
info->m_icon = NULL;
}else{
info->m_icon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(iconID), IMAGE_ICON, 16, 16, 0);
}
info->m_strText = strText;
info->m_strShortcut = "";
info->m_itemState = -1;
nFlags |= MF_POPUP | MF_OWNERDRAW;
info->m_nFlags = nFlags;
m_InfoList.AddTail(*info);
CMenu::AppendMenu(nFlags, (UINT)subMenu->GetSafeHmenu(), (LPCTSTR)info);
}
//创建分隔符
void CMyMenu::AppendSeparator(UINT nID, UINT nFlags) {
ItemInfo *info = new ItemInfo;
info->m_id = nID;
info->m_icon = NULL;
info->m_strText = "";
info->m_strShortcut = "";
info->m_itemState = 0;
nFlags |= MF_SEPARATOR | MF_OWNERDRAW;
info->m_nFlags = nFlags;
m_InfoList.AddTail(*info);
CMenu::AppendMenu(nFlags, 0, (LPCTSTR)info);
}
//设定菜单每项的高度与宽度
void CMyMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) {
// TODO: 添加您的代码以确定指定项的大小
lpMeasureItemStruct->itemWidth = NUM_ITEM_WIDTH;
//ItemInfo *info;
//info = (ItemInfo*)lpMeasureItemStruct->itemData;
//if(info->m_itemState == 0)
if (lpMeasureItemStruct->itemID == 0)
{
lpMeasureItemStruct->itemHeight = NUM_SEPARATOR_SPACE;
}
else
{
lpMeasureItemStruct->itemHeight = NUM_ITEM_HEIGHT;
}
}
//获取菜单项的ID和菜单项的内容
void CMyMenu::ChangeMenuItem(CString *pText[]) {
int itemCount = this->GetMenuItemCount();
for (int i = 0; i < itemCount; i++) {
UINT itemID = this->GetMenuItemID(i);
pText[i] = new CString;
if (NULL == pText[i]) return;
this->GetMenuString(i, *pText[i], MF_BYPOSITION);//获取菜单文本
//ModifyMenu函数最后一个参数对应DRAWITEMSTRUCT结构里的itemData变量
this->ModifyMenu(i, MF_OWNERDRAW | MF_BYPOSITION | MF_STRING | MF_CHECKED, itemID, (LPCTSTR)(*pText[i]));
//如果是一个弹出式菜单
if (itemID == -1) {
CMyMenu* pSubMenu = (CMyMenu*)(this->GetSubMenu(i));
if (NULL != pSubMenu) {
pSubMenu->ChangeMenuItem(pText);
}
}
}
}
//画菜单项
void CMyMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CString strText;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //获取菜单项的设备句柄
ItemInfo *info = (ItemInfo*)lpDrawItemStruct->itemData;
CRect rect(lpDrawItemStruct->rcItem);
//分隔条
if (info->m_itemState == 0){
pDC->FillSolidRect(rect, COLOR_BK);
CRect r = rect;
r.top = r.top;//r.Height() / 2 +
r.bottom = r.top + NUM_SEPARATOR_HEIGHT;
r.left += 5;
r.right -= 5;
pDC->Draw3dRect(r, COLOR_SEPARAROR, COLOR_SEPARAROR);
return;
}
//颜色变换
if (lpDrawItemStruct->itemState & ODS_GRAYED){
pDC->FillSolidRect(rect, COLOR_BK);
pDC->SetTextColor(COLOR_DISABLE);
}else if (lpDrawItemStruct->itemState & ODS_SELECTED){
//在菜单项上自绘矩形框的背景颜色
pDC->FillSolidRect(rect, COLOR_SEL);
//设置菜单文字颜色
pDC->SetTextColor(COLOR_TEXT);
}else{
pDC->FillSolidRect(rect, COLOR_BK);
pDC->SetTextColor(COLOR_TEXT);
}
pDC->SetBkMode(TRANSPARENT);
//画图标
if (info->m_icon != NULL){
DrawIconEx(pDC->m_hDC, rect.left , rect.top , info->m_icon, 16, 16, 0, NULL, DI_NORMAL);
}
//文字字体和字号设置
LOGFONT fontInfo;
pDC->GetCurrentFont()->GetLogFont(&fontInfo);
//字体大小
fontInfo.lfHeight = 20;
//字体
lstrcpy(fontInfo.lfFaceName, _T("华文细黑"));
CFont fontCh;
fontCh.CreateFontIndirect(&fontInfo);
pDC->SelectObject(&fontCh);
//子菜单
if (info->m_itemState == -1){
pDC->TextOut(rect.left + 36, rect.top + 1, info->m_strText, info->m_strText.GetLength());
//::ExcludeClipRect(pDC->m_hDC,rect.right-15,rect.top,rect.right,rect.bottom);
//DrawIconEx(pDC->m_hDC,rect.right-40,rect.top+7,AfxGetApp()->LoadIconA(IDI_ICON1),32,32,1,NULL,DI_NORMAL);
}else{
pDC->TextOut(rect.left + 36, rect.top + 1, info->m_strText, info->m_strText.GetLength());
//快捷键字体大小
fontInfo.lfHeight = 16;
//快捷键字体
CFont fontEn;
lstrcpy(fontInfo.lfFaceName, _T("Arial"));
fontEn.CreateFontIndirect(&fontInfo);
pDC->SelectObject(&fontEn);
pDC->TextOut(rect.left + 86, rect.top + 1, info->m_strShortcut, info->m_strShortcut.GetLength());
}
}
调用 先在Dlg.h文件中声明
//主菜单
CMyMenu myMenu;
//子菜单
CMyMenu ziMenu;
再在Dlg.cpp文件中
myMenu.CreateMenu();
myMenu.AppendItem(123, _T("帮助"), _T("F1"), IDR_MAINFRAME, TPM_LEFTALIGN);
myMenu.AppendItem(124, _T("测试"), _T("F2"), IDR_MAINFRAME, TPM_LEFTALIGN);
ziMenu.CreateMenu();
ziMenu.AppendItem(127, _T("刷新"), _T("F4"), IDR_MAINFRAME, TPM_LEFTALIGN);
myMenu.AppendSubMenu(126, &ziMenu, _T("子菜单"), IDR_MAINFRAME, TPM_LEFTALIGN);
SetMenu(&myMenu);
这是直接赋给了系统的默认菜单,但继承CMenu改的样式会与系统菜单冲突,所以高度改了也不起作用,高度只能改变子菜单的高度
这时候如果所需菜单的字体很大,那这种方法就不能够实现改变高度,但是可以通过其他方式模拟菜单栏 我这里可以提示一下,按钮+弹出菜单 , CMFCMenuButton也能实现 , 下拉框也可以通过内容改变也响应对应的映射,后面会陆续介绍