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
 
constintMAX_MENUCOUNT = 60,ITEMHEIGHT = 26,ITEMWIDTH= 120; //菜單項數量
 
 
                                                                                                          /*************************************
                                                                                                          CMenuItemInfo結構用於記錄菜單項信息
*************************************/
structCMenuItemInfo
{
       CStringm_ItemText;//菜單項文本
       intm_IconIndex;//菜單項索引
       intm_ItemID;//菜單標記 -2頂層菜單,-1彈出式菜單,0分隔條,其他普通菜單
};
 
 
classCIconMenu : publicCMenu 
{
public:
       CMenuItemInfom_ItemLists[MAX_MENUCOUNT]; //菜單項信息
       intm_index; //臨時索引
       intm_iconindex;
       CImageListm_imagelist;//存儲菜單項圖標
      
       CIconMenu();
       BOOLChangeMenuItem(CMenu* m_menu,BOOLm_Toped = FALSE);
       BOOL AttatchMenu(HMENUm_hmenu);
       voidDrawItemText(CDC* m_pdc,LPSTRstr,CRectm_rect);
       voidDrawTopMenu(CDC* m_pdc,CRectm_rect,BOOLm_selected = FALSE); //繪製頂層菜單
       voidDrawSeparater(CDC* m_pdc,CRectm_rect);//繪製分隔條
       voidDrawComMenu(CDC* m_pdc,CRectm_rect,COLORREFm_fromcolor,COLORREFm_tocolor, BOOLm_selected = FALSE);
       voidDrawMenuIcon(CDC* m_pdc,CRectm_rect,intm_icon );
      
       //override memu's viutual method
       virtual ~CIconMenu();
       virtualvoidMeasureItem( LPMEASUREITEMSTRUCTlpStruct );//設置菜單項大小
       virtualvoidDrawItem( LPDRAWITEMSTRUCTlpStruct );//重繪菜單項
      
};
 
#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
staticcharTHIS_FILE[]=__FILE__;
#define newDEBUG_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(HMENUm_hmenu)
{
       this->Attach(m_hmenu);
       returnTRUE;
}
 
BOOLCIconMenu::ChangeMenuItem(CMenu* m_menu,BOOLm_Toped)
{
       if (m_menu != NULL)
       {
              intm_itemcount = m_menu->GetMenuItemCount();
              for (inti=0;i<m_itemcount;i++)
              {
                     m_menu->GetMenuString(i,m_ItemLists[m_index].m_ItemText,MF_BYPOSITION);
                            intm_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);
                     }
              }
       }
       returnTRUE ;
}
 
voidCIconMenu::MeasureItem( LPMEASUREITEMSTRUCTlpStruct )
{
       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;
                            }    
              }
       }
}
 
voidCIconMenu::DrawItem( LPDRAWITEMSTRUCTlpStruct )
{
       if (lpStruct->CtlType==ODT_MENU)
       {
              if(lpStruct->itemData == NULL)      return;
              unsignedintm_state = lpStruct->itemState;
              CDC* m_dc = CDC::FromHandle(lpStruct->hDC);
              //m_dc.Attach(lpStruct->hDC);
 
              CStringstr = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemText;
              LPSTRm_str = str.GetBuffer(str.GetLength());
 
              intm_itemID = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemID;
              intm_itemicon = ((CMenuItemInfo*)(lpStruct->itemData))->m_IconIndex;
              CRectm_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標識菜單區域
*************************************************************/
voidCIconMenu::DrawItemText(CDC* m_pdc,LPSTRstr,CRectm_rect)
{
       m_rect.DeflateRect(20,0);
       m_pdc->DrawText(str,m_rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);
}
 
voidCIconMenu::DrawTopMenu(CDC* m_pdc,CRectm_rect,BOOLm_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
       {
              CRectrect;
              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));
       }
}
 
voidCIconMenu::DrawSeparater(CDC* m_pdc,CRectm_rect)
{
       if (m_pdc != NULL)
       {
              m_pdc->Draw3dRect(m_rect,RGB(255,0,0),RGB(0,0,255));
       }
}
 
voidCIconMenu::DrawComMenu(CDC* m_pdc,CRectm_rect,COLORREFm_fromcolor,COLORREFm_tocolor, BOOLm_selected )
{
       if (m_selected)
       {
             
              m_pdc->Rectangle(m_rect);     
              m_rect.DeflateRect(1,1);
              intr1,g1,b1;
              //讀取漸變起點的顏色值
              r1 = GetRValue(m_fromcolor);
              g1 = GetGValue(m_fromcolor);
              b1 = GetBValue(m_fromcolor);
              intr2,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());
             
              COLORREFr,g,b;//菜單區域水平方向每個點的顏色值
              CPen* m_oldpen ;
 
              for (inti = 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);
                    
                     CPenm_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));
       }
}
 
voidCIconMenu::DrawMenuIcon(CDC* m_pdc,CRectm_rect,intm_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中添加一個上述類的變量:    CIconMenum_Menu;
CMainFrameOnCreate函數中,添加經過上述類設置的菜單,代碼如下:
          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()
   然後添加函數及實現如下:
voidCMainFrame::OnDrawItem(intnIDCtl, LPDRAWITEMSTRUCTlpDrawItemStruct)
{
       m_Menu.DrawItem(lpDrawItemStruct);
}
 
voidCMainFrame::OnMeasureItem(intnIDCtl, LPMEASUREITEMSTRUCTlpMeasureItemStruct)
{
       m_Menu.MeasureItem(lpMeasureItemStruct);
}
OK,好了,直接運行,即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章