MFC 单文档中动态添加菜单项和响应菜单事件
- 格式:docx
- 大小:14.63 KB
- 文档页数:2
VS2010添加菜单MFC class wizard(类向导)project:当前工程名class name:需要编辑消息映射(将消息与处理函数一一对应)的类名object ID:该类中当前可以产生消息的对象ID。
Message:该对象能产生的消息Member function:该类的成员函数。
可以添加(Add function),删除(Delete fun…)。
Add class:添加新的类。
右下有个小箭头,可以选择‚new‛或从类库中导入。
SDI:单文档MDI:多文档1.创建MDI工程:打开VS2010,文件,新建,project,选MFC应用程序(MFC AppWizard),填入名称:Menu1,确定。
选多个文档,完成。
编译运行一下,弹出的窗口是Menu11:2.完成后在左侧点资源视图,Menu,IDR_Menu1TYPE,会发现,Menu框架中已经有了‚文件,编辑,视图,帮助‛等菜单。
单击‚帮助‛后面的‚请在此处输入‛,并输入‚Movie(&M)‛,输入(&M)的作用是用户可通过‚Alt+m‛直接打开该菜单项,输入后‘&’自动消失。
左下角的‚菜单编辑项‛中,enable和popup默认为true。
因为Popup为true,即允许有子菜单弹出,所以不用输入ID,下面杂项的ID 为‚无法编辑ID‛。
2.单击Movie下面的框,并在里面输入‘赤壁之战(&C)’。
(&C)表示直接在键盘上按‘C’,即可选择‚赤壁之战‛。
这时,他变成了这个样子,并且左下角的‘菜单编辑器’里出现了内容。
在菜单编辑器里,注意到popup为false,这是可以编辑ID,向下拉菜单,在‚杂项‛中,将ID改为ID_MOVIE1,在Prompt中填入‚打开赤壁电影‛。
此处,直接单击,就可以修改或输入。
3.为菜单添加消息处理函数直接在最上一行菜单栏选‘项目’,类向导,弹出class wizard。
实验3 菜单、工具栏和状态栏一、实验目的通过本实验,掌握菜单、工具栏和状态栏的使用二、实验内容制作一个含有菜单、工具栏和状态栏的单文档应用程序,要求如下:(1)其中菜单栏中添加一个菜单项:“我的菜单(M)”,内容如图3-1所示。
其中,Position Set中的各项分别让工作区的文本向下(Move Down10)、向左(Move Left10)、向上(Move Up10)、向右(Move Right10)移动10个坐标位置。
(a)Text Set菜单项(b)Position Set菜单项(c)Message Set菜单项图3-1“我的菜单(M)”的内容(2)工具栏中添加六个按钮,如图3-2(a)中所示,且工具栏中按钮的功能与对应菜单项功能一致。
(3)状态栏中添加两个信息用来显示鼠标的坐标位置,当鼠标移动时状态中的指针坐标位置会发生变化。
(4)运行结果如图3-2所示。
(a)初始运行结果(b)Text1菜单项的运行结果(c)Text2菜单项的运行结果(d)Position Set菜单项中各菜单项组合运行的结果(e)Hello菜单项的运行结果(f)Visual C++菜单项的运行结果提示:(1)新建一个名称为Menu的单文档使用程序,自动生成CMenuView、CMenuApp、CMenuDoc和CMainFrame四个类。
(2)打开“资源视图”标签,依次展开Menu、Menu.rc、Menu节点,单击IDR_MAINFRAME,打开菜单资源编辑器,进行“我的菜单”的添加,其中热键设置为M,因此菜单项的Caption 属性设置为“我的菜单(&M)”,其子菜单设置如下:添加加速键的方法:资源视图→“Acceleratora”项→双击“IDR_MAINFRAME”→进入加速键设置窗口。
(3)对CMenuView类进行Public类成员变量添加:int m_x;int m_y;CString m_Text;变量添加的方法:方法一:在类视图中选中CMenuView类点击右键,在弹出的快捷菜单中选择“类向导”→“成员变量”选项卡→“添加自定义…”按钮→“添加成员变量”在对话,然后在其中进行变量添加。
MFC实现动态菜单及响应函数MFC中利用CMenu类动态添加弹出菜单和响应函数步骤:1 声明一个菜单:CMenu menu;2 生成菜单对象:menu.CreatePopupMenu();3 给菜单添加上内容:menu.AppendMenu(MF_STRING,WM_CLEARHOSTS,"清除HOSTS");AppendMenu函数具体的意义可以查看MSDN,其中WM_CLEARHOSTS为自定义的一个消息,最后一个参数为菜单的text,点击这个菜单就可以调用WM_CLEARHOSTS消息的处理函数。
4 添加子弹出菜单:CMenu submenu;submenu.CreatePopupMenu();menu.AppendMenu(MF_POPUP,(UINT_PTR)(submenu.m_hM enu),"sub");5 设置当失去焦点时菜单自动消失SetForegroundWindow();6 设置菜单的位置:menu.TrackPopupMenu();以上各步连接起来就是一个完整的动态生成菜单的步骤,当动态生成的菜单很多且菜单又不固定的时候,预先为每个菜单都定义一个消息和消息处理函数是很麻烦且不现实的,现在介绍一种方法来动态响应动态生成的菜单。
其原理就是利用OnCommand函数。
首先,要为每一个动态生成的菜单指定一个ID,方式如下menu.AppendMenu(MF_STRING,ID,"yourMenuName");其中参数ID为一个唯一的整数,可以由你自己指定,当鼠标单击此菜单的时候,系统发送一个消息,此消息优先被OnCommand函数接收,OnCommand函数的原形为:BOOL OnCommand(WPARAM wParam, LPARAM lParam);假如你指定菜单的ID为10001,响应函数的具体写法为:BOOL OnCommand(WPARAM wParam, LPARAM lParam){int menuID = LOWORD(wParam);if(menuID > 10000){//添加你自己的处理代码}}如果是使用对话框的mfc,自己重载OnCommand函数即可做一个MFC程序的时候碰到一个需求。
MFC实现动态菜单及响应函数一、实现步骤1.调用AppendMenu函数在菜单栏添加菜单2.调用AppendMenu函数在菜单栏菜单项添加子菜单3.调用AppendMenu函数在菜单栏菜单项添加动态子菜单4.将菜单所属的窗口句柄传入OnInitMenu函数5.在OnInitMenu函数中清除原有的菜单6.在菜单窗口中添加新的菜单二、代码1.主程序代码```// MFC_DynamicMenu.cpp : 定义应用程序的入口点。
//#include "stdafx.h"#include "MFC_DynamicMenu.h"#define MAX_LOADSTRING 100//全局变量:HINSTANCE hInst; // 当前实例WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名//此代码模块中包含的函数的前向声明:ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPWSTR lpCmdLine,_In_ int nCmdShow)UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);//TODO:在此处放置代码。
//初始化全局字符串LoadStringW(hInstance, IDS_APP_TITLE, szTitle,MAX_LOADSTRING);LoadStringW(hInstance, IDC_MFCCDYNAMICMENU, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);//执行应用程序初始化:if (!InitInstance (hInstance, nCmdShow))return FALSE;}HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MFCCDYNAMICMENU));MSG msg;//主消息循环:while (GetMessage(&msg, nullptr, 0, 0))if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;//// 函数: MyRegisterClass////目标:注册窗口类。
在MFC中创建动态控件的生成与响应作者:风林动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的。
一、创建动态控件:为了对照,我们先来看一下静态控件的创建。
放置静态控件时必须先建立一个容器,一般是对话框,这时我们在对话框编辑窗口中,从工具窗口中拖出所需控件放在对话框中即可,再适当修改控件ID,设置控件属性,一个静态控件就创建好了,当对话框被显示时,其上的控件也会显示。
静态控件不需要调用Create()函数来创建。
而创建动态控件有很大不同,以下以按钮为例,看一下动态控件的创建过程:1.建立控件ID号:ID号是控件的标识,创建控件前必须先为它设置一个ID号。
打开资源中的“String Table”,在空白行上双击鼠标,这时会弹出一个ID属性对话框,在其中的ID编辑框中输入ID,如:IDC_MYBUTTON,在Caption中输入控件标题或注解(注:Caption框不能为空,为空会导致创建失败),这里我输入的是按钮上要显示的文字--动态按钮。
2.建立控件对象:不同种类的控件应创建不同的类对象,按钮控件CButton (包括普通按钮、单选按钮和复选按钮)编辑控件CEdit静态文本控件CStatic标签控件CTabCtrl旋转控件CSpinButtonCtrl滑标控件CSliderCtrl多信息编辑控件CRichEditCtrl进度条控件CProgressCtrl滚动条控件CSrcollBar组合框控件CComboBox列表框控件CListBox图像列表控件CImageCtrl树状控件CTreeCtrl动画控件CAnimateCtrl本例中我们创建一个CButton类的普通按钮。
注意不能直接定义CButton对象,如:CButton m_My But;这种定义只能用来给静态控件定义控制变量,不能用于动态控件。
正确做法是用new调用CButton构造函数生成一个实例:CButton *p_My But = new CButton();然后用CButton类的Create()函数创建,该函数原型如下:BOOL Create( LPCTSTR lpszCaption, DWORD dwSty le, const RECT& rect, CWnd* pParentWnd, UINT nID );lpszCaption是按钮上显示的文本;dwSty le指定按钮风格,可以是按钮风格与窗口风格的组合,取值有:窗口风格:WS_CHILD 子窗口,必须有WS_VISIBLE 窗口可见,一般都有WS_DISABLED 禁用窗口,创建初始状态为灰色不可用的按钮时使用WS_TABSTOP 可用Tab键选择WS_GROUP 成组,用于成组的单选按钮中的第一个按钮按钮风格:BS_PUSHBUTTON 下压式按钮,也即普通按钮BS_AUTORADIOBUTTON 含自动选中状态的单选按钮BS_RADIOBUTTON 单选按钮,不常用BS_AUTOCHECKBOX 含自动选中状态的复选按钮BS_CHECKBOX 复选按钮,不常用BS_AUTO3STATE 含自动选中状态的三态复选按钮BS_3STATE 三态复选按钮,不常用以上风格指定了创建的按钮类型,不能同时使用,但必须有其一。
*************************************************************************************************************程序中会用到多种资源,在为资源确定其ID号时,为了明确区分资源类型,一般都遵循这样一个原则:①菜单资源ID号以“IDM_”开始;光标资源ID号以“IDC_”开始;图标资源ID号以“IDI_”开始。
*************************************************************************************************************(CFrameWnd类、CDialog类和CView类)派生于CWnd类的有MessageBox成员函数,而CXXApp类和CXXDoc类都不是从CWnd类派生的,所以它们都没有MessageBox成员函数,只能使用应用程序框架的函数:AfxMessageBox.最保险的就是只用AfxMessageBox函数。
*************************************************************************************************************程序类对菜单命令的响应顺序自定义添加一个菜单项【test】:打开ClassWizard对话框,在Class Name下拉列表框中选择CMainFrame之外的其他类,分别在视图类、文档类和应用程序类中添加菜单命令响应函数。
运行将会看到弹出的对话框上提示信息:“View Clicked!",这就是说,视图类最先响应这个菜单命令。
下面,我们将视图类的OnTest响应函数删除,再次运行程序,我们会发现是文档类做出了响应。
后面依次删除、运行。
实验发现:响应【test】菜单项命令的顺序是:视图类、文档类、框架类,最后才是应用程序类。
1、消息的分类标准消息除WM_COMMAND之外,所有以WM_开头的消息。
从CWnd派生的类,都可以接收到这类消息。
命令消息来自菜单、加速键或工具栏按钮的消息。
这类消息都以WM_COMMAND呈现。
在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam 参数识别。
从CCmdTarget派生的类,都可以接收到这类消息。
通告消息由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。
这类消息也是以WM_COMMAND形式呈现。
从CCmdTarget派生的类,都可以接收到这类消息。
2、命令消息的路由:注意:通常消息产生时,MFC在后台将窗口过程函数替换为了AfxWndProc(可参考MFC源代码),AfxWndProc函数会调用AfxCallWndProc函数,AfxCallWndProc函数又会调用WindowPro函数,WindowPro函数是CWnd的成员函数,接下来WindowPro函数会调用OnWndMsg函数,OnWndMsg函数会判断消息类型,是标准消息则交由CWnd 类处理;是命令消息则交由OnCommand函数处理;是通告消息则交由OnNotify函数处理。
最后OnCommand和OnNotify函数都会调用OnCmdMsg函数来进行处理。
OnCommand函数会完成命令消息的路由,路由过程:首先消息由CMainFrame交给它的子窗口类CView,如果类中有消息响应函数则响应,否则会转而交给CDoc类处理,如果CDoc类也没有消息响应函数,则CDoc类会将消息交还给CView类,继而交还给CMainFrame类,如果CMainFrame类中也没有消息响应函数,则消息最后由CWndApp 类响应。
3、对菜单编程时,首先要找到菜单,然后找到子菜单,最后才是菜单项。
4、CWnd::GetMenu函数函数原型:CMenu* GetMenu( ) const;CMenu类封装了与菜单相关的操作。
C#WinForm⽤MenuStrip动态⽣成菜单并动态加载事件最近在做WINFORM开发,⼀直都在为主界⾯的点击事件及动态加载菜单苦脑。
现在已解决这个问题了,可以实现数据库或都XML等配置完成动态⽣成菜单及事件加载。
代码如下:private void Form1_Load(object sender, EventArgs e){//添加菜单⼀ToolStripMenuItem subItem;subItem = AddContextMenu("⼊库", menuStrip1.Items, null);//添加⼦菜单AddContextMenu("添加⼊库", subItem.DropDownItems, new EventHandler(MenuClicked));AddContextMenu("⼊库管理", subItem.DropDownItems, new EventHandler(MenuClicked));//添加菜单⼆subItem = AddContextMenu("出库", menuStrip1.Items, null);//添加⼦菜单AddContextMenu("添加出库", subItem.DropDownItems, new EventHandler(MenuClicked));AddContextMenu("出库管理", subItem.DropDownItems, new EventHandler(MenuClicked));}///<summary>///添加⼦菜单///</summary>///<param name="text">要显⽰的⽂字,如果为 - 则显⽰为分割线</param>///<param name="cms">要添加到的⼦菜单集合</param>///<param name="callback">点击时触发的事件</param>///<returns>⽣成的⼦菜单,如果为分隔条则返回null</returns>ToolStripMenuItem AddContextMenu(string text, ToolStripItemCollection cms, EventHandler callback){if (text == "-"){ToolStripSeparator tsp = new ToolStripSeparator();cms.Add(tsp);return null;}else if (!string.IsNullOrEmpty(text)){ToolStripMenuItem tsmi = new ToolStripMenuItem(text);tsmi.Tag = text + "TAG";if (callback != null) tsmi.Click += callback;cms.Add(tsmi);return tsmi;}return null;}void MenuClicked(object sender, EventArgs e){ //以下主要是动态⽣成事件并打开窗体 //((sender as ToolStripMenuItem).Tag)强制转换ObjectHandle t = Activator.CreateInstance("WinForms", "WinForms.Form2");Form f = (Form)t.Unwrap();f.ShowDialog();}。
为<对话框>添加工具条和状态栏前,先说说添加目录菜单栏;1,在Insert下拉菜单中选择Resorce,新建一个MENU,2,在CDialog::OnInitDialog();后面添加代码:CMenu menu;menu.LoadMenu(IDR_MENU1); // 红色部分为你新建MENU的ID索引SetMenu(&menu);为对话框程序添加工具条和状态栏摘要:本文介绍了在对话框程序基础上通过程序控制来动态添加工具条和状态条的实现过程和方法。
一、引言对于不需要文档/视图结构支持的程序一般都采用对话框做为程序的基础框架。
虽然在对话框程序上可以通过修改其属性来添加系统菜单,但对比SDI和MDI程序的工具条和状态栏未免使界面显得简单、单调。
虽然在V isual Basic 中提供有独立的工具条和状态栏标准控件可以直接在对话框上使用,但V isual C++ 6.0所提供的26种基本Windows标准控件却没有将它们包含其中。
因此要在对话框程序中实现工具条和状态栏只能通过编程来动态实现。
二、工具条的实现过程MFC对于工具条和状态栏分别提供了CToolBar和CStatusBar两个基本类库,但由于在实现时MFC 对其做了过多的封装,以至无法了解内部的一些核心技术。
因此本文在实现过程中放弃了相对比较方便的CToolBar和CStatusBar类的使用,而是通过SDK(Software Developers Kit,软件开发工具箱)式的WinAPI 应用程序接口来实现的。
在API函数中经常需要用到对话框的窗口句柄和当前的实例句柄,在SDK程序设计中以上两个句柄可以直接从入口函数WinMain()中引出,而在MFC下也对其做了封装,不能直接获取。
但MFC也为其留有接口:CWnd窗口类提供的GetSafeHwnd()可以返回对话框的窗口句柄;函数AfxGetInstanceHandle()则可以获取当前应用程序的实例句柄。
MFC动态控件添加消息响应MFC动态创建控件的消息处理前些天有⼈在论坛⾥问在动态创建TreeCtrl后怎么响应消息于是便写了⼀点⾃⼰的⼼得现整理如下。
本例在MFC动态创建控件的消息处理前些天有⼈在论坛⾥问在动态创建TreeCtrl后怎么响应消息于是便写了⼀点⾃⼰的⼼得现整理如下。
本例在view中动态创建⼀个ListCtrl并响应其NM_CLICK消息先写出动态创建的代码: 新建⼀SDI⼯程给view加上⼀个成员变量:CListCtrl m_list 在view的OnCreate中创建它:ifm_list.CreateWS_BORDER WS_CHILD WS_VISIBLELVS_ICON LVS_AUTOARRANGELVS_EDITLABELSCRect1010310210thisID_LISTCTRLTRACE0Failed to create ListCtrl windownreturn -1//添加⼀些项CString strforint i0i10istr.Formatitemdim_list.InsertItemistr 其中的ID_LISTCTRL是这个控件的ID当然你可以直接⽤数值来表⽰但为了程序清淅还是定义⼀个常量的好在主菜单View-Resource Symbols弹出的对话框中New按钮在Name下⾯输⼊ID_LISTCTRL. 创建完毕编译链接后就可以运⾏了但你怎么它都没反应当然因为我们还没写消息处理的代码。
通常做法是⼿动写消息处理函数及消息映射⾄少得三步1在头⽂件中定义消息处理函数的原型2在cpp中实现这个函数3在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间写上消息映射。
如果是单单处理⼀个消息的话那还可以忍受消息⼀多的话不但⿇烦还容易出错。
所以我采取下⾯的⽅法: 1.打开about对话框资源放⼊⼀个ListCtrl控件到对话框中并将其ID设为ID_LISTCTRL. 2.CtrlW把Class Name由原来的CAboutDlg改为CxxxView在左边的Object IDS中选择ID_LISTCTRL这时右边会出现相应的通知消息这时就可以跟平常⼀样双击添加消息映射了. 嘿嘿是不是跟在对话框⾥响应控件的消息⼀样很⽅便呀. 有⼀点需要注意只有当打开你加⼊控件的那个对话框资源编辑器的时候按CtrlW时Class Wizard中才会出现那个ID_LISTCTRL还有发⾏时注意把对话框上的listctrl控件删掉.。
MFC 单文档中动态添加菜单项和响应菜单事件
新建一个单文档程序
在查看菜单项中增加两个子菜单,分别为隐藏工具栏(ID_HIDE),新建菜单(ID_NEWMENU) 在Resource.h中增加一个ID_NEWMENU宏
#define ID_NEWMENU WM_USER+101
操作工具栏和状态栏
使用GetDescendantWindow函数获取工具栏和状态栏的指针为ID_HIDE添加消息映射,编辑代码如下
static bool m_Hide=false;
m_Hide=!m_Hide;
//获取工具栏指针
CWnd* pWndToolBar=(CWnd*)GetDescendantWindow(AFX_IDW_TOOLBAR);
//获取状态栏指针
CWnd* pWndStatusBar=(CWnd*)GetDescendantWindow(AFX_IDW_STATUS_BAR);
CMenu* pMenu=GetMenu();
CMenu* pSubMenu=pMenu->GetSubMenu(2);
if(m_Hide)
{
pSubMenu->ModifyMenu(ID_HIDE,MF_BYCOMMAND,ID_HIDE,"显示工具栏");
if(pWndStatusBar!=NULL) pWndStatusBar->SetWindowText("隐藏工具栏");
if(pWndToolBar!=NULL) pWndToolBar->ShowWindow(SW_HIDE);
}
else
{
pSubMenu->ModifyMenu(ID_HIDE,MF_BYCOMMAND,ID_HIDE,"隐藏工具栏");
if(pWndStatusBar!=NULL) pWndStatusBar->SetWindowText("显示工具栏");
if(pWndToolBar!=NULL) pWndToolBar->ShowWindow(SW_SHOW);
}
动态添加子菜单
为ID_NEWMENU增加消息映射,编辑代码如下
static UINT m_NewMenu=ID_NEWMENU+1;
//获取菜单
CMenu* pMenu=GetMenu();
//获取索引为2的菜单项,即第3列菜单
CMenu* pSubMenu=pMenu->GetSubMenu(2);
char buffer[1];
itoa(m_NewMenu-ID_NEWMENU,buffer,10);
if(m_NewMenu<=ID_NEWMENU+5)
{
pSubMenu->AppendMenu(MF_SEPARATOR); //分隔线
pSubMenu->AppendMenu(MF_STRING | MF_ENABLED,m_NewMenu++,
CString("新的菜单")+buffer);
}
//如果m_bAutoMenuEnable为true,则会依次检查View、Document、Frame的
//消息映射表是否有这个弹出菜单中每个菜单项的处理函数,澳门新濠天地官网 如果没有就会把那一项改为灰的
m_bAutoMenuEnable=false;
添加OnCommand的消息映射用来响应添加的子菜单项,代码如下UINT uMsg=LOWORD(wParam);
for(UINT i=ID_NEWMENU+1;i<=ID_NEWMENU+5;i++)
if(uMsg==i)
{
char buffer[1];
itoa(i-ID_NEWMENU,buffer,10);
MessageBox(CString("新的菜单") + buffer);
}
右键菜单
在View类中添加OnRButtonDown的消息映射,代码如下
CMenu pPopMenu;
pPopMenu.CreatePopupMenu();
if(pPopMenu==NULL);
pPopMenu.AppendMenu(MF_STRING,ID_NEWMENU+6,"右键菜单");
this->ClientToScreen(&point);
pPopMenu.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);
在View类中添加OnCommand的消息映射用来响应右键菜单的事件UINT uMsg=LOWORD(wParam);
if(uMsg==ID_NEWMENU+6)
MessageBox(CString("右键菜单"));。