MFC 菜单自绘

2023-11-11 11:18
文章标签 mfc 菜单 自绘

本文主要是介绍MFC 菜单自绘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、要想自绘菜单,首要的就是子类化菜单类,拥有自己的自定义菜单类。

也有大神子类化CWnd。。。这应该属于高度定制了,表示驾驭不了,还是看子类化的吧。 关于自绘菜单类很多大神有分享,由于自己水平有限,也只能是拿来主义。

1.总结起来,这个类通常必需要重写的方法有

1.1、BOOL CMyMenu::OnDrawItem(int nIDCtl,DRAWITEMSTRUCT*pDIS)

该方法用于自绘制每一菜单项,在菜单显示,刷新时调用。通常做法是根据菜单项属性,判断属于哪一类菜单,再决定如何绘制,一般分为顶层菜单项,一般菜单项、分隔符、系统菜单等。

1.2、BOOL CMyMenu:OnMeasureItem(int nIDCtl,MEASUREITEMSTRUCT*pMIS)

该方法用于设置菜单项的尺寸,在菜单创建时调用。如可以简单地设置,菜单项宽高为

        pMIS->itemHeight    =20;pMIS->itemWidth     =200;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

2.重写了最重要的两个类,就有了绘制菜单的基础工具,但是还需要我们添加具体的绘制方法 ,如绘制顶层菜单的方法,绘制一般菜单、绘制分割符、绘制系统菜单图标、绘制背景等。

3.有了以上方法,我们绘制菜单的工具算是齐备了,但是还少一些东西,那就是菜单的原料了,比如配色,字体,图标等属性。

另外:这些类中比较重要的是有一套绘制逻辑,比如如何匹配要加载的图标,根据菜单属性分类绘制顶层菜单,一般菜单等不同菜单项的逻辑等。不过大牛已经有现成的给我了,大家可以参考资源中的不同实现方法。

参考代码1:http://download.csdn.net/detail/u010679316/9552044 
参考代码2:http://download.csdn.net/download/exceed_me/2750768


二、在MFC中使用自定义菜单类

1.在应用菜单窗口中,如CMainFrame添加消息映射:
ON_WM_DRAWITEM()
ON_WM_MEASUREITEM()
  • 1
  • 2
  • 1
  • 2
2.然后重写它们对应的函数:
void CMainFrame::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{//CustomMenu为自定义菜单类的实例m_CustomMenu.DrawItem(lpDrawItemStruct);
}
void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{m_CustomMenu.MeasureItem(lpMeasureItemStruct);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.创建自定义菜单类实例,将其与主窗口绑定 
m_CustomMenu.Attach(this->GetMenu()->GetSafeHmenu()); 
或者 SetMenu(m_CustomMenu);

这样,自绘菜单基本上就算完成了


三、相关细节的处理

虽然有前人铺路,但是完全拿来用做项目的应用总是不现实的,总有些效果还需要自己来调。。。 
现在来看,比较容易做到的是改变菜单项的背景,字体的颜色和字号,菜单贴图等。但是整体看来,菜单效果并不理想,主要在以下几个方面:

1.菜单栏背景的绘制

网上的例程中,有些只做了顶层每个菜单项的背景设置,而菜单右侧仍然是系统默认的丑陋的背景色; 
如图: 
这里写图片描述
有一种关于菜单栏背景色绘制的思路是,在绘制顶层菜单时,额外绘制菜单的右侧区域,虽然可以实现显示效果,但是感觉上这样做不科学,额外产生多次绘制。重要的是系统默认背景色如果和你自己设置的菜单项背景色差很大的话,当频繁刷新菜单,系统配色和你的配色切换时就会产生闪烁,这不是我们想要的。 
所以,如果有一种办法,能够在绘制菜单项前就将菜单栏背景色设置为同样的颜色,就会避免了闪烁了。具体如何做呢?上代码:

::MENUINFO mnInfo;
mnInfo.cbSize = sizeof(MENUINFO);
mnInfo.fMask = MIM_BACKGROUND;
mnInfo.hbrBack = (HBRUSH)mnBgBrush;//mnBgBrush 背景色画刷
::SetMenuInfo(menu->m_hMenu, &mnInfo);//menu指向要绘制的菜单
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

也就是说,需要在绘制每项菜单时,先价格整个菜单背景被设置为相同颜色,就不会出现菜单重绘产生的闪烁的问题了。上图: 
这里写图片描述
另外:这个设置还意外地解决了弹出菜单默认的粗边框的问题:如图我们可以看到示例程序中,如果不执行上述代码,只是将每个菜单项的背景设置为了黑色,弹出菜单项会显示一个比较丑的粗的白色边框,这个边框颜色应该是系统默认色。 
这里写图片描述 
之前查了好久,去掉这个粗边框的办法。虽然网上有说可以用消息钩子重绘非客户等一些办法,但是这些总会产生一些其他绘制问题,最终没有使用。但是只要在绘制菜单项背景时确保菜单的背景已经设置为和菜单项相似的颜色,就会只显示一个细边框,看起来就比较舒服了。如图: 
这里写图片描述 
其实,如果我们将绘制菜单项的背景色和上述代码中背景画刷的颜色设为不同颜色就会看到,菜单绘制的具体过程。如果背景画刷为红色,可以看到: 
这里写代码片 
经过单步调试发现,菜单首先获取画刷,绘制一个背景,然后再绘制每一菜单项。我们之前看到的粗边框其实有一部分是整个菜单的背景,也就是没有被单个菜单项遮挡的部分。 
因为自己不清楚菜单绘制机制,走了好多弯路。。。

2、菜单快捷键显示

完成自绘之后,菜单的快捷键均显示下划线。我们希望的是,在菜单没有获得焦点时,不能响应快捷键,不显示下划线,当按下Alt键时才显示下划线。 
解决思路:在菜单没有焦点时,将菜单文本中的“&”去掉,也就不显示下划线。在获得焦点时,显示下划线。 
绘制文本的代码:

if(state &ODS_NOACCEL)
{//没有快捷键,不显示下划线CString str = pText;//pText 为菜单文本str.Replace(_T("&"),_T(""));DrawItemText(pCdc,str,Rect,state,TRUE);//绘制文本
}
else
{//有快捷键,显示下划线DrawItemText(pCdc,pText,Rect,state,TRUE);//绘制文本
}

这篇关于MFC 菜单自绘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/389672

相关文章

2_为MFC程序添加菜单

在MFC中添加菜单栏 1,双击资源文件,显示资源视图,点击Menu插入Menu菜单,编辑菜单的ID,自己取名字。 2,点击“请在此处键入”添加菜单选项,输入&E,E的下面就会产生下划线;在产生的弹出菜单中继续编辑,并且可以添加事件处理函数; 在弹出菜单的任意位置,鼠标右键,弹出的菜单中选择“插入分隔符”,即可产生分隔符 3,在你设计的Dialog窗口的属性栏,选择Menu后面的

怎么优化ArcEngine组件开发mfc程序界面?

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 问题描述   这种VS2015 + ArcEngine10.2开发的mfc小程序怎么优化界面,使系统看上去更美观 如上问题有来自我自身项目开发,有的收集网站

移植对话框MFC

VC版 MFC程序对话框资源移植 以下均拷贝自上面,仅用来记录 (部分有删除) 法1: Eg:将B工程调试好的对话框移植到A工程中 1.资源移植         1.1  在2017打开B工程,在工作区Resource标签页中选中Dialog文件夹下的资源文件,按Ctrl+C或点击Edit->Copy.         1.2. 关闭当前工程,注意不要关闭VC6,打开B工程(File

把Sublime Text 2 加入右键菜单(带图标), Edit with Sublime Text

Sublime Text 2 是现在很受大家欢迎的编辑器了,不仅是在web前端,在书定简单的php、Js等代码时,也是相当的好用,再配合多种的插件和新颖的界面,更是让人欲罢不能。 在使用时,我们通过喜欢打开一个文件的时候,右击再选择打开程序,比如会用记事本、Notedpad++之类的,这时如果把Sublime Text也加入到其中毕竟会方便不少,在找了一番后,实验成功,效果如下: 实现

vue+elementui搭建后台管理界面(5递归生成侧栏路由) vue定义定义多级路由菜单

有一个菜单树,顶层菜单下面有多个子菜单,子菜单下还有子菜单。。。 这时候就要用递归处理 1 定义多级菜单 修改 src/router/index.js 的 / 路由 {path: '/',redirect: '/dashboard',name: 'Container',component: Container,children: [{path: 'dashboard', name: '首

MFC学习--CListCtrl复选框以及选择

如何展示复选框 //LVS_EX_CHECKBOXES每一行的最前面带个复选框//LVS_EX_FULLROWSELECT整行选中//LVS_EX_GRIDLINES网格线//LVS_EX_HEADERDRAGDROP列表头可以拖动m_listctl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDL

论坛开源项目推荐(12.25):菜单(Menu)

转自  http://www.cocoachina.com/applenews/devnews/2013/1225/7608.html 更多代码可到CocoaChina代码库查看:http://code.cocoachina.com/   SvpplyTable(可折叠可张开的菜单动画) 允许你简单地创建可折叠可张开的菜单动画效果,灵感来自于Svpply app。不同表格项

项目实战--实现一个多级菜单统一工具类

一、背景介绍 在项目开发工程中,经常需要实现多级菜单的效果,比如需要一个多级功能菜单、多级评论、多级部门等功能,如果每个项目都要定制一版代码或者SQL,就会面临代码重复开发的问题。为简化开发过程并提高代码的可维护性,我实现一个统一的工具类来处理这些需求,使用SpringBoot创建一个返回多级菜单、多级评论、多级部门、多级分类的统一工具类。 二、数据库字段设计方案 首先,在数据库设计时,考虑

MFC 访问网址

.h #ifndef HTTPCLIENT_H #define HTTPCLIENT_H #include <afxinet.h> #include <string> using namespace std; #define IE_AGENT _T("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET C

关于VC6 MFC使用Gdiplus实现自绘按钮的总结

步骤1:简易教程(更换对话框的背景)及Gdiplus下载地址可查看这个博客https://blog.csdn.net/misads/article/details/78619735。 步骤2:使用Gdiplus实现自绘按钮可参考这个博客https://blog.csdn.net/wyansai/article/details/50971959。 首先感谢上面两位博主的分享,那么我写这个博客是干