Simple Bitmapped menu items

    技术2022-05-11  138

    简单位图菜单

    这篇文章由Burchak Alexander原著

       有时应用程序使用动态创建的工具条。为什么我要为了位图菜单而创建工具条资源呢?(查看Iuri Apollonio 文章)

      我提议装配菜单位图时使用标准位图表。我这个类的优点是位图和工具条图像可以用尺寸和视图等来区分。此类支持SDIMDI用户界面中的弹出菜单。若你发现了bugs请提出来。

     

     所有你对类CbitmapMenu要做的事是:

    1. 添加CbitmapMenu类的实例给CmainFrame 类:

    CbitmapMenu m_menu;

    2. 添加一个CimageList对象。例如,给CmainFrame类添加其static 成员 

    CimageList m_imglist;

     

    At the point you have in MainFrm.h:

    #include "BitmapMenu.h" class CMainFrame : public CMDIFrameWnd {     ...     public :        CBitmapMenu m_menu;        static CImageList m_imglist;     ... };

     

    MainFrm.cpp中添加:

    #include "MainFrm.h"

    CImageList CMainFrame :: m_imglist;

     

    3.给这个项目添加N个图象资源。其中一个作为checkmark.

    4.为菜单项添加一组CitemBitmap 对象(比如添加到MainFrm.cpp中),这些菜单项将显示位图。

    CItemBitmap g_ibs[ ] = {    CItemBitmap(ID_FILE_NEW, &CMainFrame :: m_imglist, 0),   CItemBitmap(ID_FILE_OPEN, &Camp;MainFrame :: m_imglist, 1),   CItemBitmap(ID_HELP_CONTENTS, &CMainFrame :: m_imglist, 19),   CItemBitmap(-1, NULL, 0, &CMainFrame :: m_imglist, 27) };

     

    CitemBitmap类有2个构造器:

    CItemBitmap( UINT uID,CImageList *pilNormal,UINT uPosNormal); CItemBitmap( UINT uID,CImageList *pilNormal,UINT uPosNormal,CImageList *pilChecked, UINT uPosChecked);

    其中,

       uID---菜单项ID,

       pilNormal---CimageList 对象指针,使用一个位图作为“正常”菜单项状态,

       pilChecked--- CimageList 对象指针,使用一个位图作为“检查”菜单项状态,

       uPosNormal---pilNormal图像列表中的图像索引,

       uPosChecked---pilChecked图像列表中的图像索引,

      列表中的最后个CitemBitmap对象用来保存checkmark图象信息。

      这个CbitmapMenu类用来画checked状态的菜单项。

    5.CmainFrame::OnCreate()函数中处理如下:

      m_menu.Initialize(IDR_MAINFRAME, this); m_menu.AddBitmaps( g_ibs,sizeof(g_ibs) / sizeof(CItemBitmap));

    6. CmainFrame 类中添加WM_MEASUREITEM, WM_DRAWITEM WM_INITMENUPOPUP 消息处理函数。

      添加CmainFrame 类的消息映射:

      ON_WM_MEASUREITEM( ) ON_WM_DRAWITEM( )

    ON_WM_INITMENUPOPUP( )

      CmainFrame类中添加下边函数:

      void CMainFrame :: OnMeasureItem(int nIDCtl,LPMEASUREITEMSTRUCT lpMIS) {    if(lpMIS->CtlType == ODT_MENU)        m_menu.MeasureItem( lpMIS );    else        CMDIFrameWnd :: OnMeasureItem(nIDCtl, lpMIS); }   void CMainFrame :: OnDrawItem(int nIDCtl,LPDRAWITEMSTRUCT lpDIS) {   if(lpDIS->CtlType == ODT_MENU)      m_menu.DrawItem( lpDIS );   else      CMDIFrameWnd :: OnDrawItem(nIDCtl, lpDIS); }   void CMainFrame :: OnInitMenuPopup(CMenu *pPopup,UINT nIndex,BOOL bSysMenu) {   CMDIFrameWnd :: OnInitMenuPopup( pPopup,nIndex,bSysMenu);   if( !bSysMenu )      CBitmapMenu :: Synchronize( pPopup ); }

    6.可选: 如果你想在视类中使用弹出式位图菜单,可按如下:

      CMenu menu;

    VERIFY( menu.LoadMenu( SOME_POPUP_MENU_RESOURCE_ID ) );

    CMenu *pMenu = (CMenu *)  menu.GetSubMenu( 0 );

    ASSERT(pMenu != NULL);

    pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, x, y, AfxGetMainWnd( ));

      我们在TrackPopupMenu()中使用AfxGetMainWnd(),让主框架更新菜单项状态。如果你欲要使用“this”作为弹出菜单的父类,会存在两个问题:

    1.  你需要手工check/gray/enable/disable 菜单项。

    2.  你需要为了适当的绘制位图菜单而添加下面三个消息处理函数。

    我并没提供第一个问题的解决办法。第二个问题的办法是在CmainFrame类中为相同消息添加处理函数:

      ON_WM_MEASUREITEM( ) ON_WM_DRAWITEM( )

    ON_WM_INITMENUPOPUP( )

    处理体如下:

    void CMyEditView :: OnMeasureItem(int nIDCtl,LPMEASUREITEMSTRUCT lpMIS) {    if(lpMIS->CtlType == ODT_MENU)       ((CMainFrame *) AfxGetMainWnd( ))->m_menu.MeasureItem( lpMIS );    else       CEditView :: OnMeasureItem(nIDCtl, lpMIS); }   void CMyEditView :: OnDrawItem(int nIDCtl,LPDRAWITEMSTRUCT lpDIS) {    if(lpDIS->CtlType == ODT_MENU)      ((CMainFrame *) AfxGetMainWnd( ))->m_menu.DrawItem( lpDIS );    else      CEditView :: OnDrawItem(nIDCtl, lpDIS); }   void CMyEditView :: OnInitMenuPopup(CMenu *pPopup,UINT nIndex,BOOL bSysMenu) {    CEditView :: OnInitMenuPopup(pPopup,nIndex,bSysMenu);    if( !bSysMenu )       CBitmapMenu :: Synchronize( pPopup ); }

    全文完。


    最新回复(0)