zoukankan      html  css  js  c++  java
  • VC学习笔记:菜单

    VC学习笔记:菜单

     SkySeraph NOV.1sh 2010  HQU

    Email-zgzhaobo@gmail.com  QQ-452728574

    Latest Modified Date:NOV.1sh 2010 HQU

    基本操作

    • 动态创建菜单[1]

    步骤:

    ① 创建一个对话框工程,并在对话框头文件中声明一个CMenu类对象m_Menu

    ② 在对话框OnInitDialog函数中添加:

    m_Menu.CreateMenu();//创建菜单窗口

    CMenu m_PopMenu;//定义菜单类对象

    m_PopMenu.CreatePopupMenu();//创建弹出菜单窗口

    m_Menu.AppendMenu(MF_POPUP,(UINT)m_PopMenu.m_hMenu,"动物");//插入菜单

    m_PopMenu.AppendMenu(MF_STRING,ID_MENUCAT,"猫");//插入子菜单

    m_PopMenu.AppendMenu(MF_STRING,ID_MENUDOG,"狗");

    m_PopMenu.AppendMenu(MF_STRING,ID_MENUMONKEY,"猴子");

    m_Menu.AppendMenu(MF_POPUP,-1,"植物");//插入兄弟菜单

    m_PopMenu.Detach();//分离菜单句柄

    SetMenu(&m_Menu);//将菜单和窗口进行关联

    ③在对话框头文件中声明菜单处理函数

    afx_msg void OnMenucat();

    afx_msg void OnMenudog();

    afx_msg void OnMenumonkey();

    ④在对话框的源文件中添加消息映射宏

    ON_COMMAND(ID_MENUCAT, OnMenucat)

    ON_COMMAND(ID_MENUDOG, OnMenudog)

    ON_COMMAND(ID_MENUMONKEY, OnMenumonkey)

    ⑤在对话框的源文件中添加消息处理函数实现代码

    void CCreateMenuDlg::OnMenucat()

    {

    MessageBox("猫菜单被按下");

    }

    void CCreateMenuDlg::OnMenudog()

    {

    MessageBox("狗菜单被按下");

    }

    void CCreateMenuDlg::OnMenumonkey()

    {

    MessageBox("猴子菜单被按下");

    }

    说明:

    首先通过CreateMenu创建一个菜单窗口并将其关联到菜单对象上

    然后调用CreatePopupmenu创建一个弹出式窗口并将其关联到菜单对象上

    再调用AppendMenu添加菜单项

    再调用Detach从菜单对象上分离菜单句柄

    最后调用SetMenu将创建的菜单分配到指定的窗口

    • 创建弹出式菜单法一[1]

    步骤:

    ①新建对话框工程,并在对话框头文件中声明一个CMenu类对象m_Menu

    ②Insert一个菜单资源,设置好菜单

    ③在对话框OnInitDialog函数中添加:

    m_Menu.LoadMenu(IDR_MENU1);//加载菜单资源

    ④在dlg中右键添加鼠标右键抬起的触发消息处理函数OnRButtonUp,编辑代码

    void CPopupMenuDlg::OnRButtonUp(UINT nFlags, CPoint point)

    {

    // TODO: Add your message handler code here and/or call default

    CMenu* pMenu = m_Menu.GetSubMenu(0);//获得菜单句柄

    CRect rect;

    ClientToScreen(&point);//将客户坐标转化为屏幕坐标

    rect.top  = point.x;//鼠标当前横坐标作为弹出菜单的左上角坐标

    rect.left = point.y;

    pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,

    rect.top,rect.left,this,&rect);//显示弹出菜单

    CDialog::OnRButtonUp(nFlags, point);//调用基类的方法

    }

    ⑤添加菜单处理事件。。如。。

    void CPopupMenuDlg::OnMenuadd()

    {

    // TODO: Add your command handler code here

    MessageBox("菜单被按下");

    }

    说明:

    首先创建一个菜单资源,然后调用LoadMenu方法加载菜单资源

    再调用GetSubMenu方法获取弹出式菜单中的一个菜单项

    最后调用TrackPopupMenu方法显示一个弹出式菜单

    • 创建弹出式菜单法二[2]

    <<03.rar>>

    • 创建图标菜单[2]

    ①创建单文档工程,创建一个菜单类CIconMenu,派生于CMenu

    ②在CIconMenu头文件中定义菜单信息,并定义一些成员变量,同时向CIconMenu中添加AttachMenu方法,具体如下

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

    CMenuItemInfo结构用于记录菜单项信息

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

    struct CMenuItemInfo

    {

    CString m_ItemText;//菜单项文本

    int m_IconIndex;//菜单项索引

    int m_ItemID;//菜单标记 -2顶层菜单,-1弹出式菜单,0分隔条,其他普通菜单

    };

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

    public:

    CMenuItemInfo m_ItemLists[MAX_MENUCOUNT]; //菜单项信息

    int m_index; //临时索引

    int m_iconindex; //菜单项图标索引

    CImageList m_imagelist;//存储菜单项图标

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

    BOOL  CIconMenu::AttatchMenu(HMENU m_hmenu)

    {

    this->Attach(m_hmenu);

    return TRUE;

    }

    ③编写CIconMenu类的构造函数

    CIconMenu::CIconMenu()

    {

    m_index= 0;

    m_iconindex= 0;

    //创建图像列表

    m_imagelist.Create(16,16,ILC_COLOR24|ILC_MASK,0,0);

    //添加图标

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON3));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON4));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON5));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON6));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON7));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON8));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON9));

    m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON10));

    }

    ④向CIconMenu类中添加ChangeMenuItem方法,用于修改菜单项信息,使其包含MF_OWNERDRAW风格,并将菜单项信息存储在m_ItemLists成员变量中

    BOOL CIconMenu::ChangeMenuItem(CMenu* m_menu,BOOL m_Toped)

    {

    if (m_menu != NULL)

    {

    int m_itemcount = m_menu->GetMenuItemCount();

    for (int i=0;i<m_itemcount;i++)

    {

    m_menu->GetMenuString(i,m_ItemLists[m_index].m_ItemText,MF_BYPOSITION);

    int m_itemID = m_menu->GetMenuItemID(i);

    if (m_itemID==-1 && m_Toped)

    {

    m_itemID = -2;//顶层菜单

    };

    m_ItemLists[m_index].m_ItemID = m_itemID;

    if (m_itemID>0)

    {

    m_ItemLists[m_index].m_IconIndex= m_iconindex;

    m_iconindex+=1;

    }

    m_menu->ModifyMenu(i,MF_OWNERDRAW|MF_BYPOSITION |MF_STRING,m_ItemLists[m_index].m_ItemID,(LPSTR)&(m_ItemLists[m_index]));

    m_index+=1;

    CMenu* m_subMenu = m_menu->GetSubMenu(i);

    if (m_subMenu)

    {

    ChangeMenuItem(m_subMenu);

    }

    }

    }

    return TRUE        ;

    }

    ⑤改写菜单类的MeasureItem虚拟方法,计算菜单项的大小

    void CIconMenu::MeasureItem( LPMEASUREITEMSTRUCT lpStruct )

    {

    if (lpStruct->CtlType==ODT_MENU)

    {

    lpStruct->itemHeight = ITEMHEIGHT;

    lpStruct->itemWidth = ITEMWIDTH;

    CMenuItemInfo* m_iteminfo;

    m_iteminfo = (CMenuItemInfo*)lpStruct->itemData;

    lpStruct->itemWidth = ((CMenuItemInfo*)lpStruct->itemData)->m_ItemText.GetLength()*10;

    switch(m_iteminfo->m_ItemID)

    {

    case 0: //分隔条

    {

    lpStruct->itemHeight = 1;

    break;

    }        

    }

    }

    }

    ⑥添加成员函数DrawItemText绘制菜单项文本、DrawMenuIcon绘制菜单项图标、DrawSeparater绘制分隔条、DrawTopMenu绘制顶层菜单、DrawComMenu在菜单项区域绘制渐变效果,代码如下

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

    功能描述: 绘制菜单项文本

    参数说明: m_pdc标识画布对象,str标识菜单文本,m_rect标识菜单区域

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

    void CIconMenu::DrawItemText(CDC* m_pdc,LPSTR str,CRect m_rect)

    {

    m_rect.DeflateRect(20,0);

    m_pdc->DrawText(str,m_rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);

    }

    void CIconMenu::DrawTopMenu(CDC* m_pdc,CRect m_rect,BOOL m_selected )

    {

    if (m_selected)

    {

    m_pdc->SelectStockObject(BLACK_PEN);

    m_pdc->Rectangle(&m_rect);

    m_rect.DeflateRect(1,1);

    m_pdc->FillSolidRect(m_rect,RGB(150, 185, 255));

    }

    else

    {

    CRect rect;

    AfxGetMainWnd()->GetClientRect(rect);

    rect.top = m_rect.top;

    rect.bottom = m_rect.bottom;

    rect.left= 360;

    rect.right +=4;

    //CRect c_rect(m_rect);

    m_pdc->FillSolidRect(&rect,RGB(200,187, 255));

    m_pdc->FillSolidRect(&m_rect,RGB(200,187, 255));

    //m_pdc->SelectStockObject(BLACK_PEN);

    //m_pdc->FillSolidRect(m_rect,RGB(100, 185, 255));

    }

    }

    void CIconMenu::DrawSeparater(CDC* m_pdc,CRect m_rect)

    {

    if (m_pdc != NULL)

    {

    m_pdc->Draw3dRect(m_rect,RGB(255,0,0),RGB(0,0,255));

    }

    }

    void CIconMenu::DrawComMenu(CDC* m_pdc,CRect m_rect,COLORREF m_fromcolor,COLORREF m_tocolor, BOOL m_selected )

    {

    if (m_selected)

    {

    m_pdc->Rectangle(m_rect);        

    m_rect.DeflateRect(1,1);

    int r1,g1,b1;

    //读取渐变起点的颜色值

    r1 = GetRValue(m_fromcolor);

    g1 = GetGValue(m_fromcolor);

    b1 = GetBValue(m_fromcolor);

    int r2,g2,b2;

    //读取渐变终点的颜色值

    r2 = GetRValue(m_tocolor);

    g2 = GetGValue(m_tocolor);

    b2 = GetBValue(m_tocolor);

    float  r3,g3,b3;//菜单区域水平方向每个点RGB值应该变化的度(范围)

    r3 = ((float)(r2-r1)) / (float)(m_rect.Height());

    g3 = (float)(g2-g1)/(float)(m_rect.Height());                        

    b3 = (float)(b2-b1)/(float)(m_rect.Height());

    COLORREF r,g,b;//菜单区域水平方向每个点的颜色值

    CPen* m_oldpen ;

    for (int i = m_rect.top;i<m_rect.bottom;i++)

    {

    r = r1+(int)r3*(i-m_rect.top);

    g = g1+(int)g3*(i-m_rect.top);

    b = b1+ (int)b3*(i-m_rect.top);

    CPen m_pen (PS_SOLID,1,RGB(r,g,b));

    m_oldpen = m_pdc->SelectObject(&m_pen);

    m_pdc->MoveTo(m_rect.left,i);

    m_pdc->LineTo(m_rect.right,i);

    }

    m_pdc->SelectObject(m_oldpen);

    }

    else

    {

    m_pdc->FillSolidRect(m_rect,RGB(0x000000F9, 0x000000F8, 0x000000F7));

    }

    }

    void CIconMenu::DrawMenuIcon(CDC* m_pdc,CRect m_rect,int m_icon )

    {

    m_imagelist.Draw(m_pdc,m_icon,CPoint(m_rect.left+2,m_rect.top+4),ILD_TRANSPARENT);

    }

    ⑦改写菜单的DrawItem虚拟方法,根据菜单项的不同状态绘制菜单,代码如下

    void CIconMenu::DrawItem( LPDRAWITEMSTRUCT lpStruct )

    {

    if (lpStruct->CtlType==ODT_MENU)

    {

    if(lpStruct->itemData == NULL)        return;

    unsigned int m_state = lpStruct->itemState;

    CDC* m_dc = CDC::FromHandle(lpStruct->hDC);

    //m_dc.Attach(lpStruct->hDC);

    CString str =  ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemText;

    LPSTR m_str = str.GetBuffer(str.GetLength());

    int m_itemID = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemID;

    int m_itemicon = ((CMenuItemInfo*)(lpStruct->itemData))->m_IconIndex;

    CRect m_rect = lpStruct->rcItem;

    m_dc->SetBkMode(TRANSPARENT);

    switch(m_itemID)

    {

    case -2:

    {

    DrawTopMenu(m_dc,m_rect,(m_state&ODS_SELECTED)||(m_state&0x0040)); //0x0040 ==ODS_HOTLIGHT

    DrawItemText(m_dc,m_str,m_rect);

    break;

    }

    case -1:

    {        

    DrawItemText(m_dc,m_str,m_rect);

    break;

    }

    case 0:

    {

    DrawSeparater(m_dc,m_rect);

    break;

    }

    default:

    {                

    DrawComMenu(m_dc,m_rect,0xfaa0,0xf00ff,m_state&ODS_SELECTED);

    DrawItemText(m_dc,m_str,m_rect);

    DrawMenuIcon(m_dc,m_rect,m_itemicon);

    break;

    }

    }

    }

    }

    ⑧在框架类中引入CIconMenu头文件,定义一个CIconMenu类型成员m_menu。处理框架类的WM_DRAWITEM消息,在其消息处理函数中调用m_menu对象的MeasureItem方法,代码如下:

    void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)

    {

    m_menu.MeasureItem(lpMeasureItemStruct);        

    //        CFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);

    }

    ⑨在框架类的OnCreate方法中将m_menu对象关联到应用程序中的菜单窗口,代码如下

    m_menu.AttatchMenu(this->GetMenu()->GetSafeHmenu());

    m_menu.ChangeMenuItem(&m_menu,TRUE);

    • 创建图标菜单[1]

    ①创建对话框工程,新建一个菜单资源设置好菜单,创建一个菜单类CMenuIcon,派生于Cmenu

    <<IconMenu.rar>>

    Author:         SKySeraph

    Email/GTalk: zgzhaobo@gmail.com    QQ:452728574

    From:         http://www.cnblogs.com/skyseraph/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的劳动成果。


    作者:skyseraph
    出处:http://www.cnblogs.com/skyseraph/
    更多精彩请直接访问SkySeraph个人站点:http://skyseraph.com//
    Email/GTalk: zgzhaobo@gmail.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    linux 权限管理命令
    大三上学期总结
    C# 读写Excel的一些方法,Aspose.Cells.dll
    Topshelf 创建.net服务整理和安装步骤(转)
    你必须知道的.NET之特性和属性(转)
    用SQL语句删除一个数据库的所有表和所有存储过程
    System.DllNotFoundException: 无法加载 DLL“FileTracker.dll”: 动态链接库(DLL)初始化例
    关于消息队列的使用[转]
    PhpStorm使用技巧小结
    转载]C#实现获取浏览器信息
  • 原文地址:https://www.cnblogs.com/skyseraph/p/1870876.html
Copyright © 2011-2022 走看看