菜单控制
为什么即使调用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;
}

VC++的菜单控制和自绘菜单的更多相关文章

  1. MFC自绘菜单

    自绘控件问题多多.本文以菜单为例. ①当要使用顶层菜单资源.对话框资源.状态栏资源等这3种资源的任何一种.那么CWinApp::InitInstance函数内部必须使用LoadFrame函数来加载资源 ...

  2. C#winform菜单权限分配,与菜单同步的treeView树状菜单权限控制使用心得

    在网上查了很多,发现没有讲述关于--C#winform菜单权限分配,与菜单同步的treeView树状菜单权限控制使用--的资料 自己研究了一个使用方法.下面来看看. 我有两个窗体:LOGINFRM,M ...

  3. vue实现隔行换色,下拉菜单控制隔行换色的颜色

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 轻量级多级菜单控制框架程序(C语言)

    1.前言 作为嵌入式软件开发,可能经常会使用命令行或者显示屏等设备实现人机交互的功能,功能中通常情况都包含 UI 菜单设计:很多开发人员都会有自己的菜单框架模块,防止重复造轮子,网上有很多这种菜单框架 ...

  5. web标准(复习)--4 纵向导航菜单及二级弹出菜单

    今天我们开始学习纵向导航菜单及二级弹出菜单,包含以下内容和知识点: 纵向列表 标签的默认样式 css派生选择器 css选择器的分组 纵向二级列表 相对定位和绝对定位 一.纵向列表纵向列表或称为纵向导航 ...

  6. Android开发 ---代码创建选项菜单、隐藏菜单项、菜单的生命周期,菜单按钮图标设置、搜索框、xml中设置子菜单

    1.activity_main.xml 描述: 定义了一个按钮 <?xml version="1.0" encoding="utf-8"?> < ...

  7. Web标准:四、纵向导航菜单及二级弹出菜单

    Web标准:四.纵向导航菜单及二级弹出菜单 知识点: 1.纵向列表 2.标签的默认样式 3.css派生选择器 4.css选择器的分组 5.纵向二级列表 6.相对定位和绝对定位   1)纵向列表 可以看 ...

  8. Django - 权限(5)- 非菜单权限对应的一级菜单展开、面包屑导航

    一.非菜单权限对应的一级菜单展开 需求:客户列表和账单列表页面中都有添加按钮,当点击添加客户(或编辑客户.删除客户)时,客户列表所属的一级菜单展开,当点击添加账单(或编辑账单.删除账单)时,账单列表所 ...

  9. js禁止默认的右键菜单或出现自定义右键菜单

    1.屏蔽默认的右键菜单 js: document.getElementById('myimg').oncontextmenu=function(){return false;} jquery: $(' ...

随机推荐

  1. codeforces 459C Pashmak and Buses(模拟,组合数A)

    题目 跑个案例看看结果就知道了:8 2 3 题目给的数据是 n,k,d 相当于高中数学题:k个人中选择d个人排成一列,有多少种不同的方案数,列出其中n中就可以了. #include<iostre ...

  2. Android activity属性

    android:allowTaskReparenting 是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务. android:alwaysRetainTaskState 是否 ...

  3. DB2常用函数:字符串函数

    VALUE函数 语法:VALUE(EXPRESSION1,EXPRESSION2) VALUE函数是用返回一个非空的值,当其第一个参数非空,直接返回该参数的值,如果第一个参数为空,则返回第一个参数的值 ...

  4. lintcode: 跳跃游戏 II

    跳跃游戏 II 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 样例 给出数组A =  ...

  5. Java学习笔记之:Java 定时任务

    一.介绍 在应用里经常都有用到在后台跑定时任务的需求.比如网络运营商会在每个月的一号对数据进行一次统计.在java中我们可以继承timertask类来实现定时任务. 二.笔记 /** * 定时任务 * ...

  6. Sublime Text 2安装汉化破解、插件包安装教程

    原文地址: Sublime Text 2安装汉化破解.插件包安装教程_百度经验 http://jingyan.baidu.com/article/ff4116259b057c12e48237b8.ht ...

  7. 【原创】【ViewPager+Fragment】ViewPager中切换界面Fragment被销毁的问题分析

    ViewPager中切换界面Fragment被销毁的问题分析   1.使用场景 ViewPager+Fragment实现界面切换,界面数量>=3   2.Fragment生命周期以及与Activ ...

  8. Data Base sqlServer 组合主键

    sqlServer   组合主键 创建表时: create table Person ( Name1 ) not null ,Name2 ) not null primary key(Name1,Na ...

  9. dojo 十 ajax dojo/_base/xhr

    官方教程:Ajax with DojoAjax功能:1.从服务器加载静态数据2.从web服务中访问xml或json类型的数据3.将表单(form)数据发送到服务器4.刷新页面内容....Ajax在RI ...

  10. Java 字符串拼接方式

    import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; impor ...