自繪選單的實現 (轉)

worldblog發表於2007-12-04
自繪選單的實現 (轉)[@more@]

自繪選單的實現

聞怡洋譯

在這裡提供一個C++類(CCustomMenu),該類是CMenu的子類,並且擁有自繪能力。它可以向你提供以下的功能:

  1. 設定字型顏色。
  2. 設定高亮度顏色。
  3. 設定高亮度時的風格。
  4. 設定選中時和在普通狀態下的選單顯示的圖示。
  5. 設定顯示圖示大小。

CCustomMenu中定義了結構MENUDATA,你必須根據你的需要填充該結構,並且在增加選單時提供該結構的指標(AppendMenu,InsertMenu)。下面是一個例子:

1、定義CCustomMenu的例項,和MENUDATA結構變數。

CCustomMenu m_cCustomMenu; MENUDATA menuData [8]; // as many menu items are present , You should be able to use //new and do the same 2、呼叫CreateMenu()設定有關引數。


m_customMenu.CreateMenu (); m_customMenu.SetIconSize (25,25); //This is to set the size of the Icon. // This should be used only once for any menu // in order to resize it, destroy and create the menu again with different size. m_customMenu.SetHighlightStyle (Normal); //Or TextOnly, if you want the // background color to remain the same // and the Text color to change to the Highlight color. // The following setXXXColor sets the menu colors. If you dont want to change any, Dont call these member functions.


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 && IsMenu((HMENU)lpMeasureItemStruct->itemID) && (lpMeasureItemStruct->itemID == (UINT)m_hMenuSub) ) { m_customMenu.MeasureItem (lpMeasureItemStruct); } else // let MFC's self-drawing handle it 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; menuIconed = -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: // Overrs // 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) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG }; /////////////////////////////////////////////////////////////////////////// // //{{AFX_INSERT_LOCATION}} // 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 _DE #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////////////////////////////// // // CCustomMenu CCustomMenu::CCustomMenu() { m_clrText = GetSylor (COLOR_MENUTEXT); m_clrBack = GetSysColor (COLOR_MENU); m_brBackground.CreateSolirush (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) &m_lf,sizeof (LOGFONT)); NONCLIENTMETRICS nm; nm.cbSize = sizeof (NONCLIENTMETRICS); //Get the system metrics for the Captionfromhere VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,0,&nm,0)); m_lf = nm.lfMenuFont; m_iMenuHeight = nm.iMenuHeight; m_fontMenu.CreateFontIndirect (&m_lf); } CCustomMenu::~CCustomMenu() { if ((HBRUSH) m_brBackground != NULL) m_brBackground.Delete (); 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(&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 & 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 %sn", strText); } else { strText.Empty(); hIcon = NULL; } if ( (state & ODS_SELECTED) ) { // draw the down edges CPen *pOldPen = pDC->SelectObject (&m_penBack); //You need only Text highlight and thats what you get if (m_hilightStyle != Normal) { pDC->FillRect (rect,&m_brBackground); } else { pDC->FillRect (rect,&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,SELECTEDn"); } else { CPen *pOldPen = pDC->SelectObject (&m_penBack); pDC->FillRect (rect,&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, NORMALn"); } // 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 succesullyn"); else TRACE0 ("SORRY.NOGOn"); } //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); int iOldMode = pDC->GetBkMode(); pDC->SetBkMode( TRANSPARENT); pDC->SetTextColor( crText); pFont = pDC->SelectObject (&dispFont); TRACE1( "About To DrawText %sn",strText); pDC->DrawText (strText,rect,DT_LEFT|DT_SINGLELINE|DT_VCENTER); TRACE0("Donen"); 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 (&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; } //*************************************************************************


 


摘自玉海園


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987989/,如需轉載,請註明出處,否則將追究法律責任。

相關文章