MFC重绘菜单栏控件

接下来是重头戏 菜单栏
实现菜单栏的背景,宽度,文字改变

.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也能实现 , 下拉框也可以通过内容改变也响应对应的映射,后面会陆续介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠风丶北枝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值