1、双击COMMAND弹出对话框,要求在该对话框中输入消息处理函数的名称,选择默认函数名,确定后,双击消息处理函数OnEllipse进行编辑(矩形同样进行编辑,消息处理函数为OnRectangle),代码如下: int flag;void CEx61View:OnEllipse() /椭圆画图 flag=0;/ TODO: Add your command handler code hereInvalidate();UpdateWindow();CDC *pDC=GetDC();pDC-Ellipse(100,100,200,200);OnRectangle() /矩形画图 flag=1; / T
2、ODO: Invalidate(); UpdateWindow(); CDC *pDC=GetDC(); pDC-Rectangle(100,100,200,200);(5)给“椭圆”和“矩形”子菜单添加UPDATE_COMMAND_UI消息,并在消息处理函数中实现在选中的子菜单项前打钩。UPDATE_COMMAND_UI消息的添加和WM_COMMAND消息类似。在上图中,在Messages中选择UPDATE_COMMAND_UI即可。消息处理函数为:Void CE61View:OnUpdateEllipse(CCmdUI* pCmdUI)pCmdUI-SetCheck(flag=0); Vo
3、id CE61View:OnUpdateRectangle(CCmdUI* pCmdUI)SetCheck(flag=1);例2.用上下文菜单实现例1的功能。创建上下文菜单的步骤如下:(1)创建一个新菜单资源。用AppWizard创建一个基于MFC的SDI应用程序,工程名为ex62。在工作区的ResourceView选项卡中,右击Menu文件夹,在弹出菜单中选择插入菜单便可创建一个新的菜单资源,其ID为IDR_MENU1。右击IDR_MENU1,在弹出菜单中选择属性,修改其ID为IDR_POPMENU。双击IDR_POPMENU资源进入编辑对话框,对弹出式菜单进行编辑,方法见例1,完成后的菜单
4、资源如图:(2)添加代码,实现鼠标右键单击时显示弹出式菜单。在查看菜单项中选择建立类向导来添加右键单击弹出式菜单WM_CONTEXTMENU及消息处理函数,这时MFC会发现创建了一个新资源,将询问是否创建一个新类,取消后,弹出下图对话框,选择ID为CEx62View,Messages为WM_CONTEXTMENU,双击该消息或单击Add Function按钮,将为该消息添加默认处理函数,单击Edit Code按钮进入OnContextMenu()函数,对其进行编辑。在相应的消息处理函数中添加代码如下:void CEx62View:OnContextMenu(CWnd* pWnd, CPoint
5、 point) Add your message handler code here CMenu menu; menu.LoadMenu(IDR_POPMENU); menu.GetSubMenu(0)-TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,AfxGetMainWnd();(3)为“椭圆”和“矩形”子菜单添加WM_COMMAND和UPDATE_COMMAND_UI消息映射,并编辑相应的消息处理函数;具体方法同例1。修改例1,增加工具栏按钮的步骤如下:打开工程ex61,在ResourceView页面中,双击Tool
6、bar文件夹,可以看到有一个ID位ID_MAINFRAME的工具栏。双击ID_MAINFRAME工具栏,在工具栏编辑框中出现如下图所示的工具栏。在工具栏的最右边有一空白按钮,双击该按钮,弹出对话框如下图,其中ID选择ID_ELLIPSE,即“椭圆”按钮。该按钮显示在编辑窗口中,可以通过Graphics和Colors工具箱及鼠标画自己的图标。(矩形工具栏图标同椭圆方法)例3 (状态栏)在状态上添加信息行,用来实时显示当前鼠标在视图中的位置,同时也添加一个状态指示器,用来显示当前是否按下了Ctrl键。步骤如下:第一步,C乘车基于AppWizardexe的单文档工程,名称为ex63。第二步,添加新的
7、窗格,在窗格中显示鼠标的位置,详细步骤如下:(1)为新窗口创建一个ID标识号。选择主菜单中的view下的Resource Symbols菜单项,弹出Resource Symbols对话框,它显示了用户应用程序中的所有资源符号。单击NEW按钮,在显示的New Symbols对话框中添加新的ID值ID_xy,去默认值:确定后关闭对话框。(2)定义新窗格的默认字符串。为了表示一个窗格,ID必须和一个定义它的字符串相连。定义字符串,在Resource View页面下,打开String Table文件夹,双击String Table资源,在字符串编辑器中打开它。双击最后一个空白行,弹出下图对话框, 在I
8、D的下拉列表框中选择ID_xy,在Caption中键入“x=100,y=100”。选中一个以“ID_INDICATOR_”开头的字符串资源,在键盘上按下“Insert“键,插入一个新的字符串资源,将标识号(ID)设置为ID_INDICATOR_CTRL,内容(Caption)设置为“Ctrl键“。(3)添加窗口的ID标识到状态栏的提示符数组中。窗格在状态栏中的位置由状态栏的提示符数组决定。前面提到,在应用程序的MainFrame.cpp文件中定义了提示符数组,若在第一窗格显示“鼠标位置”,修改后的数组如下:static UINT indicators = ID_SEPARATOR, / sta
9、tus line indicator ID_xy, ID_INDICATOR_CTRL, ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL,;第三步,创建状态栏。(1)声明一个CStatusBar类对象。在头文件MainFrm.h中可以看到CStatusBar类对象的声明如下:CStatusBar m_wndStatusBar;(2)调用Create()函数创建状态栏。调用SetIndicators()函数,设置指示器的标识符为数组中相应元素指定的值,装载每个标识符指定的字符串资源并将字符串设为提示符文本。在CMainFrame:On
10、Create()函数中可以状看到态栏的创建代码如下:int CMainFrame:OnCreate(LPCREATESTRUCT lpCreateStruct) if (CFrameWnd:OnCreate(lpCreateStruct) = -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) | !m_wndToolBar.Lo
11、adToolBar(IDR_MAINFRAME) TRACE0(Failed to create toolbarn); / fail to create m_wndStatusBar.Create(this) |m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)Failed to create status barn Delete these three lines if you dont want the toolbar to / be dockable m_wndToolBar.EnableDoc
12、king(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0;第4步,调用SetPaneText()函数更新窗格中的文字。当鼠标移动时,坐标值发生变化,第一窗格内的文字随之相应变化。在CEx63View类中添加WM_ONMOUSEMOVE消息,在其消息处理函数OnMouseMove()中,更新窗格内容,代码如下:void CEx63View:OnMouseMove(UINT nFlags, CPoint point) Add your message handler co
13、de here and/or call default CString str; str.Format(x=%d,y=%d,point.x,point.y); CMainFrame*pMainFrame=(CMainFrame*)(AfxGetApp()-GetMainWnd(); pMainFrame-m_wndStatusBar.SetPaneText(1,str); CView:OnMouseMove(nFlags, point);注:由于CEx63View类使用了CMainFrame类,因此,需要将类的定义包含进来,在CEx63View.cpp文件头部增加 #include “Main
14、Frm.h”。由于在CEx63View类中访问了成员变量m_wndStatusBar,因此需要将成员变量m_wndStatusBar的受保护类型变为公有类型。第5步,添加Ctrl键的消息函数。为了在状态指示器中显示ctrl键的状态,可以在视图类中手工添加相应的消息响应函数。(1)在ex63View.h中找到类的定义处,添加消息处理函数原型。class CEx63View : public CView/ Generated message map functionsprotected: /AFX_MSG(CEx63View) afx_msg void OnMouseMove(UINT nFlag
15、s, CPoint point); afx_msg void OnUpdateKeyCtrl(CCmdUI* pCmdUI); /AFX_MSG DECLARE_MESSAGE_MAP()(2)找到文件ex63View.cpp中消息映射宏的定义处,在其中添加消息映射宏:BEGIN_MESSAGE_MAP(CEx63View, CView) /AFX_MSG_MAP(CEx63View) ON_WM_MOUSEMOVE() ON_UPDATE_COMMAND_UI(ID_INDICATOR_CTRL,OnUpdateKeyCtrl) /AFX_MSG_MAP END_MESSAGE_MAP()(
16、3)在文件ex63View.cpp末尾添加消息响应函数体:OnUpdateKeyCtrl(CCmdUI* pCmdUI) pCmdUI-Enable(:GetKeyState(VK_CONTROL)0); /更新状态指示器编译、链接并运行程序,状态栏中的显示为:,第一窗格显示的内容是ID_xy中定义的字符串,当鼠标移动时,窗口内容随便发生变化。第二窗格则在Ctrl键按下时显示其状态。思考与联系1.资源描述文件的作用是什么?资源页面的作用是什么?答:在基于MFC框架编程中,经常要使用一些位图、菜单、对话框、工具栏之类的资源均在文件资源中,其相关的一些信息也都存储在资源描述文件中。资源界面中有相关
17、于界面设计的一些基本信息。2.resource.h文件的作用是什么?与其他头文件类似,它包含了MFC界面设计的基本函数,通过声明resourse.h头文件,便可以调用其中的库函数用于用户界面的开发。3.菜单消息的消息映射为什么不采用标准的消息映射?菜单消息映射的控件通知消息主要由窗口类即直接或间接由CWND类派生类处理.相对标准WINDOWS消息及控件通知消息而言,命令消息的处理对象范围就广得多.它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。因此菜单的消息映射函数并没有采用标准的消息映射函数。4.为什么一般把快捷键和图标资源的ID定义为菜单的ID相同?图标资源是以位图形式保
18、存的,这一位图资源会放在工程的哪个文件夹中?通过相同的ID可以直接定位到快捷键以及图标资源相对应的菜单上;位图资源是放在工程resourse.h文件夹中。5.在使用CStatusBar类创建状态栏时,定义了全局数组UNIT Indicator=ID_SEPARATOR,ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,试说明这一全局数组的作用。这个全局数组保存了状态栏上各个组件的ID值。6.工具栏类(CStatusBar)如何和工具栏资源进行链接?在声明了一个CStatusBar后,在声明之后,调用Creat()函数创建状态栏,再调用SetIndicators()函数,设置指示器的标识符为数组中相应元素指定的值,装载每个标识符指定的字符串资源并将字符串设为提示符文本。