WEB开发网
开发学院软件开发VC 完美实现真彩自绘菜单 阅读

完美实现真彩自绘菜单

 2008-01-19 20:23:56 来源:WEB开发网   
核心提示: 摘录自原CMenuEx.cpp第546-560行 if(uID == 0) //分隔符{::AppendMenu(hNewMenu,MF_SEPARATOR,0,NULL);......// 注意,就是下面那个-1,完美实现真彩自绘菜单(3),把分割条的ID从0改到-1, // 从而是MFC框架误以为找到了ID

摘录自原CMenuEx.cpp第546-560行 if(uID == 0) //分隔符
{
  ::AppendMenu(hNewMenu,MF_SEPARATOR,0,NULL);
  ......
  // 注意,就是下面那个-1,把分割条的ID从0改到-1,
     // 从而是MFC框架误以为找到了ID为-1的菜单项,并且测量了它的尺寸
  // 而实际上ID为-1的菜单项是不可能被void CWnd::OnMeasureItem()找到的
  ::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem);
}    
菜单编辑器中没有分割条菜单的菜单

原CMenuEx执行的模样

菜单编辑器中有分割条菜单的菜单

原CMenuEx执行的模样

  • 代码不够简练,程序粒度划分不好,可读性差(不过比BCMENU的代码可读性强多了:))。

  • 二、解决问题

    针对以上遇到的问题,我参考BCMENU和原作者的CMenuEx,对CMenuEx类重新进行了组织,类定义如下:

    // 声明,因为下面的结构要用到 CMenuEx*,又不支持向后引用,又什么办法啊!
    class CMenuEx;
    //自绘菜单数据项结构,就是要传给系统的那个牛X的LPCTSTR指针所指向的东东
    class CMenuEx : public CMenu
    {
      DECLARE_DYNAMIC( CMenuEx )
        
    // Constructor
    public:  
      CMenuEx();  
      virtual ~CMenuEx();
      virtual BOOL DestroyMenu();
      
    // Operation
    public:
      // 加载菜单操作
      BOOL LoadMenu(UINT nIDResource);
      BOOL LoadMenu(LPCTSTR lpszResourceName);
      BOOL LoadMenu(HMENU hMenu);
      BOOL LoadMenu(CMenu & Menu);
      
      // 菜单项操作,如果当前菜单为主菜单(top-level)就调用相应的CMenu的操作。如果是弹出菜单,
         // 就将新加入的菜单项定义为自绘菜单
      BOOL AppendMenu(UINT nFlags, UINT nIDNewItem = 0,LPCTSTR lpszNewItem = NULL);
      BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL );
      BOOL ModifyMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL );  
      BOOL RemoveMenu(UINT nPosition, UINT nFlags);  
      
      // 加载菜单图像操作
      //通过菜单索引表加载图像索引,此操作必须在设置过菜单图像后调用
      void SetImageIndex(const UINT* nIDResource,UINT nIDCount);
      void LoadToolBar(const CToolBar* pToolBar);// 通过工具栏加载图像,和图像索引
      
      // 取自绘菜单项的数据项
      UINT GetMenuItemSize() const;
      LPMENUITEM GetMenuItem(UINT nPosition);  
      
      // 取子菜单操作,如果位置nPosition存在子菜单,返回该子菜单指针
      // 如果不存在子菜单,返回NULL
      CMenuEx* GetSubMenu(int nPosition);
      // 在当前菜单和所以子菜单中中寻找相应ID
      // 如果找到,返回ID所在菜单的指针,没找到返回NULL
      CMenuEx* FindPopupMenuFromID(UINT nID);
      
    // Attributes
    protected:
      // 指示为主菜单(top-level menu or menubar)还是弹出菜单(popupmenu)
      BOOL m_bPopupMenu;
      
      // 分割条的默认高度
      int m_nSeparator;
      
      // 绘制菜单需要的颜色
      COLORREF m_crBackground;    // 菜单背景色  
      COLORREF m_crTextSelected;    // 菜单项被选中时的文字颜色
      COLORREF m_crText;      // 菜单项文字颜色
      COLORREF m_crLeft;      // 菜单左侧的背景颜色
      COLORREF m_crSelectedBroder;    // 菜单选中框的线条颜色
      COLORREF m_crSelectedFill;    // 菜单选中框的填充颜色
      
      // 菜单项图像的尺寸  
      CSize m_szImage;
      
      CImageList* m_pImageList;    // 菜单项正常的图像列表
      CImageList* m_pDisabledImageList;  // 菜单项禁用时的图像列表
      CImageList* m_pHotImageList;    // 菜单项被选中时的图像列表
      
    protected:
      // 包含所有菜单项的数组
      CArray m_MenuItemArr;
      
    public:
      // 设置颜色操作
      void SetTextSelectedColor(COLORREF color);
      void SetBackgroundColor(COLORREF color);
      void SetTextColor(COLORREF color);
      void SetLeftColor(COLORREF color);
      void SetSelectedBroderColor(COLORREF color);
      void SetSelectedFillColor(COLORREF color);
      
      // 设置图像列表操作
      void SetImageList(CImageList* pImageList);
      void SetDisabledImageList(CImageList* pImageList);
      void SetHotImageList(CImageList* pImageList);
      
      // 设置当前菜单为主菜单还是弹出菜单
      void SetPopupMenu(BOOL bPopupMenu);
      
      // Implementation
    public:
      // 绘制菜单项的虚拟函数,由MFC框架自动调用
      virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
      
      // 更新弹出菜单菜单项操作
      // 因为有时候系统会通过菜单句柄插入一些非自绘菜单
      // 该函数就是更新这些非自绘菜单为自绘菜单
      void UpdatePopupMenu();
      
    protected:
      // 绘制菜单项的辅助函数,想自己的菜单看上去更COOL,就拿他们开刀
      void DrawBackground(CDC* pDC,CRect rect);
      void DrawMenuImage(CDC* pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
      void DrawMenuText(CDC* pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
      void DrawSelected(CDC* pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
      
      // Static Member
    public:
      // 在CMainFrame的OnMeasureItem()消息映射函数中调用它,用来测量所有菜单项尺寸
      static void MeasureItem(LPMEASUREITEMSTRUCT lpMIS);
      
      // 在CMainFrame的OnInitPopupMenu()消息映射函数中调用它,
      // 用来更新系统自动添加的菜单项为自绘菜单
      static void InitPopupMenu(CMenu* pPopupMenu,UINT nIndex,BOOL bSystem);
      
    };
    #endif // !defined(MENUEX_H)   
    三、实现方法

    上一页  1 2 3 4  下一页

    Tags:完美 实现 真彩

    编辑录入:爽爽 [复制链接] [打 印]
    赞助商链接