实现自绘菜单

为了实现菜单的自绘,花了我几个小时,其实真正解决后又发现很简单。实现菜单的自绘只需要三个步骤:

第一步:将所有菜单项设置为MF_OWNERDRAW,即自绘模式

第二步:在WM_MEASUREITEM消息中设置菜单项的大小

第三步:在WM_DRAWITEM消息中进行菜单项的绘制

问题首先出现在了第一步,我要绘制的是一个上下文菜单,即右键菜单,要将菜单项设置为MF_OWNERDRAW,需要用到ModifyMenu函数,起始由于ModifyMenu函数的参数设置错误,导致程序怎么也响应不了WM_MEASUREITEM和WM_DRAWITEM消息,所以建议在使用ModifyMenu时对返回值进行检查。

void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point) {     ClientToScreen(&point);     CMenu Menu;     Menu.LoadMenuW(IDR_MENU2);     CMenu *pMenu = Menu.GetSubMenu(0);     CString strText;     for (int i = 0; i < pMenu->GetMenuItemCount(); i++)     {         BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);         if (!bModi)        {               TRACK("ModifyMenu fail!");        }         pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);     }     pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,         point.x,         point.y,         this); }

第一步的问题解决后,接在在第二步的WM_MEASUREITEM消息中设置菜单项的大小:

void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis) {     //lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;     lpmis->itemWidth = 150;     lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU); }  在WM_MEASUREITEM消息中设置的菜单项大小会传入WM_DRAWITEM消息中,然后再在WM_DRAWITEM消息中根据菜单项的大小来进行重绘。

到第三步也遇到了几个问题,由于最初对WM_DRAWITEM消息中的LPDRAWITEMSTRUCT结构体不了解,以致写出的程序不管在什么时候都会作同一个绘制操作,先来看看WM_DRAWITEM消息的声明:

afx_msg void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis);

在这个消息中有两个参数,在自绘菜单时,两个参数都要用到。其中nIDCtl,书上说是所属控件的ID,不太明白是什么意思,在MSDN看到,对于菜单发出的WM_DRAWITEM消息,nIDCtl为0。再说LPDRAWITEMSTRUCT结构体,该结构体中包含了菜单复选状态、选中状态以及菜单项的大小等信息。

下面是OnDrawItem消息的实现代码:

void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis) {     CBrush *brush = new CBrush;     CPen *pen = new CPen;     CString strText;     CDC *pDC = CDC::FromHandle(lpdis->hDC); //获取菜单项的设备句柄     //菜单项是否为选中状态     if ((lpdis->itemState & ODS_SELECTED))     {         //在菜单项上自绘矩形框的背景颜色         brush->CreateSolidBrush(RGB(182, 189,210));         //在菜单项自绘矩形的边框颜色         pen->CreatePen(PS_SOLID, 1, RGB(10,36,106));         //设置菜单项的文字背景颜色         pDC->SetBkColor(RGB(182,189,210));     }     else     {         brush->CreateSolidBrush(GetSysColor(COLOR_MENU));         pen->CreatePen(PS_SOLID, 0, GetSysColor(COLOR_MENU));         pDC->SetBkColor(GetSysColor(COLOR_MENU));     }     pDC->SelectObject(pen);     pDC->SelectObject(brush);     //在当前菜单项上画一个矩形框     pDC->Rectangle(lpdis->rcItem.left,         lpdis->rcItem.top,         lpdis->rcItem.right,         lpdis->rcItem.bottom);     /*--------------------------------------*/     //获取当前消息所在菜单项的文本     CMenu menu;     menu.Attach((HMENU)lpdis->hwndItem);     menu.GetMenuStringW(lpdis->itemID, strText,MF_BYCOMMAND);     /*--------------------------------------*/     //如果为菜单发出的DrawItem消息     if (nIDCtl == 0)     {         //在菜单项上输出菜单文本         pDC->TextOutW(lpdis->rcItem.left + 20, lpdis->rcItem.top + 4, strText.GetBuffer(0), strText.GetLength());     }     menu.Detach();     delete brush;     delete pen; }

效果图:

 

参考资料:http://www.vckbase.com/document/viewdoc/?id=1583

时间: 2024-10-30 23:00:08

实现自绘菜单的相关文章

完美实现真彩自绘菜单

一.提出问题 在VCKBASE上读到<自绘菜单的实现>[作者:querw].应用的我自己的正在进行的工程后发现效果不错,可是有存在许多问题.整个类的设计方面存在很多缺陷(先天,后天的),存在的主要问题如下: 当应用在多文档界面(MDI)中的时候,无法对系统自动添加菜单和文档模板菜单进行自绘(比如无法对文件->最近文件(MRU)菜单项中的文件列表就是系统自动添加).原因是类内部没有对CMainFrame::OnInitPopupMenu()消息进行处理的函数, 因此不具备修改系统自动添加菜

自绘菜单的实现

在VCKBASE上读到<一种漂亮的自绘菜单> [作者:郑恒 (lbird)].应用到我的工程里后发现:文章中提到的效果能很好的实现.但是有一点不方便:需要映射 WM_DRAWITEM 和 WM_MEASUREITEM 消息才能实现自画功能.这对于一个基于对话框的工程或者仅仅需要弹出式菜单的工程来说很不方便.网上有一种很有名的自绘菜单 :BCMenu (http://www.rocscience.com/~corkum/BCMenu.html) (在附带工程中也有 BCMenu),在使用它的时候

mfc自绘菜单前面的竖线没有了

问题描述 mfc自绘菜单前面的竖线没有了 mfc自绘菜单前面的竖线没有了 解决方案 http://www.cnblogs.com/pcdelphi/archive/2009/04/26/2018034.html 你是重绘的item么?大小计算正确么? 没看到你的代码,估计你重绘了边框或者客户区计算不正确. 看上面的例子.

VC++的菜单控制和自绘菜单

菜单控制为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态   需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项. //Disable MFC from automatically disabling menu items. m_bAuoMenuEnable=FALSE; //Now enable the men

一种漂亮的自绘菜单

以前还是菜鸟时就觉得QQ的菜单做得很漂亮,想着自已的程序如果有那种菜单多好. 现在积累了一定的知识,就自已设计了一个类似的菜单控件类.并把它发表出来供大家使用和参考,难免有不足的地方请高手不吝赐教! 菜单效果如下:   一.CMenuEx菜单类主要接口函数: 1.void InitMenu(CMenu *pMenu,UINT uToolBar,CToolBar *pToolBar); 说明:这是最主要的一个接口.如果要改变主窗口的菜单则应在主窗口的OnInitMenu(CMenu *pMenu)

三个函数实现框架菜单自绘

在VCKBASE看到的自绘菜单都是派生出一个新类,其实不用这么麻烦,添加三个函数即可实现框架菜单自绘,方便简单,易于维护. 在MFC中,如果菜单带有MF_OWNERDRAW标志,程序就会调用OnDrawItem和OnMeasureItem函数来绘制菜单. 下面就让我们来动手吧!首先在CMainFrame响应三个消息,分别是: WM_DRAWITEM:绘制菜单的样式WM_MEASUREITEM:指定要绘制菜单的大小WM_INITMENU:把框架菜单全部改成带MF_OWNERDRAW标志 下面我帖出

VB打造超酷个性化菜单(二)

菜单 VB打造超酷个性化菜单(二) 其实,漂亮的界面都是"画"出来的,菜单当然也不例外.既然是"画"出来的,就需要有窗体来接收"画"菜单这个消息,后面我们会看到,实际上不仅仅是"画"这个消息,一切关于这个菜单的消息都要有一个窗体来接收.如果你对消息不太了解,可以看看网上其它一些关于Windows消息机制的文章.不了解也没有关系,只要会使用就可以了,后面的文章给出了完整的源代码,而且文章的最后还给出了源代码的下载地址. 下面我们

VB打造超酷个性化菜单(三)

菜单 VB打造超酷个性化菜单(三) 现在到了最关键,最精彩,也是最复杂的部分了.我们最关心的就是怎样"画"菜单,怎样处理菜单事件,在MenuWndProc这个处理消息的函数里,我们要处理如下消息:WM_COMMAND(单击菜单项),WM_MEASUREITEM(处理菜单高度和宽度),WM_MENUSELECT(选择菜单项),WM_DRAWITEM(绘制菜单项). 打开上次建好的工程,添加一个标准模块,并将其名称设置为mMenu,代码如下: '**********************

.NET中的自绘机制

本文配套源码 每次 Microsoft 推出象 Office 或者 Visual Studio 这样拳头产品的新版本时,都会推出一些新的特性,其中包括了新的菜单样式(Menu Style).当新的菜单样式以各自的方式集成到成品中后,第三方的开发商便会掀起一阵模仿浪潮,利用一些定制控件和组件来仿效它.如果你正在使用这些产品,那么你惟有升级到新版本才能享受提供的新的特性.否则,你的应用程序将继续使用大约十年前随 Windows 95 上市时的那种 Windows 经典菜单用户界面. 虽然 Micro