最近研究了一下CMenu的相关属性和方法,发现出现了一道难以逾越的关卡。
如下:
1,CNiceMenu继承自CMenu.
2,要实现菜单重绘就必须响应WM_DRAWITEM消息,这一点来自文章 文章链接
但是,发现却出现了DrawItem函数里面重新绘制的东西把SetMenuItemBitmaps函数设置的菜单位图给覆盖了,起初以为是
SetMenuItemBitmaps有问题。但后来使用GetLastError时返回为0,说明函数已经执行成功,为了验证,偶然发现,把鼠标指针在设置了位图的菜单项上反复快速移动,会出现SetMenuItemBitmaps设置的位图的“影子”。
3,怎么办呢,DrawItem函数始终在SetMenuItemBitmaps之后执行,似乎找不到方法了。
望各位兄弟姐妹,前辈先祖,指点迷津啦!

解决方案 »

  1.   

    既然重绘,那么在DrawItem里面,SetMenuItemBitmaps设置的位图也要自己来输出
      

  2.   

    咋输出呢,要输出位图,就必须知道要在什么地方输出,虽然可以做一个接口函数来让用户指定要输出的位图和在要输出位图的菜单项ID,但是得计算输出的具体坐标。好,输出的具体坐标也可以在DrawItem函数的形参里面找到,这样的接口也可以让用户指定某个菜单项的位图,但是却无法在多次调用该接口函数时,却出现问题:只有最后的那次调用才是有效的,前面的调用无效,因为显示设备在每一次调用DrawItem函数之后就被销毁了!
      

  3.   

    既然重绘,还要SetMenuItemBitmaps干嘛。
      

  4.   

    首先声明,该类是在文章链接 的基础上改的,知识对其作了一些删改,千万别说我侵权啊!
    头文件//  MenuEx.h: interface for the CMenuEx class.
    //  CMenuEx
    //  原作者:lbird(郑恒)
    //  修改:(querw)阙荣文
    //  新增接口:
    //  void LoadMenu();
    // BOOL ModifyMenuEx()
    // BOOL AppendMenuEx()
    // BOOL RemoveMenuEx()
    // void LoadToolBar()
    //  原接口:
    // void SetHighLightColor(COLORREF crColor)
    // void SetBackColor(COLORREF)
    // void SetTextColor(COLORREF)
    // void SetImageLeft(UINT idBmpLeft)
    //
    // 2004.7.23
    //////////////////////////////////////////////////////////////////////#if !defined(AFX_MENUEX_H__FE677F6B_2315_11D7_8869_BB2B2A4F4D45__INCLUDED_)
    #define AFX_MENUEX_H__FE677F6B_2315_11D7_8869_BB2B2A4F4D45__INCLUDED_
    #include "afxtempl.h"
    #include "afxwin.h"
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000typedef struct tagMENUITEM
    {
    CString strText; //菜单文本
    UINT uID; //菜单ID
    int uIndex; //菜单图标的编号
    int  uPositionImageLeft; //菜单左边位图的位置
    int nSubMenuIndex; //若是子菜单,表示在数组中的位置
    tagMENUITEM()   //结构体中的构造函数初始化成员
    {
    strText = _T(""); 
    uID = -2; 
    uIndex = -1; 
    uPositionImageLeft = -1; 
    nSubMenuIndex = -1;
    pImageList = NULL;
    pLeftBitmap = NULL;
    };
    CImageList *pImageList;
    CBitmap *pLeftBitmap;
    }MENUITEM,*LPMENUITEM;
    ///////////////////////////////////////////
    class CMenuEx : public CMenu  
    {
    DECLARE_DYNAMIC( CMenuEx )
    public:
    //读入菜单,调用这个函数以后,菜单就有了自画风格
    BOOL LoadMenu(UINT uMenu);

    //修改,添加,删除菜单项,自动指定为自画风格
    BOOL ModifyMenuEx(UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
    BOOL AppendMenuEx(UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
    BOOL RemoveMenuEx(UINT nPosition, UINT nFlags);

    //读入工具条,可以指定一张位图以替代工具条资源的16色位图
    void LoadToolBar(UINT uToolBar,UINT uFace);

    //其他各种设置
    void SetHighLightColor(COLORREF crColor);
    void SetBackColor(COLORREF);
    void SetTextColor(COLORREF);
    void SetImageLeft(UINT idBmpLeft,BOOL bIsPopupMenu = FALSE);
    CMenuEx* GetSubMenu( int nPos ) const;

    virtual void MeasureItem(LPMEASUREITEMSTRUCT  lpMIS);
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);

    CMenuEx();
    virtual ~CMenuEx();protected:
    int m_nSeparator; //分割条的高度

    CSize m_szImageLeft; //菜单左边为体的高度和宽度
    CBitmap m_bmpImageLeft; //菜单左边的位图
    int m_nWidthLeftImage; //菜单左边位图的宽度
    BOOL m_bHasImageLeft; //是否有侧边位图

    COLORREF m_colMenu; //菜单背景色
    COLORREF m_colTextSelected; //菜单被选中时文本的颜色 COLORREF m_crCurSelBorder;  // 当前指针所指项目边框的颜色
    COLORREF m_crCurSelRect;  //当前鼠标指针所在菜单项的边框背景色 COLORREF m_crLeftErectRect;  // 设置左边竖直边框填充色
    COLORREF m_crSeparator; CImageList m_ImageList; //菜单项位图列表
    COLORREF m_colText; //菜单项没被选中时文本的颜色
    CSize m_szImage; //菜单项位图的大小
    int CalculateLeftImagePos(CMenu *pPopupMenu); //重新计算左边位图的位置(最底部的菜单项的位图标号是 0 )
    void ChangeMenuStyle(CMenu* pMenu,HMENU hNewMenu);
    //void DrawImageLeft(CDC *pDC,CRect &rect,LPMENUITEM lpItem);
    void TextMenu(CDC *pDC,CRect rect,CRect rcText,BOOL bSelected,BOOL bGrayed,LPMENUITEM lpItem);
    void DrawMenuItemImage(CDC *pDC,CRect &rect,BOOL bSelected,BOOL bChecked,BOOL bGrayed,BOOL bHasImage,LPMENUITEM lpItem);
    void GrayString(CDC *pDC,const CString &str,const CRect rect); CArray<CMenuEx *,CMenuEx *> m_SubMenuArr;
    CArray<MENUITEM *,MENUITEM *>m_MenuItemArr;

    public:
    // 设置选中边框颜色
    void SetCurSelBorderColor(COLORREF crBorder);
    // 设置选中边框填充色
    void SetCurSelRectColor(COLORREF crFill);

    // 设置左边竖直矩形的边框颜色
    void SetLeftRectBkColor(COLORREF crBkgnd);
    // 设置分隔符高度
    //void SetSeparatorHeight(UINT uHeight);
    protected:
    // 设置分隔符高度(2-15)
    UINT m_uHeight;
    public:
    void SetCheckBmp(UINT nBmpID);
    protected:
    UINT nCheckBmpID;
    public:
    // 设置菜单项的位图
    void SetMenuItemImage(UINT nPosition , UINT nBmpSourceID);
    protected:
    // 此ID用来指定要设置左边位图的菜单项
    int m_nMenuID;
    };#endif // !defined(AFX_MENUEX_H__FE677F6B_2315_11D7_8869_BB2B2A4F4D45__INCLUDED_)
      

  5.   

    当然不要也行,只是能在重绘时,给用户提供一个类似于SetMenuItemBitmaps也可以啊!