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

完美实现真彩自绘菜单

 2008-01-19 20:23:56 来源:WEB开发网   
核心提示:有了以上的强有力的武器,就可以对我们的程序下手了:)在MDI或SDI中使用CMenuEx的时候需要修改以下地方,完美实现真彩自绘菜单(4), 先将MenuEx.h和MenuEx.cpp添加到工程中,在CMainFrame中添加头文件,就够了, 希望大家能从文章中学到点东西,CMenuEx对象,用于存储菜单图像的

有了以上的强有力的武器,就可以对我们的程序下手了:)在MDI或SDI中使用CMenuEx的时候需要修改以下地方。

  1. 先将MenuEx.h和MenuEx.cpp添加到工程中,在CMainFrame中添加头文件,CMenuEx对象,用于存储菜单图像的CImageList对象和初始化菜单程序。

    #include "MenuEx.h" // 添加头文件
    class CMainFrame : public CMDIFrameWnd
    {
      ...
    public:
      HMENU InitMainFrameMenu();    // 初始化主菜单
      HMENU InitImageTypeMenu();    // 初始化文档模板菜单
      
    protected: // CMenuEx members
      CMenuEx m_menuMainFrame;    // 主窗体没有打开任何文档时菜单
      CMenuEx m_menuImageType;    // 主窗体打开文档时菜单(文档模板菜单)
      
    protected: // CMenuEx''s image list members  
      CImageList  m_imageMenu;    // 菜单项正常的图像列表
      CImageList  m_imageMenuDisable;  // 菜单项禁用时的图像列表
      CImageList  m_imageMenuHot;    // 菜单项被选中时的图像列表
      ...
    }    

  2. 撰写菜单图像索引表,初始化菜单程序,初始化菜单图像列表程序, 和两个重要的消息映射函数CMainFrame::OnMeasureItem()和CMainFrame::OnInitPopupMenu()。 (什么?不会添加!,找ClassWizard帮忙或许有点帮助了:))

    // 声明,因为下面的结构要用到 CMenuEx*,又不支持向后引用,又什么办法啊!
    class CMenuEx;
    //自绘菜单数据项结构,就是要传给系统的那个牛X的LPCTSTR指针所指向的东东
    typedef struct tagMENUITEM
    {
      CString    strText;    // 菜单名称
      UINT    nID;    // 菜单ID号
      // 分割条的ID是 0
      // 子菜单的ID是 -1
            
      CSize    itemSize;    // 菜单项的尺寸,不包括菜单图像的尺寸
      
      CImageList*   pImageList;    // 菜单项的正常图像列表
      CImageList*   pDisabledImageList;  // 菜单项的禁用图像列表
      CImageList*   pHotImageList;  // 菜单项的选中图像列表
      UINT    nImageIndex;  // 菜单项的图像列表索引,-1表示没有图像
      
      BOOL    bIsSubMenu;    // 表示当前菜单项是否为子菜单项
      
      CMenuEx*  pSubMenu;    // 如果是一般菜单,该值为NULL
      // 如果bIsSubMenu为TRUE,该值为指向子菜单项的CMenuEx*指针
      
    } MENUITEM,*LPMENUITEM;
    ///////////////////////////////////////////
    // 在ManiFram.cpp 中添加菜单图像索引表
    static UINT nMenuImageIndex[] =
    {
      ID_FILE_OPEN,
        ID_FILE_SAVE,
        ID_FILE_PRINT,    
        ID_EDIT_COPY,
        ID_EDIT_PASTE,  
        ID_EDIT_UNDO,
        ID_EDIT_REDO,    
        ID_APP_ABOUT,
        
        ID_IMAGE_LEVEL,
        ID_IMAGE_EQUALIZE,    
        ID_IMAGE_SMOOTH,
        ID_IMAGE_SHARP,    
        ID_IMAGE_SIZE,
        ID_IMAGE_RA,    
        ID_IMAGE_HISTOGRAM,    
        ID_ZOOMOUT,
        ID_ZOOMIN,
    };
    /////////////////////////////////////////////////////////////////////////////
    // 在ManiFram.cpp 中添加初始化菜单程序
    void CMainFrame::InitMenuImage()
    {
      // 初始化菜单图像列表
      CBitmap bm;  
      
      m_imageMenu.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
      // 要问我IDB_SMALLMENUCOLOR是什么,当然是是真彩位图了,看图说话了
      bm.LoadBitmap(IDB_SMALLMENUCOLOR);  
      m_imageMenu.Add(&bm,(CBitmap*)NULL);
      bm.Detach();
      // 还有IDB_SMALLMENUDISABLE
      m_imageMenuDisable.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
      bm.LoadBitmap(IDB_SMALLMENUDISABLE);  
      m_imageMenuDisable.Add(&bm,(CBitmap*)NULL);
      bm.Detach();
      // 还有IDB_SMALLMENUHOT
      m_imageMenuHot.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
      bm.LoadBitmap(IDB_SMALLMENUHOT);  
      m_imageMenuHot.Add(&bm,(CBitmap*)NULL);
      bm.Detach();  
      
    }
    /*
    IDB_SMALLMENUCOLOR
       
       
    IDB_SMALLMENUHOT
        
               
           
    IDB_SMALLMENUDISABLE
            
                  
    当然,要通过资源编辑器的Import功能将他们导入到资源文件中,不过因为是真彩,所以不能用VC的图片编辑器编辑了。 告诉大家个敲门,我是用windows自带的画笔画的:) */
    /////////////////////////////////////////////////////////////////////////////
    // 在ManiFram.cpp 中添加初始化菜单图像列表程序
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
      // 在CMainFrame::OnCreate中调用菜单图标初始化程序
      。。。。。。
        
        InitMenuImage();
      
      。。。。。。
    }
    /////////////////////////////////////////////////////////////////////////////
    HMENU CMainFrame::InitMainFrameMenu()
    {  
      //初始化主菜单  
      m_menuMainFrame.LoadMenu(IDR_MAINFRAME);
      
      {
        // 这只加载图像的一种方法,是一种两步方法,先加载图像列表
        m_menuMainFrame.SetImageList(&m_imageMenu);
        m_menuMainFrame.SetDisabledImageList(&m_imageMenuDisable);
        m_menuMainFrame.SetHotImageList(&m_imageMenuHot);
        
        // 再通过菜单图像索引表为菜单加载图像索引,
        m_menuMainFrame.SetImageIndex(nMenuImageIndex,
                      sizeof(nMenuImageIndex)/sizeof(UINT));  
      }
      
      // 也可以使用另外一种一步方法加载图像
      /*
      // 假设MAINFRAM具有m_wndToolBar成员,并且已经设置了真彩位图
      // 关于设置工具栏的真彩位图,请参考 http://www.vckbase.com/document/viewdoc/?id=576
      // 或者看我的另外一篇文章 《完美实现真彩工具栏》(还没写出来那:))
         // 不过源程序里面已经有实现方法了
      // 自己看也可以明白的
      m_menuMainFrame.LoadToolBar(&m_wndToolBar);  
      */
      
      return m_menuMainFrame.Detach();
    }
    /////////////////////////////////////////////////////////////////////////////
    HMENU CMainFrame::InitImageTypeMenu()
    {    
      // 初始化文档模板菜单
      
      m_menuImageType.LoadMenu(IDR_IMAGETYPE);
      
      m_menuImageType.SetImageList(&m_imageMenu);
      m_menuImageType.SetDisabledImageList(&m_imageMenuDisable);
      m_menuImageType.SetHotImageList(&m_imageMenuHot);
      //通过菜单图像索引表为菜单加载图像索引
      m_menuImageType.SetImageIndex(nMenuImageIndex,sizeof(nMenuImageIndex)/sizeof(UINT));
      
      return m_menuImageType.Detach();
    }
    /////////////////////////////////////////////////////////////////////////////
    void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
    {  
      // 记住,顺序一定不能反,因为有些MFC自动添加的菜单是在CMDIFrameWnd::OnInitMenuPopup()
         // 中添加的.
      // 如果反了,当然就找不到新加入的菜单了
      CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
      // 静态函数,看好了,别忘了写CMenuEx啊  
      CMenuEx::InitPopupMenu(pPopupMenu, nIndex, bSysMenu);  
    }
    /////////////////////////////////////////////////////////////////////////////
    void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
    {
      // 都是她惹的祸"CMDIFrameWnd::OnMeasureItem()",不对子菜单项的尺寸进行测量
      // 害的我们只好映射这个函数了    
      CMDIFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
      // 静态函数,看好了,别忘了写CMenuEx啊
      CMenuEx::MeasureItem(lpMeasureItemStruct);
    }   

  3. 在CXXXApp::InitInstance()中添加代码,XXX代表你自己的程序了 BOOL CXXXApp::InitInstance()
    {
      ......
      CMultiDocTemplate* pDocTemplate;
      pDocTemplate = new CMultiDocTemplate(
        IDR_IMAGETYPE,
        RUNTIME_CLASS(CImageDoc),
        RUNTIME_CLASS(CChildFrame), // custom MDI child frame
        RUNTIME_CLASS(CImageView));
      AddDocTemplate(pDocTemplate);
      
      // create main MDI Frame window
      CMainFrame* pMainFrame = new CMainFrame;
      if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
        return FALSE;
      m_pMainWnd = pMainFrame;
      
      // 这些才是要添加的代码,别弄错了
      // 初始化文档模板菜单
      pDocTemplate->m_hMenuShared=pMainFrame->InitImageTypeMenu();  
      // 初始化主窗体菜单
      pMainFrame->m_hMenuDefault=pMainFrame->InitMainFrameMenu();  
      
      // 更新,具体干什么没研究,反正不调用就出错了:)
      pMainFrame->OnUpdateFrameMenu(pMainFrame->m_hMenuDefault);  
      // 要添加的代码到这结束  
      ......
    }    

三、总结

说了这么多,也不知道大家看明白没有,没关系,先贴个图,大家看看效果再说了。

效果图一,使用图像索引表加载的小图标菜单

效果图一,工具条加载的大图标菜单

四、结束语

感谢querw和BCMenu的作者,没有他们的辛勤劳动,后人是没办法站在他们肩膀上的!由于程序写的匆忙,难免有不尽人意和错误的地方,欢迎大家任意修改源程序:) 要说这个菜单做的完美,那是吹牛,世界上哪有完美的东西啊 :) 只要自己觉得完美,就够了。 希望大家能从文章中学到点东西,就好。

上一页  1 2 3 4 

Tags:完美 实现 真彩

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