当前位置:有风信息港IT学院编程技术.net → VC中进行自绘菜单的实现

VC中进行自绘菜单的实现

减小字体 增大字体 作者:有风IT学院  来源:有风信息港  发布时间:2008-1-13 8:07:54
  在这里提供一个C++类(CCustomMenu),该类是Cmenu的子类,并且拥有自绘能力。它可以向你提供以下的功能:
  设置字体颜色。
  设置高亮度颜色。
  设置高亮度时的风格。
  设置选中时和在普通状态下的菜单显示的图标。
  设置显示图标大小。
  在CCustomMenu中定义了结构MENUDATA,你必须根据你的需要填充该结构,并且在增加菜单时提供该结构的指针(调用AppendMenu,InsertMenu)。下面是一个例子:

  1、定义CCustomMenu的实例,和MENUDATA结构变量。
  CCustomMenu m_cCustomMenu;

  MENUDATA menuData [8];

  2、调用CreateMenu()设置有关参数。

  m_customMenu.CreateMenu ();
  m_customMenu.SetIconSize (25,25);
  m_customMenu.SetHighlightStyle (Normal);
  m_customMenu.SetTextColor (RGB (255,0,0));
  m_customMenu.SetBackColor (RGB (255,255,255));
  m_customMenu.SetHighlightColor (RGB (0,0,255));

  3、设置MENUDATA变量,并增加菜单项。

  lstrcpy (menuData[0].menuText , "text1");
  menuData[0].menuIconNormal= IDI_ICON1;
  m_customMenu.AppendMenu (MF_OWNERDRAW,3,(LPCTSTR)menuData);  

  3、在你的窗口中重载OnMeasureItem(...)函数。

  void CMyView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  {
  if ( lpMeasureItemStruct->CtlType == ODT_MENU amp;amp;
  IsMenu((HMENU)lpMeasureItemStruct->itemID) amp;amp;
  (lpMeasureItemStruct->itemID == (UINT)m_hMenuSub) )
  {
  m_customMenu.MeasureItem (lpMeasureItemStruct);
}
  else
    Cview::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
  }

  下面的函数将帮助你设置菜单属性。  

  void SetTextColor (COLORREF );
  void SetBackColor (COLORREF);
  void SetHighlightColor (COLORREF);
  void SetIconSize (int, int);
  void SetHighlightStyle (HIGHLIGHTSTYLE ); // HIGHLIGHTSTYLE : enum {Normal, TextOnly}
  void SetHighlightTextColor (COLORREF);

  下面是文件代码:

  //*************************************************************************

  // CustomMenu.h : header file

  //  

  #if
  !defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)
  #define AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_
  #if _MSC_VER >= 1000
  #pragma once
  #endif // _MSC_VER >= 1000

  class MENUDATA
  {
  public:
  MENUDATA () { menuIconNormal = -1; menuIconSelected = -1;};
  char menuText[32];
  UINT menuIconNormal;
  UINT menuIconSelected;
  };  

  typedef enum {Normal,TextOnly} HIGHLIGHTSTYLE;

  ///////////////////////////////////////////////////////////////////////////
  //
  // CCustomMenu window
  class CCustomMenu : public Cmenu
  {
  // Construction
  public:
  CCustomMenu();
  // Attributes
  public:
  // Operations
  public:
  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CCustomMenu)
  //}}AFX_VIRTUAL
  // Implementation

  public:
  virtual ~CCustomMenu();
  virtual void DrawItem( LPDRAWITEMSTRUCT);
  virtual void MeasureItem( LPMEASUREITEMSTRUCT );
  void SetTextColor (COLORREF );
  void SetBackColor (COLORREF);
  void SetHighlightColor (COLORREF);
  void SetIconSize (int, int);
  void SetHighlightStyle (HIGHLIGHTSTYLE );
  void SetHighlightTextColor (COLORREF); 

  // Generated message map functions

  protected:
  COLORREF m_crText;
  COLORREF m_clrBack;
  COLORREF m_clrText;
  COLORREF m_clrHilight;
  COLORREF m_clrHilightText;
  LOGFONT m_lf;
  Cfont m_fontMenu;
  UINT m_iMenuHeight;
  BOOL m_bLBtnDown;
  Cbrush m_brBackground,m_brSelect;
  Cpen m_penBack;
  int m_iconX,m_iconY;
  HIGHLIGHTSTYLE m_hilightStyle; 

  //{{AFX_MSG(CCustomMenu) 
  //}}AFX_MSG
  };

  //{{AFX_INSERT_LOCATION}}
  // Microsoft Developer Studio will insert additional declarations immediately before the previous line.  

  #endif //!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_) 

  //************************************************************************* 
  // CustomMenu.cpp : implementation file
  //
  #include "stdafx.h"
  #include "CustomMenu.h"
  #ifdef _DEBUG
  #define new DEBUG_NEW
  #undef THIS_FILE
  static char THIS_FILE[] = __FILE__;
  #endif  

  /////////////////////////////////////////////////////////////////////////////
  // CCustomMenu  

  CCustomMenu::CCustomMenu()
  {
  m_clrText = GetSysColor (COLOR_MENUTEXT);
  m_clrBack = GetSysColor (COLOR_MENU);
  m_brBackground.CreateSolidBrush (m_clrBack);
  m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
  m_crText = m_clrText;
  m_bLBtnDown = FALSE;
  m_iconX =GetSystemMetrics ( SM_CXMENUCHECK);
  m_iconY =GetSystemMetrics (SM_CYMENUCHECK );
  m_clrHilight = GetSysColor (COLOR_HIGHLIGHT);
  m_brSelect.CreateSolidBrush (m_clrHilight);
  m_clrHilightText = GetSysColor (COLOR_HIGHLIGHTTEXT);  

  ZeroMemory ((PVOID) amp;m_lf,sizeof (LOGFONT));
  NONCLIENTMETRICS nm;
  nm.cbSize = sizeof (NONCLIENTMETRICS);
  //Get the system metrics for the Captionfromhere
  VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,0,amp;nm,0));  

  m_lf = nm.lfMenuFont;
  m_iMenuHeight = nm.iMenuHeight;
  m_fontMenu.CreateFontIndirect (amp;m_lf);
  } 

  CCustomMenu::~CCustomMenu()
  {
  if ((HBRUSH) m_brBackground != NULL)  m_brBackground.DeleteObject ();
  if ((HFONT)m_fontMenu !=NULL)
  m_fontMenu.DeleteObject ();
  if ((HBRUSH)m_brSelect != NULL)
   m_brSelect.DeleteObject ();
  }  

  ///////////////////////////////////////////////////////////////////////////
  // CCustomMenu message handlers

  void CCustomMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
  {
  ASSERT(lpDIS != NULL);  
  CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  Crect rect;
  HICON hIcon;
  COLORREF crText = m_crText;
  // draw the colored rectangle portion
  rect.CopyRect(amp;lpDIS->rcItem);
  // draw the up/down/focused/disabled state
  UINT action = lpDIS->itemAction;
  UINT state = lpDIS->itemState;
  Cstring strText;
  LOGFONT lf;
  lf = m_lf;  

  Cfont dispFont;
  Cfont *pFont;
  //GetWindowText(strText);
  if (lpDIS->itemData != NULL)
  {
  strText = (((MENUDATA*) (lpDIS->itemData))->menuText);
  if ((((MENUDATA *)(lpDIS->itemData))->menuIconNormal) == -1)
  hIcon = NULL;
  else if (state amp; ODS_SELECTED)
  {
  if ((((MENUDATA *)(lpDIS->itemData))->menuIconSelected) != -1)
  hIcon = AfxGetApp ()->LoadIcon (((MENUDATA *)(lpDIS->itemData))->menuIconSelected);
  else
  hIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);

  }
  else

    hIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
    TRACE1 ("Draw for %s\n", strText);
  }
  else
  {
  strText.Empty();
  hIcon = NULL;
  } 

  if ( (state amp; ODS_SELECTED) )
  {
  // draw the down edges
  Cpen *pOldPen = pDC->SelectObject (amp;m_penBack);
  //You need only Text highlight and that's what you get
  if (m_hilightStyle != Normal)
  {
  pDC->FillRect (rect,amp;m_brBackground);
  }
  else
  {
  pDC->FillRect (rect,amp;m_brSelect);

  }

  pDC->SelectObject (pOldPen);
  pDC->Draw3dRect (rect,GetSysColor (COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
  lf.lfWeight = FW_BOLD;
  if ((HFONT)dispFont != NULL)
  dispFont.DeleteObject ();
  dispFont.CreateFontIndirect (lf);
  crText = m_clrHilightText; 

  //While selected move the text a bit
  TRACE0 ("SELECT,SELECTED\n");
  }
  else
  {
  Cpen *pOldPen = pDC->SelectObject (amp;m_penBack);
  pDC->FillRect (rect,amp;m_brBackground);
  pDC->SelectObject (pOldPen);
  // draw the up edges
  pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
  if ((HFONT)dispFont != NULL)
  dispFont.DeleteObject ();
  dispFont.CreateFontIndirect (lf); //Normal
  TRACE0 ("SELECT, NORMAL\n");
  }  

  // draw the text if there is any
  //We have to paint the text only if the image is nonexistant
  if (hIcon != NULL)
  {
  if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hIcon,
  (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))
  TRACE0("Wrote the icon successfully\n");
  else
  TRACE0 ("SORRY.NOGO\n");
  }
  //This is needed always so that we can have the space for check marks
  rect.left = rect.left +((m_iconX)?m_iconX:32);
  if ( !strText.IsEmpty())
  {
  //pFont->GetLogFont (lf);

  intiOldMode = pDC->GetBkMode();
  pDC->SetBkMode( TRANSPARENT);  
  pDC->SetTextColor( crText);
  pFont = pDC->SelectObject (amp;dispFont);
  TRACE1( "About To DrawText %s\n",strText);
  pDC->DrawText (strText,rect,DT_LEFT DT_SINGLELINE DT_VCENTER);
  TRACE0("Done\n");
  pDC->SetBkMode( iOldMode );
  pDC->SelectObject (pFont); //set it to the old font
  }
  dispFont.DeleteObject ();
  } 

  void CCustomMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
  {
  CDC *pDC = AfxGetApp()->m_pMainWnd->GetDC();
  Cfont* pFont = pDC->SelectObject (amp;m_fontMenu);
  int iconX = 0,iconY= 0;
  TEXTMETRIC tm;
  pDC->GetTextMetrics (tm);
  pDC->SelectObject (pFont);
  AfxGetApp()->m_pMainWnd->ReleaseDC (pDC);  

  if (m_iconX)
  iconX = m_iconX;
  if (m_iconY)
  iconY = m_iconY; 

  lpMIS->itemWidth = iconX + tm.tmAveCharWidth * lstrlen(((MENUDATA*)(lpMIS->itemData))->menuText) +10;
  lpMIS->itemHeight = (iconY > (m_iMenuHeight+1))?iconY:m_iMenuHeight + 1;
  } 

  void CCustomMenu::SetIconSize (int width, int height)
  {
  m_iconX = width;
  m_iconY = height;
  }

  void CCustomMenu::SetTextColor (COLORREF clrText)
  {
  m_crText = clrText;
  } 

  void CCustomMenu::SetBackColor (COLORREF clrBack)

  {
  m_clrBack = clrBack;
  if ((HBRUSH)m_brBackground != NULL)
  m_brBackground.DeleteObject ();
  m_brBackground.CreateSolidBrush (clrBack);
  }  

  void CCustomMenu::SetHighlightColor (COLORREF clrHilight)
  {
  m_clrHilight = clrHilight;
  if ((HBRUSH)m_brSelect != NULL)
  m_brSelect.DeleteObject ();
  m_brSelect.CreateSolidBrush (clrHilight);
  }
  

  void CCustomMenu::SetHighlightTextColor (COLORREF clrHilightText)
  {
  m_clrHilightText = clrHilightText;
  }

  void CCustomMenu::SetHighlightStyle (HIGHLIGHTSTYLE hilightStyle)

  {
  m_hilightStyle = hilightStyle;
  }

  //*************************************************************************