[Visual C++]VC++的菜单控制和自绘菜单【转载收藏】

    技术2022-05-11  123

    菜单控制为什么即使调用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}elseCMDIFrameWnd:: 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 same2、调用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 >= 1000class MENUDATA{public:    MENUDATA () { menuIconNormal = -1; menuIconSelected = -1;};    char menuText[32];    UINT menuIconNormal;    UINT menuIconSelected;};typedef enum {Normal,TextOnly} HIGHLIGHTSTYLE;//// CCustomMenu windowclass CCustomMenu : public CMenu{// Constructionpublic:    CCustomMenu();// Attributespublic:// Operationspublic:// Overrides    // ClassWizard generated virtual function overrides    //{{AFX_VIRTUAL(CCustomMenu)    //}}AFX_VIRTUAL// Implementationpublic:    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 functionsprotected:    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_FILEstatic char THIS_FILE[] = __FILE__;#endif//// CCustomMenuCCustomMenu::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 handlersvoid 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;}

    最新回复(0)