4. 菜单

4.1 弹出菜单

本节主要讲解如何在主对话框的指定区域内通过鼠标右击来弹出一个菜单选项。最终效果图如图4.1。

如图4.1鼠标只能在指定区域(图中深色区域)内右击时弹出菜单,在指定区域外点击时不执行创建菜单操作。具体操作步骤如下:

(1) 首先在指定区域响应鼠标右击消息,需要在主对话框类中添加消息句柄WM_RBUTTONUP,并在该消息响应函数void CFDlg::OnRButtonUp(UINT nFlags, CPoint point)中进行坐标判断,示例代码如下:

void CFDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
RECT myrc;//指定窗口区域
RECT wndrc;//主对话框窗口区域
RECT myrc_to_wndrc;//指定区域相对主窗口坐标
int pt_to_wndrcX;//光标X位置相对主窗口坐标
int pt_to_wndrcY;//光标Y位置相对主窗口坐标
CPoint pt_to_screen(point);//建立一个相对屏幕坐标系下的光标位置坐标
//获取指定区域的窗口指针
CWnd* mywnd = GetDlgItem(IDC_BITMAPAREA);
//获取指定窗口的客户坐标
mywnd->GetClientRect(&myrc);
//指定区域相对屏幕坐标系下的坐标
mywnd->ClientToScreen(&myrc);
//获取主窗口的客户区域坐标
GetClientRect(&wndrc);
//主窗口的客户区域相对屏幕坐标系下的坐标
ClientToScreen(&wndrc);
//光标位置相对屏幕坐标下的坐标
ClientToScreen(&pt_to_screen);
//计算指定窗口区域和光标位置相对主窗口客户区域的坐标
myrc_to_wndrc.left = myrc.left - wndrc.left;
myrc_to_wndrc.right = myrc.right - wndrc.left;
myrc_to_wndrc.top = myrc.top - wndrc.top;
myrc_to_wndrc.bottom = myrc.bottom - wndrc.top;
pt_to_wndrcX = pt_to_screen.x - wndrc.left;
pt_to_wndrcY = pt_to_screen.y - wndrc.top; if ( pt_to_wndrcX > myrc_to_wndrc.left && pt_to_wndrcX < myrc_to_wndrc.right &&
pt_to_wndrcY > myrc_to_wndrc.top && pt_to_wndrcY < myrc_to_wndrc.bottom)
{
//在指定区域进行鼠标右击消息响应操作,本节是创建弹出式菜单
}
CDialog::OnRButtonUp(nFlags, point);
}

(2) 其次创建弹出式菜单,示例代码如下:

CMenu mymenu;
if (mymenu.CreatePopupMenu())
{
//定义两条菜单项显示的字符串,其中‘&’比较有用,用于对弹出菜单通过指定键盘字符来响应
CString strFSR("第 1 条(&F)");
CString strWH("第 2 条(&S)");
//增加第1条菜单项,函数的第二个参数在Resource.h文件已经定义:
// #define IDM_FSRMENU 0x0020
// #define IDM_WHMENU 0x0030
mymenu.AppendMenu(MF_STRING, IDM_FSRMENU, strFSR);
//添加一条分割线
mymenu.AppendMenu(MF_SEPARATOR);
mymenu.AppendMenu(MF_STRING, IDM_WHMENU, strWH );
//在指定位置显示一个弹出式菜单
mymenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt_to_screen.x, pt_to_screen.y,this);
}

(3) 查看MSDN对CMenu::TrackPopupMenu的解释可知,TrackPopupMenu的第4个参数表示哪个窗口拥有这个菜单,该窗口处理菜单的WM_COMMAND消息。因此还需要添加对菜单条目的响应处理,示例代码如下:

BOOL CFDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
//添加菜单条目的命令消息代码
if (wParam = = IDM_FSRMENU)
{
MessageBox("选择第 1 条菜单选项");
}
else if (wParam = = IDM_WHMENU)
{
MessageBox("选择第 2 条菜单选项");
}
else
{
CDialog::OnCommand(wParam,lParam);
}
return TRUE;
}

此外还需要对OnCommand函数进行申明:

virtual BOOL OnCommand( WPARAM wParam,  LPARAM lParam );系统框架调用该函数。

最后,结合图文方式介绍几个菜单条目操作:

(1) 菜单条目前添加位图,示例代码如下:

CString strFSR("第 1 条(&F)");
CString strWH("第 2 条(&S)");
// 增加第1条菜单条目,函数的第一个参数选择了MF_CHECKED,表示该菜单条目前有一个选中位图
//(形如“√”),如图4.2的第1条菜单条目所示
mymenu.AppendMenu(MF_STRING | MF_CHECKED , IDM_FSRMENU, strFSR );
mymenu.AppendMenu(MF_SEPARATOR);//添加分割线
mymenu.AppendMenu(MF_STRING, IDM_WHMENU, strWH );//添加第2条菜单条目
//添加第3条菜单条目,函数的第1个参数选择了MF_CHECKED
mymenu.AppendMenu(MF_CHECKED, 0x0040,"第 3 条(&T)");
// 为第3条菜单条目前增加一个位图,函数的第3、4参数分别表示当菜单未选中时使用的位图和菜单选
// 中时所用的位图。因此首先之前已经创建了两幅CBitmap对象。如图4.2所示,第3条菜单的状态是选
// 中,因此前面的“√”消失,取而代之的是一幅位图。而当第3条菜单条目是未被选中(AppendMenu
// 第1个参数是MF_UNCHECKED)那么此时该条目前显示的是未选中状态的位图,如图4.3。
mymenu.SetMenuItemBitmaps(0x0040,MF_BYCOMMAND,&uncheck_map,&check_map);
mymenu.AppendMenu(MF_STRING, 0x0050,"第 4 条(&D)");//添加第4条菜单条目

实现效果如图4.2和4.3:

(2) 创建层叠菜单,效果图如图4.4:

示例代码如下:

CMenu mymenu;
CMenu newmenu;//--
//创建一个层叠菜单,在后续操作时将其关联到主菜单的指定条目上
newmenu.CreatePopupMenu();
newmenu.AppendMenu(MF_UNCHECKED,0x0060,"层叠1");
newmenu.AppendMenu(MF_CHECKED,0x0070,"层叠2");
newmenu.AppendMenu(MF_STRING,0x0080,"层叠3");
CBitmap check_map;
CBitmap uncheck_map;
if (mymenu.CreatePopupMenu())
{
check_map.LoadBitmap(IDB_BITMAP3);
uncheck_map.LoadBitmap(IDB_BITMAP4);
CString strFSR("第 1 条(&F)");
CString strWH("第 2 条(&S)");
mymenu.AppendMenu(MF_STRING | MF_CHECKED , IDM_FSRMENU, strFSR );
mymenu.AppendMenu(MF_SEPARATOR);
//创建层叠菜单时,AppendMenu的第2个参数是层叠菜单的句柄,第1个参数为MF_POPUP
mymenu.AppendMenu(MF_POPUP, (UINT)newmenu.m_hMenu, strWH ); mymenu.AppendMenu(MF_CHECKED, 0x0040,"第 3 条(&T)");
mymenu.SetMenuItemBitmaps(0x0040,MF_BYCOMMAND,&uncheck_map,&check_map);
mymenu.AppendMenu(MF_STRING, 0x0050,"第 4 条(&D)"); mymenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt_to_screen.x, pt_to_screen.y, this);
}

4.2 窗口菜单

最后介绍一下如何在对话框窗口创建菜单,如图4.5所示:

方法很简单,只需要在BOOL CFDlg::OnInitDialog()函数中添加如下代码:

CMenu mymenu;

mymenu.LoadMenu(IDR_MENU1);

SetMenu(&mymenu);

mymenu.DestroyMenu();

其中ID号IDR_MENU1是在资源中创建一个菜单资源如图4.6所示:

最后对每个菜单选项进行ID号编辑后,即可在OnCommand函数中进行消息响应操作。

MFC技术积累——基于MFC对话框类的那些事儿5的更多相关文章

  1. MFC技术积累——基于MFC对话框类的那些事儿

    1. 创建对话框类 (1)打开VC++6.0环境,点击:文件→新建: (2)在弹出的新建对话框中选择:工程→MFC AppWizard (exe)→输入工程名称(例如:功能调试)→工程保存路径名→确定 ...

  2. MFC技术积累——基于MFC对话框类的那些事儿2

    3. 绘图 3.1 对话框资源编辑 首先通过添加控件的方式来创建一个简单的绘图对话框如图所示,创建步骤为: 第一.在VC++6.0软件环境的灰色空白区域右击,选中Controls,然后会弹出一个控件对 ...

  3. MFC技术积累——基于MFC对话框类的那些事儿3

    3.3.2 创建图形画刷来实现位图加载 1.首先在Resource View中导入一幅位图,位图大小96×96像素: 2.其次在主对话框中添加一个静态文本资源,ID号是IDC_BITMAPAREA,添 ...

  4. MFC技术积累——基于MFC对话框类的那些事儿4

    3.3.4 借助兼容DC加载DIB位图 创建一个与设备环境相兼容的DC,通过将位图暂时导入至兼容DC,然后利用CDC::BitBlt 或者CDC::StretchBlt函数将位图绘制到设备环境中. 示 ...

  5. MFC技术内幕系列之(四)---MFC消息映射与消息传递内幕

    ////////////////////////////////////////////////////////////////////////////////////                 ...

  6. MFC编程入门之八(对话框:创建对话框类和添加控件变量)

    创建好对话框资源后要做的就是生成对话框类了.生成对话框类主要包括新建对话框类.添加控件变量和控件的消息处理函数. 例程Addition是基于对话框的程序,所以程序自动创建了对话框模板IDD_ADDIT ...

  7. mfc 在VC的两个对话框类中传递参数的三种方法

    弄了好久,今天终于把在VC中的对话框类之间传递参数的问题解决了,很开心,记录如下: 1. 我所建立的工程是一个基于MFC对话框的应用程序,一共有三个对话框,第一个对话框为主对话框,所对应的类为CTMD ...

  8. 【转】VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)

    原文网址:http://www.jizhuomi.com/software/153.html 前两讲中鸡啄米为大家讲解了如何创建对话框资源.创建好对话框资源后要做的就是生成对话框类了.鸡啄米再声明下, ...

  9. VS2010/MFC对话框三:创建对话框类和添加控件变量

    创建对话框类和添加控件变量 前两讲中讲解了如何创建对话框资源.创建好对话框资源后要做的就是生成对话框类了.生成对话框类主要包括新建对话框类.添加控件变量和控件的消息处理函数等. 例程Addition是 ...

随机推荐

  1. java中io类型及成熟io框架

    就io本身而言,概念上有5中模型:blocking I/O, nonblocking I/O, I/O multiplexing(select and poll), singal driven I/O ...

  2. BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组

    BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...

  3. macbook pro 一些操作经验记录

    [一]启用root用户 (1)打开终端 (2)输入命令:sudo passwd root (3)给root设置密码 (4)然后再终端输入命令:su root 进行登陆 [二]解压eclipse压缩包, ...

  4. [POI 2014] Little Bird

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3831 [算法] 单调队列优化动态规划 时间复杂度 : O(N) [代码] #incl ...

  5. UI:数据库练习、滤镜效果

    相机处理滤镜效果 滤镜主要使用在相机的美颜. #import "ViewController.h" #import "ImageUtil.h" #import ...

  6. 【207】WinForm Chart类

    目录: 在工具箱中找到 Chart 控件并使用 设置 Chart 属性 代码中设置属性 属性中设置属性 Chart 类说明 ChartAreas ChartAreaCollection 类 Chart ...

  7. Jmeter学习之While Controller

    参考 https://www.cnblogs.com/richered/p/8404641.html https://blog.csdn.net/rwang99/article/details/511 ...

  8. python学习笔记4-时间函数

    1 time #时间与日期 import time; # This is required to include time module. ticks = time.time() print (&qu ...

  9. Redis的相关命令

    Redis的相关命令 redis程序的命令 /usr/bin/redis-benchmark /usr/bin/redis-check-aof /usr/bin/redis-check-rdb /us ...

  10. 两分钟彻底让你明白Android Activity生命周期(图文)!(转载)

    转自:http://kb.cnblogs.com/page/70125/ 大家好,今天给大家详解一下Android中Activity的生命周期,我在前面也曾经讲过这方面的内容,但是像网上大多数文章一样 ...