VC++的菜單控制和自繪菜單。
菜單控制
爲什麼即使調用EnableMenuItem菜單項後,菜單項還處於禁止狀態
需要將CFrameWnd:: m_bAutomenuEnable設置爲FALSE,如果該數據成員爲TRUE(缺省值),工作框將自動地禁止沒有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜單項。
//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE;
//Now enable the menu item.
CMenu* pMenu=GetMenu ();
ASSERT_VALID (pMenu);
pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED);
如何給系統菜單添加一個菜單項
給系統菜單添加一個菜單項需要進行下述三個步驟:
首先,使用Resource Symbols對話(在View菜單中選擇Resource Symbols...
可以顯示該對話)定義菜單項ID,該ID應大於0x0F而小於0xF000;
其次,調用CWnd::GetSystemMenu獲取系統菜單的指針並調用CWnd:: Appendmenu將菜單項添加到菜單中。下例給系統菜單添加兩個新的菜單項:
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
…
//Make sure system menu item is in the right range.
ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM);
ASSERT (IDM-MYSYSITEM<0xF000);
//Get pointer to system menu.
CMenu* pSysmenu=GetSystemmenu (FALSE);
ASSERT_VALID (pSysMenu);
//Add a separator and our menu item to system menu.
CString StrMenuItem (_T ("New menu item"));
pSysMenu->Appendmenu (MF_SEPARATOR);
pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem);
…
}
現在,選擇系統菜單項時用戶應進行檢測。使用ClassWizard處理
WM_SYSCOMMAND消息並檢測用戶菜單的nID參數:
void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
//Determine if our system menu item was selected.
if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
{
//TODO-process system menu item
}
else
CMDIFrameWnd:: OnSysCommand (nID, lParam);
}
最後,一個設計良好的UI應用程序應當在系統菜單項加亮時在狀態條顯示一個幫助信息,這可以通過增加一個包含系統菜單基ID的串表的入口來實現。
如何確定頂層菜單所佔據的菜單行數
這可以通過簡單的減法和除法來實現。首先,用戶需要計算主框窗口的高度和客戶區;其次,從主框窗口的高度中減去客戶區、框邊界以及標題的高度;最後,除以菜單欄的高度。下例成員函數是一個計算主框菜單所佔據的行數的代碼實現。
int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient;
GetWindowRect (rcFrame);
GetClientRect (rcClient);
return (rcFrame.Height () -rcClient.Height ()-
:: GetSystemMetrics (SM_CYCAPTION) -
(:: getSystemMetrics (SM_CYFRAME) *2)) /
:: GetSystemMetrics (SM_CYMENU);
}
自繪菜單
聞怡洋譯
在這裏提供一個C++類(CCustomMenu),該類是CMenu的子類,並且擁有自繪能力。它可以向你提供以下的功能:
設置字體顏色。
設置高亮度顏色。
設置高亮度時的風格。
設置選中時和在普通狀態下的菜單顯示的圖標。
設置顯示圖標大小。
在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; 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)
// NOTE - the ClassWizard will add and remove member functions here.
//}}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) &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.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(&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 %s/n", 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,SELECTED/n");
}
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, 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);
int iOldMode = pDC->GetBkMode();
pDC->SetBkMode( TRANSPARENT);
pDC->SetTextColor( crText);
pFont = pDC->SelectObject (&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 (&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;
}
爲什麼即使調用EnableMenuItem菜單項後,菜單項還處於禁止狀態
需要將CFrameWnd:: m_bAutomenuEnable設置爲FALSE,如果該數據成員爲TRUE(缺省值),工作框將自動地禁止沒有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜單項。
//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE;
//Now enable the menu item.
CMenu* pMenu=GetMenu ();
ASSERT_VALID (pMenu);
pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED);
如何給系統菜單添加一個菜單項
給系統菜單添加一個菜單項需要進行下述三個步驟:
首先,使用Resource Symbols對話(在View菜單中選擇Resource Symbols...
可以顯示該對話)定義菜單項ID,該ID應大於0x0F而小於0xF000;
其次,調用CWnd::GetSystemMenu獲取系統菜單的指針並調用CWnd:: Appendmenu將菜單項添加到菜單中。下例給系統菜單添加兩個新的菜單項:
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
…
//Make sure system menu item is in the right range.
ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM);
ASSERT (IDM-MYSYSITEM<0xF000);
//Get pointer to system menu.
CMenu* pSysmenu=GetSystemmenu (FALSE);
ASSERT_VALID (pSysMenu);
//Add a separator and our menu item to system menu.
CString StrMenuItem (_T ("New menu item"));
pSysMenu->Appendmenu (MF_SEPARATOR);
pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem);
…
}
現在,選擇系統菜單項時用戶應進行檢測。使用ClassWizard處理
WM_SYSCOMMAND消息並檢測用戶菜單的nID參數:
void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
//Determine if our system menu item was selected.
if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
{
//TODO-process system menu item
}
else
CMDIFrameWnd:: OnSysCommand (nID, lParam);
}
最後,一個設計良好的UI應用程序應當在系統菜單項加亮時在狀態條顯示一個幫助信息,這可以通過增加一個包含系統菜單基ID的串表的入口來實現。
如何確定頂層菜單所佔據的菜單行數
這可以通過簡單的減法和除法來實現。首先,用戶需要計算主框窗口的高度和客戶區;其次,從主框窗口的高度中減去客戶區、框邊界以及標題的高度;最後,除以菜單欄的高度。下例成員函數是一個計算主框菜單所佔據的行數的代碼實現。
int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient;
GetWindowRect (rcFrame);
GetClientRect (rcClient);
return (rcFrame.Height () -rcClient.Height ()-
:: GetSystemMetrics (SM_CYCAPTION) -
(:: getSystemMetrics (SM_CYFRAME) *2)) /
:: GetSystemMetrics (SM_CYMENU);
}
自繪菜單
聞怡洋譯
在這裏提供一個C++類(CCustomMenu),該類是CMenu的子類,並且擁有自繪能力。它可以向你提供以下的功能:
設置字體顏色。
設置高亮度顏色。
設置高亮度時的風格。
設置選中時和在普通狀態下的菜單顯示的圖標。
設置顯示圖標大小。
在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; 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)
// NOTE - the ClassWizard will add and remove member functions here.
//}}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) &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.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(&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 %s/n", 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,SELECTED/n");
}
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, 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);
int iOldMode = pDC->GetBkMode();
pDC->SetBkMode( TRANSPARENT);
pDC->SetTextColor( crText);
pFont = pDC->SelectObject (&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 (&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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.