VC带图标的程序菜单

带图标的程序菜单
本文介绍在基于单文档程序中,如何实现带图标的程序菜单。如下:
1.      创建一个单文档工程: AddIconMenu
2.      这个工程里面用到了一个类来实现对程序菜单图标的添加以及颜色的设定等等。添加到工程。头文件如下: IconMenu.h
   // IconMenu1.h: interface for the CIconMenu class.
//
//
 
#if !defined( AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_ )
#define AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
 
const int MAX_MENUCOUNT = 60, ITEMHEIGHT = 26, ITEMWIDTH = 120; // 菜单项数量
 
 
                                                                                                           /*************************************
                                                                                                          CMenuItemInfo 结构用于记录菜单项信息
*************************************/
struct CMenuItemInfo
{
       CString m_ItemText ; // 菜单项文本
       int m_IconIndex ; // 菜单项索引
       int m_ItemID ; // 菜单标记 -2 顶层菜单 ,-1 弹出式菜单 ,0 分隔条 , 其他普通菜单
};
 
 
class CIconMenu : public CMenu  
{
public :
       CMenuItemInfo m_ItemLists [ MAX_MENUCOUNT ]; // 菜单项信息
       int m_index ; // 临时索引
       int m_iconindex ;
       CImageList m_imagelist ; // 存储菜单项图标
      
       CIconMenu ();
       BOOL ChangeMenuItem ( CMenu * m_menu , BOOL m_Toped = FALSE );
       BOOL   AttatchMenu ( HMENU m_hmenu );
       void DrawItemText ( CDC * m_pdc , LPSTR str , CRect m_rect );
       void DrawTopMenu ( CDC * m_pdc , CRect m_rect , BOOL m_selected = FALSE ); // 绘制顶层菜单
       void DrawSeparater ( CDC * m_pdc , CRect m_rect ); // 绘制分隔条
       void DrawComMenu ( CDC * m_pdc , CRect m_rect , COLORREF m_fromcolor , COLORREF m_tocolor , BOOL m_selected = FALSE );
       void DrawMenuIcon ( CDC * m_pdc , CRect m_rect , int m_icon );
      
       //override memu's viutual method
       virtual ~ CIconMenu ();
       virtual void MeasureItem ( LPMEASUREITEMSTRUCT lpStruct ); // 设置菜单项大小
       virtual void DrawItem ( LPDRAWITEMSTRUCT lpStruct ); // 重绘菜单项
      
};
 
#endif // !defined(AFX_ICONMENU1_H__FAA8B855_EE72_4332_96D7_73F8FA07E521__INCLUDED_)
 
实现文件如下:
// IconMenu1.cpp: implementation of the CIconMenu class.
//
//
 
#include "stdafx.h"
//#include "IconMenu.h"
//#include "IconMenu1.h"
#include "AddIconMenu.h"
#include "IconMenu.h"
 
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE []= __FILE__ ;
#define new DEBUG_NEW
#endif
 
//
// Construction/Destruction
//
 
CIconMenu :: CIconMenu ()
{
       m_index = 0;
       m_iconindex = 0;
       // 创建图像列表
       m_imagelist . Create (16,16, ILC_COLOR24 | ILC_MASK ,0,0);
 
       // 添加图标
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON1 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON2 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON3 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON4 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON5 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON6 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON7 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON8 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON9 ));
       m_imagelist . Add ( AfxGetApp ()-> LoadIcon ( IDI_ICON10 ));
}
 
CIconMenu ::~ CIconMenu ()
{
       m_imagelist . Detach ();
}
 
BOOL   CIconMenu :: AttatchMenu ( HMENU m_hmenu )
{
       this -> Attach ( m_hmenu );
       return TRUE ;
}
 
BOOL CIconMenu :: ChangeMenuItem ( CMenu * m_menu , BOOL m_Toped )
{
       if ( m_menu != NULL )
       {
              int m_itemcount = m_menu -> GetMenuItemCount ();
              for ( int i =0; i < m_itemcount ; i ++)
              {
                     m_menu -> GetMenuString ( i , m_ItemLists [ m_index ]. m_ItemText , MF_BYPOSITION );
                            int m_itemID = m_menu -> GetMenuItemID ( i );
                     if ( m_itemID ==-1 && m_Toped )
                     {
                            m_itemID = -2; // 顶层菜单
                     };
                     m_ItemLists [ m_index ]. m_ItemID = m_itemID ;
                     if ( m_itemID >0)
                     {
                            m_ItemLists [ m_index ]. m_IconIndex = m_iconindex ;
                            m_iconindex +=1;
                     }
                     m_menu -> ModifyMenu ( i , MF_OWNERDRAW | MF_BYPOSITION | MF_STRING , m_ItemLists [ m_index ]. m_ItemID ,( LPSTR )&( m_ItemLists [ m_index ]));
                    
                     m_index +=1;
                     CMenu * m_subMenu = m_menu -> GetSubMenu ( i );
 
                     if ( m_subMenu )
                     {
                            ChangeMenuItem ( m_subMenu );
                     }
              }
       }
       return TRUE  ;
}
 
void CIconMenu :: MeasureItem ( LPMEASUREITEMSTRUCT lpStruct )
{
       if ( lpStruct -> CtlType == ODT_MENU )
       {
              lpStruct -> itemHeight = ITEMHEIGHT ;
              lpStruct -> itemWidth = ITEMWIDTH ;
              CMenuItemInfo * m_iteminfo ;
              m_iteminfo = ( CMenuItemInfo *) lpStruct -> itemData ;
              lpStruct -> itemWidth = (( CMenuItemInfo *) lpStruct -> itemData )-> m_ItemText . GetLength ()*10;
              switch ( m_iteminfo -> m_ItemID )
              {
                     case 0: // 分隔条
                            {
                                   lpStruct -> itemHeight = 1;
                                   break ;
                            }    
              }
       }
}
 
void CIconMenu :: DrawItem ( LPDRAWITEMSTRUCT lpStruct )
{
       if ( lpStruct -> CtlType == ODT_MENU )
       {
              if ( lpStruct -> itemData == NULL )      return ;
              unsigned int m_state = lpStruct -> itemState ;
              CDC * m_dc = CDC :: FromHandle ( lpStruct -> hDC );
              //m_dc.Attach(lpStruct->hDC);
 
              CString str = (( CMenuItemInfo *)( lpStruct -> itemData ))-> m_ItemText ;
              LPSTR m_str = str . GetBuffer ( str . GetLength ());
 
              int m_itemID = (( CMenuItemInfo *)( lpStruct -> itemData ))-> m_ItemID ;
              int m_itemicon = (( CMenuItemInfo *)( lpStruct -> itemData ))-> m_IconIndex ;
              CRect m_rect = lpStruct -> rcItem ;
 
              m_dc -> SetBkMode ( TRANSPARENT );
 
              switch ( m_itemID )
              {
              case -2:
                     {
 
                            DrawTopMenu ( m_dc , m_rect ,( m_state & ODS_SELECTED )||( m_state &0x0040)); //0x0040 ==ODS_HOTLIGHT
 
                            DrawItemText ( m_dc , m_str , m_rect );
                            break ;
                     }
              case -1:
                     {    
                            DrawItemText ( m_dc , m_str , m_rect );
                            break ;
                     }
              case 0:
                     {
                            DrawSeparater ( m_dc , m_rect );
                            break ;
                     }
              default :
                     {           
                            DrawComMenu ( m_dc , m_rect ,0xfaa0,0xf00ff, m_state & ODS_SELECTED );
                            DrawItemText ( m_dc , m_str , m_rect );
                            DrawMenuIcon ( m_dc , m_rect , m_itemicon );
                            break ;
                     }
              }
       }
}
/*************************************************************
功能描述 : 绘制菜单项文本
 
参数说明 : m_pdc 标识画布对象 ,str 标识菜单文本 ,m_rect 标识菜单区域
*************************************************************/
void CIconMenu :: DrawItemText ( CDC * m_pdc , LPSTR str , CRect m_rect )
{
       m_rect . DeflateRect (20,0);
       m_pdc -> DrawText ( str , m_rect , DT_SINGLELINE | DT_VCENTER | DT_LEFT );
}
 
void CIconMenu :: DrawTopMenu ( CDC * m_pdc , CRect m_rect , BOOL m_selected )
{
       if ( m_selected )
       {
              m_pdc -> SelectStockObject ( BLACK_PEN );
              m_pdc -> Rectangle (& m_rect );
              m_rect . DeflateRect (1,1);
              m_pdc -> FillSolidRect ( m_rect , RGB (150, 185, 255));
       }
       else
       {
              CRect rect ;
              AfxGetMainWnd ()-> GetClientRect ( rect );
              rect . top = m_rect . top ;
              rect . bottom = m_rect . bottom ;
              rect . left = 360;
              rect . right +=4;
              //CRect c_rect(m_rect);
              m_pdc -> FillSolidRect (& rect , RGB (200,187, 255));
              m_pdc -> FillSolidRect (& m_rect , RGB (200,187, 255));
              //m_pdc->SelectStockObject(BLACK_PEN);
              //m_pdc->FillSolidRect(m_rect,RGB(100, 185, 255));
       }
}
 
void CIconMenu :: DrawSeparater ( CDC * m_pdc , CRect m_rect )
{
       if ( m_pdc != NULL )
       {
              m_pdc -> Draw3dRect ( m_rect , RGB (255,0,0), RGB (0,0,255));
       }
}
 
void CIconMenu :: DrawComMenu ( CDC * m_pdc , CRect m_rect , COLORREF m_fromcolor , COLORREF m_tocolor , BOOL m_selected )
{
       if ( m_selected )
       {
             
              m_pdc -> Rectangle ( m_rect );     
              m_rect . DeflateRect (1,1);
              int r1 , g1 , b1 ;
              // 读取渐变起点的颜色值
              r1 = GetRValue ( m_fromcolor );
              g1 = GetGValue ( m_fromcolor );
              b1 = GetBValue ( m_fromcolor );
              int r2 , g2 , b2 ;
 
 
              // 读取渐变终点的颜色值
              r2 = GetRValue ( m_tocolor );
              g2 = GetGValue ( m_tocolor );
              b2 = GetBValue ( m_tocolor );
 
              float   r3 , g3 , b3 ; // 菜单区域水平方向每个点 RGB 值应该变化的度 ( 范围 )
             
              r3 = (( float )( r2 - r1 )) / ( float )( m_rect . Height ());
              g3 = ( float )( g2 - g1 )/( float )( m_rect . Height ());                 
              b3 = ( float )( b2 - b1 )/( float )( m_rect . Height ());
             
              COLORREF r , g , b ; // 菜单区域水平方向每个点的颜色值
              CPen * m_oldpen ;
 
              for ( int i = m_rect . top ; i < m_rect . bottom ; i ++)
              {
                     r = r1 +( int ) r3 *( i - m_rect . top );
                     g = g1 +( int ) g3 *( i - m_rect . top );
                     b = b1 + ( int ) b3 *( i - m_rect . top );
                    
                     CPen m_pen ( PS_SOLID ,1, RGB ( r , g , b ));
                     m_oldpen = m_pdc -> SelectObject (& m_pen );
                     m_pdc -> MoveTo ( m_rect . left , i );
                     m_pdc -> LineTo ( m_rect . right , i );
              }
 
              m_pdc -> SelectObject ( m_oldpen );
       }
       else
       {
              m_pdc -> FillSolidRect ( m_rect , RGB (0x000000F9, 0x000000F8, 0x000000F7));
       }
}
 
void CIconMenu :: DrawMenuIcon ( CDC * m_pdc , CRect m_rect , int m_icon )
{
       m_imagelist . Draw ( m_pdc , m_icon , CPoint ( m_rect . left +2, m_rect . top +4), ILD_TRANSPARENT );
}
 
当然这里面需要的图标资源,自己拷贝到 res 目录下即可。
3.      然后在文档类中添加 SetTitle 消息,可以修改标题栏信息,如下:
   lpszTitle = " 基于单文档结构的带图标的程序菜单 " ;
4. CMainFrame 中添加一个上述类的变量:     CIconMenu m_Menu ;
CMainFrame OnCreate 函数中,添加经过上述类设置的菜单,代码如下:
          m_Menu . AttatchMenu ( this -> GetMenu ()-> GetSafeHmenu ());
          m_Menu . ChangeMenuItem (& m_Menu , TRUE );
 
          this -> SetIcon ( AfxGetApp ()-> LoadIcon ( IDI_ICON1 ), TRUE );
this -> SetTitle ( "IconMenuExample" );
5.      分别为 CMainFrame 添加,如下两个消息函数 WM_DRAWITEM () WM_MEASUREITEM () ,不知道为什么,我的消息函数中没有,所以就手工添加了。在消息映射中添加如下:
       ON_WM_DRAWITEM ()
      ON_WM_MEASUREITEM ()
   然后添加函数及实现如下:
void CMainFrame :: OnDrawItem ( int nIDCtl , LPDRAWITEMSTRUCT lpDrawItemStruct )
{
       m_Menu . DrawItem ( lpDrawItemStruct );
}
 
void CMainFrame :: OnMeasureItem ( int nIDCtl , LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
       m_Menu . MeasureItem ( lpMeasureItemStruct );
}
OK ,好了,直接运行,即可。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值