65.9K
CodeProject 正在变化。 阅读更多。
Home

CmenuModifier - 一个自定义绘制的图像菜单

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.92/5 (9投票s)

2008年6月3日

CPOL

6分钟阅读

viewsIcon

49906

downloadIcon

1876

CmenuModifier - 一个自定义绘制的图像菜单

特点

该类CMenuModifier面向MFC程序,具有以下特点: 

  1. 可信

    它使用原始的拥有绘制方法来修改现有菜单(CMenu),因此它是可信的(与使用另一个菜单替换现有菜单相比),并且占用的内存更少。

  2. 为任何级别的子菜单添加图像

    我使用了一些从CodeProject下载的菜单类,但那些类只能为顶层子菜单添加图像。这就是我创建这个类的原因。

  3. 适用于所有MFC应用程序,例如SDI、MDI、对话框菜单和跟踪弹出菜单。

类文件

所有代码都包含在“Class”目录下的CMenuModifier.h中(没有CPP文件)。
你只需要在你的程序中包含头文件。

图像和透明色

要使用图像,必须将一个CToolBar实例传递给SetOwnerDraw(...)函数。
CToolBar实例可以是全局变量也可以是局部变量。
如果没有CToolBar实例,则不会向菜单添加图像。

重要

CToolBar上第一个按钮(左上角)的**第一个像素**的颜色代表**透明色**。
当图像绘制在菜单上时,颜色将对背景(菜单垂直条)透明——请参见下面的示例4。

类实例

CMenuModifier的实例必须是类成员或全局变量,因为它被两个消息使用

  1. WM_DRAWITEM
  2. WM_MEASUREITEM 
  • 静态菜单每个静态菜单,如SDI、MDI和对话框主菜单,都需要一个CMenuModifier实例。
  • 跟踪弹出菜单一个窗口中的所有跟踪弹出菜单只需要一个CMenuModifier实例。
    你可以为每个跟踪弹出菜单使用一个实例。

函数和用法

必须使用以下三个函数: 

  1. BOOL SetOwnerDraw (CMenu*pMenu,BOOL bMainMenu,CToolBar*pBar=NULL,
    int iImageStyle=CCMenuModifier::FLATE,
    COLORREF*pClrMenuBar=NULL, 
    	COLORREF*pClrVertBar=NULL, COLORREF*pClrSelected=NULL); 

    当菜单准备好时调用此函数。
    函数参数,均为“输入”值。

    CMenu*pMenu 要修改的菜单
    BOOL bMainMenu 主菜单为True,跟踪弹出菜单为false
    CToolBar*pBar 图像工具栏,如果不用图像则为NULL
    int iImageStyle 启用的图像样式,如果pBarNULL则不使用——请参见下面的示例3。
    COLORREF *pClrMenuBar 菜单栏颜色的指针,如果为NULL则使用默认颜色
    COLORREF *pClrVertBar 垂直条颜色的指针,如果为NULL则使用默认颜色
    COLORREF*pClrSelected 选中项颜色的指针,如果为NULL则使用默认颜色

  2. BOOL OnMeasureItem (int nIDCtl, MEASUREITEMSTRUCT*pMIS); 

    在消息处理程序中调用此函数

    OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  3. BOOL OnDrawItem (int nIDCtl, DRAWITEMSTRUCT*pDIS); 

    在消息处理程序中调用此函数

    OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)

如果需要修改多个菜单,调用函数2和3的最佳方式是
例如,md_Mainmd_PopupCMenuModifier实例用于修改主菜单和跟踪弹出菜单。以下代码将加快修改速度:  

BOOL b=md_Main.OnDrawMeasureItem(...);
if(b==0) b=md_Popup.OnDrawMeasureItem(...); 

上述代码优化并加速了拥有绘制过程。
然而,以下四个示例没有以上述优化方式调用这两个函数,因为菜单项的数量并不太多。 

以下函数是可选使用的 

void SetChechedItemStyle (BOOL bUseObmBitmap);

如果bUseObmBitmaptrue(默认),则选中菜单项的图像是Windows OBM复选框。否则

  1. 如果选中的菜单项有图像,则该图像显示为带有凹陷3D边框,以指示它已被选中。
  2. 如果选中的菜单项没有图像,则显示Windows OBM复选框。

内部类

有五个内部类

  1. BitmapBuffer

    用于存储位图位的缓冲区,简单易用。

  2. BitmapUnit

    包含启用和禁用位图。 

  3. MenuUser

    该类的指针作为参数lpszNewItem添加到Windows菜单函数中。

    ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem);
  4. MenuUserArray

    一个排序数组,用于存储MenuUser的指针,可以更快地在数组中搜索MenuUser的指针。
    Windows菜单在拥有绘制模式下,并非完全面向对象,它直接测量和绘制菜单项,而不考虑最顶层的菜单ID。
    在数组中快速搜索对于窗口有多个菜单(例如主菜单和跟踪弹出菜单)且菜单项较多的情况很重要且高效。  

  5. ObmChecked

    加载OBM_CHECK图像用于选中的菜单项。

示例

压缩文件中包含四个示例。 

1. SDI示例

该示例修改了3个菜单:一个主框架菜单和两个跟踪弹出菜单。
因此,该示例包含两个CMenuModifier实例,一个用于主菜单,另一个用于2个跟踪弹出菜单。

2. MDI示例

该示例包含三个CMenuModifier实例,一个用于主框架菜单,一个用于子窗口菜单,另一个用于2个跟踪弹出菜单。

3. 对话框示例

该示例修改了3个菜单:一个主菜单和两个跟踪弹出菜单。
因此,该示例包含两个CMenuModifier实例,一个用于主菜单,另一个用于2个跟踪弹出菜单。
CToolBar实例是示例中的局部变量。

该示例更改了启用图像样式。
下图所示的菜单是跟踪弹出菜单。

在深色菜单垂直条上,启用的图像比平面样式看起来更突出、更漂亮。 

4. 彩色对话框示例 

CToolBar实例是示例中的全局变量(类成员)。

该示例更改了菜单栏颜色以匹配彩色对话框。
  
对话框背景颜色由CWinApp::SetDialogBkColor(RGB(191,223,223))确定。

最终结果是

需要进行两个步骤来实现此目的

1. 在SetOwnerDraw(...)函数中将菜单栏颜色更改为对话框颜色。

此时,菜单看起来像

我尝试在类中以编程方式添加一个比最后一个菜单(本例中的“帮助”菜单)长很多的菜单,以覆盖浅灰色菜单栏的右侧部分,但Windows操作系统不允许这样做——额外长的菜单要么消失,要么被操作系统移到第二行。 

2. 添加几个额外的空白、灰色的菜单项

这些菜单项是从VC资源中手动添加的。
此时,菜单看起来像

然后使用一个无模式对话框来覆盖浅灰色菜单栏的右侧部分——这些空白菜单项使得覆盖更容易。

请注意,这一步与该类无关,我只是想展示如何在彩色对话框中使用该类。

限制

  1. 256色系统设置无效

    该类分析CToolBar的位图,然后在类内部生成并存储启用和禁用的图像。因此,CToolBar可以是一个局部变量,并在传递给SetOwnerDraw(...)函数后立即销毁。

    限制是计算机系统的颜色设置为16位或32位。如果计算机设置为256色,图像将不会显示——因为我从未修改过256色位图——我认为今天没有人使用这种设置。如果你需要,请修改类的P_CreateUserImage(...)函数。

  2. 动态菜单项无效

    该类修改在调用SetOwnerDraw(...)函数之前创建的菜单项。
    动态菜单项,例如MDI中的“最近打开的文件”或“窗口”,可能随时添加,因此这些菜单项未设置为拥有绘制,并且未被修改。

更多信息

类内部图像的大小比CToolBar按钮的原始图像大两个像素。

禁用图像在右边框和下边框需要一个额外的像素。样式中的启用图像需要在所有边框上额外一个像素。

下图展示了一个平面图像如何通过在左侧和顶部添加白色线条,在右侧和底部添加深灰色线条,从而被修改为凸起的两种样式。

最后的提示

  1. 再次提醒

    工具栏的第一个像素代表透明色。通常,该颜色应为浅灰色。“透明”意味着颜色将被更改为图像背景色或菜单垂直条的颜色。

  2. 超级计算器

    这款计算器可以计算矩阵、向量、复数、定积分、方程根、常用函数(如正弦、对数)、统计、绘制轨迹等,功能众多,是我比较满意的程序之一,希望你也喜欢,它是免费的。
    这个提示是一个附带的礼物,与菜单类无关。

历史

  • 2008年6月3日:首次发布

© . All rights reserved.