第四部分装饰应用程序的外观教学课件

上传人:痛*** 文档编号:179647442 上传时间:2023-01-02 格式:PPT 页数:136 大小:457.03KB
返回 下载 相关 举报
第四部分装饰应用程序的外观教学课件_第1页
第1页 / 共136页
第四部分装饰应用程序的外观教学课件_第2页
第2页 / 共136页
第四部分装饰应用程序的外观教学课件_第3页
第3页 / 共136页
点击查看更多>>
资源描述
第四章第四章 装饰应用程序的外观装饰应用程序的外观 创建友好,美观的用户界面是成功设计和编制一个 Windows 应用程序的重要组成部分,程序用户界面的设计编程工作包括菜单、控制栏(其中包括工具栏、状态栏、对话框栏等)创建和控制、对话框、帮助信息的制作和运行,以及框架、视图窗口的位置和大小控制等。其中对话框的制作和运行操作将在下一章中作详细的描述。在 AppWizard 创建的应用程序框架中,菜单,工具栏,状态栏和视图窗口均可以缺省隶属于主框架窗口,并由主框架窗口管理和控制。一个典型主框架窗口的组成以及与用户界面各个组成部分的关系如下图所示:SDI 应用程序框架SDI主主框框架架窗窗口口标题栏标题栏菜单栏菜单栏工具栏窗口工具栏窗口状态栏窗口状态栏窗口视图窗口视图窗口子子窗窗口口 MDI 应用程序框架MDI主主框框架架窗窗口口标题栏标题栏菜单栏菜单栏工具栏窗口工具栏窗口状态栏窗口状态栏窗口标题栏标题栏MDI子子框框架架窗窗口口视图窗口视图窗口子子窗窗口口 MFC AppWizard 所生成的应用程序主框架窗口可以选择拥有缺省的基本菜单、相应的工具栏、状态栏和由系统自动确定框架窗口位置和尺寸,但在实际编程中往往需要在此基础上修改和添加自定义的菜单、工具栏、状态栏以及由用户确定框架窗口位置和尺寸,使应用程序外观满足特定的程序功能、特定的用户和特定的使用环境的需要。MFC 为工具栏,状态栏,菜单,主框架窗口提供了相应的基类,以便实现对这些程序外观组成部分的创建和各种操作。这些类在 MFC 中的派生层次结构如下:工具栏和状态栏分别由 CToolBar 和 CStatusBar 类描述,它们都是控制栏类 CControlBar 的派生类,而 CControlBar又是 CWnd 的派生类,因此,工具栏和状态栏本身也是一个能响 应消息的特定窗口,在主框架窗口中可以视为是子窗口。CObjectCCmdTargetCWndCControlBarCToolBarCStatusBarCDialogBarCReBar菜单是由 CMenu 类描述,它是直接从 CObject 类派生的,因此该类的对象只能用于完 成菜单的创建、跟踪、修改、销毁和发送命令消息,而本身 不能响应消息;在主框架窗中可以视为用于发送命令消息的 一个特定区域。CObjectCMenu主框架窗口是由 CFrameWnd(用于 SDI)或 CMDIFrameWnd 和 CMDIChildWnd(用于 MDI),它们都是 CWnd 的直接或间接派 生类。CObjectCCmdTargetCWndCFrameWndCMDIFrameWndCMDIChildWnd 由 AppWizard 创建的文档视图结构的应用程序主框架窗口类对象中缺省的工具栏被定义成名为 m_wndToolBar 的 CToolBar 类对象成员,而状态栏被定义成名为 m_wndStatusBar 的 CStatusBar 类对象成员。创建和显示工具栏和状态栏的操作应在程序主框架窗类 CMainFrame 对象所关联的窗口已经创建完成(窗口句柄已有效)但还未显示时进行,即在窗口创建消息 WM_CREATE 的响应成员函数 OnCreate 被调用中完成的。因此,需要在 CMainFrame 类中重新定义 OnCreate 函数,以便在主框架窗口显示之前添加任何需要附加的初始化工作,例如创建和显示工具栏和状态栏、创建其他子窗口等。与其它 Windows 资源所对应的 MFC 类一样,CMenu 类也是将菜单的句柄和属性和对菜单属性的各种操作等封装了起来,并且只有当菜单句柄有效时,对菜单属性的操作才是合法的。通常情况下,菜单总是主框架窗口的一个区域,所以当主框架窗口的产生函数或 LoadFrame 函数被调用时,与菜单资源相关联的CMenu 对象作为框架窗口的保护成员被创建。因此,通常情况下,编程者只需要通过设计菜单的静态资源,而且无须通过 CMenu 类对象的调用对象的行为,就能满足程序对主菜单的一般设计编程需求。但在程序需要动态创建新菜单或修改已有菜单时,则必须调用 CMenu 对象的行为。如果你需要修改主框架窗口的菜单,你可能需要通过窗口类 CWnd 的成员函数 GetMenu 获取保护成员 CMenu 对象的指针,并通过该指针对该菜单对象进行各种需要的访问和操作,以便满足特殊的菜单设计编程需求,例如:动态切换不同菜单;动态隐藏和显示菜单;动态添加和删除菜单项;动态禁止和激活菜单项;动态为菜单项添加图形标签;动态创建浮动的弹出式环境菜单。对框架和视图窗口的外观操作,就是对它们的位置、大小、状态的控制,称之为放置(Placement)操作。视图窗口是包含在框架窗口中的,它随着框架窗口的变化而变化,换句话说,对视图窗口的放置操作是通过对框架窗口的放置操作实现的。虽然用户可以方便地通过框架窗口提供的最大化、最小化等窗口操作界面对框架和视图窗口的放置进行动态交互控制,但在不少情况下,还是需要在程序中通过代码对框架和视图窗口的放置进行定制操作。例如,希望程序在运行开始时能保持最近一次运行的框架和视图窗口的位置、大小、状态。实现这些放置操作是窗口创建过程中完成的,这对于 SDI 和 MDI 应用程序是不完全一样的,对于 MDI,不仅要考虑主框架窗口的放置,还要考虑子框架窗口的放置。本章将通过 5 类实例程序分别讲述如何实现上述外观设计:第 1 类实例讲解工具栏和状态栏编程;第 2 类实例讲解 CDialogBar 编程;第 3 类实例讲解 CReBar 编程;第 4 类实例讲解菜单编程;第 5 类实例讲解具有持续特性的定制框架窗口类编程。4.1 创建浮动工具栏4.1.1 利用 AppWizard 自动创建工具栏 在 MFC 中,工具栏资源和工具栏类 CToolBar 是实现工具栏的两个要素。创建工具栏对象的基本步骤为:创建工具栏资源;创建一个 CToolBar 对象;调用 CToolBar:Create 函数创建工具栏窗口;调用 CToolBar:LoadToolBar 载入工具栏资源。在使用 AppWizard 生成的默认配置的应用程序框架中包括了能创建一个缺省工具栏的四步操作的所有代码,因此修改工具栏中的按钮只需要修改缺省工具栏资源就可以实现。而如果需要创建缺省工具栏以外的工具栏,则必须在 AppWizard 生成的框架基础上,效仿上述缺省资源和代码添加相应的自定义资源和代码。为此,分析创建缺省工具栏的代码是十分必要的。创建一个 SDI 应用程序项目“”(使用 AppWizard 的缺省选择),查询所创建的应用程序框架的代码,可以发现与工具栏有关的资源和代码有:1 在资源中添加了工具栏资源 IDR_MAINFRAME:2 在 CMainWnd 的定义中添加了定义工具栏对象成员的代码:CToolBar m_wndToolBar;3 在重新定义的 CMainWnd:OnCreate 中添加了创建工具栏,装 载工具资源和初始化工具栏的缺省代码。分析 CMainWnd:OnCreate,该虚函数首先调用了基类中定义 的版本 CFrameWnd:OnCreate 进行基类部分的初始化工作,然后可以添加主框架窗口所需要的任何初始化代码,其中包 括了对工具栏的创建和初始化操作:创建工具栏窗口 创建工具栏窗口的函数是 CToolBar:Create 或CToolBar:CreateEx 它们的原型分别为:BOOL Create(CWnd*pParentWnd,/父窗口指针DWORD dwStyle=WS_CHILD|WS_VISIBLE|CBRS_TOP,/风格UINT nID=AFX_IDW_TOOLBAR/*工具栏子窗口 ID*/);BOOL CreateEx(CWnd*pParentWnd,/父窗口指针DWORD dwCtrlStyle=TBSTYLE_FLAT,/工具栏控件风格DWORD dwStyle=WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP,CRect rcBorders=CRect(0,0,0,0),/工具栏的矩形边界UINT nID=AFX_IDW_TOOLBAR/*工具栏子窗口 ID*/);其中:pParentWnd 是指向工具栏的父窗口,即主框架窗口对象的 指针。dwCtrlStyle 和 dwStyle 的设置是决定所创建的工具栏的外观 和状态的重要因素,可设置的样式值包括 CWnd 的样式和 CToolBar 的样式两部分(祥见 MSDN 的有关部分)。如果创建成功,返回真实的;否则返回错误的。例如,在本例中实现创建工具栏窗口的缺省代码为:m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC);注意,该调用中第 4 参数 rcBorders 和第 5 参数 nID 使用了缺省值 CRect(0,0,0,0)和 AFX_IDW_TOOLBAR。加载工具栏资源 为工具栏对象加载资源的函数为 CToolBar:LoadToolBar,其 原型为:BOOL LoadToolBar(LPCTSTR lpszResourceName/*资源名*/);BOOL LoadToolBar(UINT nIDResource/*资源 ID*/);本例中实现加载工具栏资源的代码为:m_wndToolBar.LoadToolBar(IDR_MAINFRAME);IDR_MAINFRAME 是工具栏资源的 ID。如果资源加载成功,则 返回 TRUE 的;否则返回 FALSE 的。设置工具栏停靠特性 实现设置的函数为 CControlBar:EnableDocking,其原型为:void EnableDocking(DWORD dwStyle);参数为停靠样式,种类和取值参考 MSDN 中的相关部分。本例中实现设置的代码为:m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);参数 CBRS_ALIGN_ANY 所指示的停靠样式是允许工具栏停靠 到主框架窗口中的任何一边。设置主框架窗口的工具栏停靠特性 实现该设置的函数为 CFrameWnd:EnableDocking,其原型:void EnableDocking(DWORD dwdocStyle);参数为停靠样式,种类和取值参考 MSDN 中的相关部分。本例中实现设置的代码为:EnableDocking(CBRS_ALIGN_ANY);参数 CBRS_ALIGN_ANY 所指示的停靠样式是使框架窗口的任 何一边都可以停放控制栏。在拥有多个控制栏的框架窗口中 该函数只需调用一次。把工具栏停靠在主框架窗口中的确定位置 实现停靠操作的函数为 CFrameWnd:DockControlBar,原型:void DockControlBar(CControlBar*pBar,UINT nDockBarID=0,LPCRECT lpRect=NULL);本例中实现停靠的代码为:DockControlBar(&m_wndToolBar);使工具栏按照创建工具栏窗口时的默认位置(框架窗口工作 区的顶部),实现停靠操作。4.1.2 添加自定义工具栏 创建一个名为 的 SDI 应用程序项目,参照由 AppWizard缺省创建的工具栏添加自定义工具栏。1 自定义工具栏资源 使用资源编辑器添加一个标识为 ID_TOOLBAR1 的工具栏资源 其中包括两个按钮:2.添加自定义工具栏的程序代码 在 CMainFrame 类中增加一个 CToolBar 类的保护成员对象:CToolBar m_wndToolBar1;在 CMainFrame:OnCreate 添加对应于 m_wndToolBar1 的创建、加载资源和初始化代码:标识操作提示文本ID_LINEID_CIRCLE绘制一条直线绘制一条直线n直线直线绘制一个圆绘制一个圆n圆圆 if(!m_wndToolBar1.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)|!m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1)TRACE0(Failed to create toolbarn);return-1;/fail to create m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar1);此时编译运行应用程序,可以看到新增加的自定义工具栏,但工具栏中的按钮是灰色的,即不能对它进行任何操作。4.1.3 自定义工具栏的命令响应及其用户界面更新在 CTbView 类中,添加工具栏按钮 ID_LINE 和 ID_CIRCLE 的命令消息和界面更新命令消息的响应。1 为 CTbView 类增加保护数据成员和枚举:int m_nDraw;/指示当前的绘图类别。enumLINE,CIRCLE;/定义可以使用的绘图类别。2 在 CTbView 的构造函数中对 m_nDraw 进行初始化:m_nDraw=LINE;3.使用 ClassWizard 为命令消息 ID_LINE 和 ID_CIRCLE 定义命令 响应函数和用户界面更新函数。在类定义文件中添加了这些成员函数的原型:afx_msg void OnLine();afx_msg void OnCircle();afx_msg void OnUpdateLine(CCmdUI*pCmdUI);afx_msg void OnUpdateCircle(CCmdUI*pCmdUI);在类实现文件中添加了上述成员函数的操作定义如下:void CTbView:OnLine()m_nDraw=LINE;void CTbView:OnCircle()m_nDraw=CIRCLE;void CTbView:OnUpdateLine(CCmdUI*pCmdUI)pCmdUI-SetCheck(m_nDraw=LINE);void CTbView:OnUpdateCircle(CCmdUI*pCmdUI)pCmdUI-SetCheck(m_nDraw=CIRCLE);4 编译运行 4.1.4 自定义工具栏的隐藏/显示 要使自定义的工具栏能像缺省工具栏那样具有隐藏和显示操作功能必须添加以下资源和代码:1 在主菜单 IDR_MAINFRAME 的“查看”弹出菜单中增加新的菜单 项 自定义工具栏,其标识值为 ID_VIEW_TOOLBAR12 在主框架窗口类 CMainFrame 中,为 ID_VIEW_TOOLBAR1 定义 命令响应函数和用户界面更新函数 在类定义文件中添加这些成员函数的原型:afx_msg void OnViewToolbar1();afx_msg void OnUpdateViewToolbar1(CCmdUI*pCmdUI);在类实现文件中添加上述成员函数的操作定义:void CMainFrame:OnViewToolbar1()ShowControlBar(&m_wndToolBar1,m_wndToolBar1.IsWindowVisible()?FALSE:TRUE,FALSE);void CMainFrame:OnUpdateViewToolbar1(CCmdUI*pCmdUI)pCmdUI-SetCheck(m_wndToolBar1.IsWindowVisible();3 编译运行 4.1.5 动态删除和添加工具栏中按钮 如果希望通过程序动态地从已经创建的工具栏中删除一些按钮或向工具栏中添加一些按钮,则需要使用 CToolBar 类对象中的 CToolBarCtrl 类对象成员来实现,而这个对象成员可以通过调用 CToolBar:GetToolBarCtrl 函数获得实例 是在实例 Tb的基础上增加了通过程序代码对工具栏中的按钮进行动态删除和添加的功能:1 在 CMainFrame 类定义中增加下列保护数据成员:/for saving buttons of the m_wndToolBar TBBUTTON m_tbButtons11;/for saving the most and least count of buttons int m_nMost,m_nLeast;2 在 CMainFrame:OnCreate 中增加下列初始化代码:/Save some TBBUTTONs for restoring later m_nMost=m_wndToolBar.GetToolBarCtrl().GetButtonCount();/Save the most count of buttons for(int I=2;I m_nMost-1;i+)m_wndToolBar.GetToolBarCtrl().GetButton(i,&m_tbButtonsi);/Delete some buttons from m_wndToolBar.DeleteTBButtons(2,m_nMost-3);/Save the least count of buttons m_nLeast=m_wndToolBar.GetToolBarCtrl().GetButtonCount();3 为 CMainFrame 定义删除和恢复工具栏按钮的保护成员函数:在定义文件中增加这两个函数的原型声明:void RecoverTBButtons(int index,int count);void DeleteTBButtons(int index,int count);在实现文件中增加这两个函数的定义代码:void CMainFrame:DeleteTBButtons(int index,int count)for(int I=index;I index+count;i+)m_wndToolBar.GetToolBarCtrl().DeleteButton(index);/从工具栏中顺序删除索引为 index 的按钮。ShowControlBar(&m_wndToolBar,TRUE,TRUE);/重新显示变化后的工具栏。void CMainFrame:RecoverTBButtons(int index,int count)for(int I=index;I Enable(m_wndToolBar.GetToolBarCtrl().GetButtonCount()=m_nMost);void CMainFrame:OnUpdateRecoverButtons(CCmdUI*pCmdUI)pCmdUI-Enable(m_wndToolBar.GetToolBarCtrl().GetButtonCount()=m_nLeast);6 编译运行Tb1 4.2 创建自定义状态栏 分析“”项目中关于状态栏的代码。不难发现状态栏也是窗口,该窗口一般分成几个窗格,在每个窗格中可以显示不同的信息。自动创建的缺省状态栏包括了四个窗格,分别显示菜单命令提示和键盘的大写、数字、滚屏锁定状态。状态栏是由 CStatusBar 类实现的。状态栏的典型创建步骤:定义一个 CStatusBar 对象;为状态栏的每个窗格定义 ID,并为每个窗格定义了标题字符 串资源(字符串资源和窗格的 ID 相同);调用CStatusBar:Create 创建状态栏窗口;调用CStatusBar:SetIndicators 函数分配窗格,并将状态栏的每 个窗格与对应 的字符串资源绑定。4.2.1 利用 AppWizard 自动创建状态栏 使用 AppWizard 的缺省选择创建的程序框架能自动创建一个缺省状态栏。分析程序中与状态栏有关的代码,对于修改原有的状态栏和创建自定义状态栏都是十分必要的。与缺省状态栏有关的资源和代码包括:1 CMainFrame 类中定义中添加了状态栏对象保护成员:protected:CStatusBarm_wndStatusBar;2 在 CMainFrame 类实现文件中添加了把状态栏分割为窗格的全程静态数组定义 static UINT indicators=ID_SEPARATOR,/status line indicatorID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,;其中:ID_SEPARATOR 对应的窗格用于显示菜单命令提示。其他三项用于显示键盘相应的键状态,它们所对应的字符串在资源 String Table 中被定义为:STRINGTABLE DISCARDABLE BEGIN ID_INDICATOR_CAPS CAP ID_INDICATOR_NUM NUMID_INDICATOR_SCRL SCRLEND 确定状态栏窗格数目和内容的 indicators 由几个和哪些 ID 组 成取决于程序的需要。如果 indicators 中加入新元素,则要为新元素指定 ID,还要 根据需要,在字符串资源中定义 ID 标识的描述字符串。3 创建状态栏窗口 与工具栏一样,状态栏创建操作也是在 CMainFrame:OnCreate 完成的。实现该操作的代码:if(!m_wndStatusBar.Create(this)|!m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)TRACE0(Failed to create status barn);return-1;/fail to create 其中 Create 和 SetIndicators 函数的原型:BOOL Create(CWnd*pParentWnd,/父窗口指针DWORD dwStyle=WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,UINT nID=AFX_IDW_STATUS_BAR /*状态栏 ID*/);其中状态栏样式参数包括如下三种:CBRS_TOP Control bar is at top of frame window.CBRS_BOTTOM Control bar is at bottom of frame window.CBRS_NOALIGN Control bar is not repositioned when the parent is resized.注意:状态栏不支持浮动。BOOL SetIndicators(const UINT*lpIDArray,int nIDCount);这两个成员函数调用成功,返回 TRUE,否则返回 FALSE。由于状态栏不支持浮动,所以就不必设置其停靠特性。4.2.2 自定义状态栏 实例“Sb”是在实例“Default”的基础上对状态栏 m_wndStatusBar 进行了如下修改:第一个窗格在保持原有功能的基础上,使它能够显示鼠标在 窗口工作区中移动时的位置信息。将第四个窗格中显示的键状态修改为显示键盘的 键的 状态,即按下 键,窗格显示文本信息“SHIFT”,释放 键,窗格中的文本信息“SHIFT”消失。增加第五个窗格用于显示当前时间(时:分:秒)。1 在 indicators 数组中删除 ID_INDICATOR_SCRL,并添加新元素 ID_INDICATOR_SHIFT 和 ID_INDICATOR_CLOCK:static UINT indicators=ID_SEPARATOR,/status line indicatorID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SHIFT,ID_INDICATOR_CLOCK,;2 选择菜单命令 View-Resource Symbols,在资源符号对话框中 为 ID_INDICATOR_SHIFT 和 ID_INDICATOR_CLOCK 定义 ID 值。3 在资源 String Table 中为新增的 ID 添加字符串:4 更新时间窗格 实现该功能首先要利用系统定时器产生变化的当前时间,并将产生的时间转换成格式为“时:分:秒”的字符串;然后通过调用CStatusBar:SetPaneText 函数将时间字符串显示在第五窗格中。SetPaneText 的原型如下:BOOL SetPaneText(int nIndex,LPCTSTR lpszNewText,BOOL bUpdate=TRUE);标识值字符串ID_INDICATOR_SHIFTID_INDICATOR_CLOCK SHIFT00:00:00 动态地获取当前时间可以通过定时读取系统当前时间实现,为此可以使用 ClassWizard 为 CMainFrame 增加系统定时器窗口消息 WM_TIMER 的映射项、响应函数 OnTimer 的声明和定义。在 OnTimer 函数中添加操作代码:void CMainFrame:OnTimer(UINT nIDEvent)CTime time;time=CTime:GetCurrentTime();CString s=time.Format(%H:%M:%S);m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_CLOCK),s);CFrameWnd:OnTimer(nIDEvent);设置系统定时器 为了使系统能按照要求的时间间隔发出时间中断,需要在CMainFame 构造函数或 OnCreate 中调用 CWnd:SetTimer 设置能指定时间间隔发出中断的定时器。SetTimer 的原型:UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD);参数:nIDEvent 定时事件标识,一个程序中可以有多个定时器。nElapse定时器的定时间隔。lpfnTimer指向自定义定时器设置函数,NULL 表示使用系统定时器设置函数。返回:如果设置成功,返回定时事件标识;否则返回 0。本例中在 CMainFrame:OnCreate 中添加了如下设置代码:m_nTimer=SetTimer(1,1000,NULL);/定时间隔为1000ms其中 m_nTimer 是在 CMainFrame 中添加的数据成员:class CMainFrame public CFrameWnd private:UINT m_nTimer;/用于保存定时器标识。已经设置成功的定时器在其所属窗口关闭撤消时,应该调用CWnd:KillTimer 同时撤消,为此使用 ClassWizard 为 CMainFrame 增加主框架窗口关闭消息 WM_CLOSE 的映射项、响应函数 OnClose 的声明和定义。为 OnClose 函数添加操作代码:void CMainFrame:OnClose()KillTimer(m_nTimer);CFrameWnd:OnClose();5 更新 按键状态对应的窗格 该功能是通过添加 ID_INDICATOR_SHIFT 的用户界面更新消息的映射项、响应函数 OnUpdateShift 的声明和定义实现的。完成这些编程只能手工进行,而不能使用 ClassWizard。在 CMainFrame 中加入消息处理函数 OnUpdateShift 的原型:/AFX_MSGafx_msg void OnUpdateShift(CCmdUI*pCmdUI);DECLARE_MESSAGE_MAP()在 CMainFrame 类的消息映射表中加入映射条目:/AFX_MSG_MAPON_UPDATE_COMMAND_UI(ID_INDICATOR_SHIFT,OnUpdateShift)END_MESSAGE_MAP()实现 CMainFrame:OnUpdateShift 函数定义:void CMainFrame:OnUpdateShift(CCmdUI*pCmdUI)short flag=:GetKeyState(VK_SHIFT);if(flag Enable(TRUE);else pCmdUI-Enable(FALSE);6 显示鼠标移动位置信息 由于当主框架窗口工作区的顶层窗口是视图窗口时,鼠标移 动发出的窗口消息 WM_MOUSEMOVE 只能被视图窗口捕获。因此,对该消息的响应处理应该在视图类定义。用 ClassWizard 为 CSbView 添加窗口消息 WM_MOUSEMOVE 的响应,并为响应函数 OnMouseMove 添加如下操作代码:void CSbView:OnMouseMove(UINT nFlags,CPoint point)CMainFrame*pm=(CMainFrame*)AfxGetMainWnd();CStatusBar*psb=(CStatusBar*)pm-GetControlBar(AFX_IDW_STATUS_BAR);CString str;if(psb)str.Format(X=%d Y=%d,point.x,point.y);psb-SetPaneText(0,str);CView:OnMouseMove(nFlags,point);由于 OnMouseMove 中使用了 CMainFrame,所以需要在视图类 CSbView 的实现文件添加包含文件:#include“MainFrm.h”7 编译运行“”4.3 创建 DialogBar DialogBar 具备工具栏和对话框两者的特性。可视为 DialogBar创建一个具有工具栏特点的非模态的“对话框”,其中可以包含能够与其他 Windows 对象交互的控件;并且作为 CControlBar 的派生类对象,还具有绘制边界、停靠和浮动等功能。本例中,将介绍如何在一个应用程序中创建一个 DialogBar。创建名为“”的 SDI 应用程序项目,视图基类为 CEditView,资源语言为英文。在该项目需要添加的 DialogBar 中有三个控件:按钮,用于发出清除视图窗口中文本的命令;组合框,用于从其列表中选取文本内容显示在视图窗口中;静态文本框,作为组合框的提示。1 创建 DialogBar 资源 添加一个对话框 IDD_DIALOG1。修改对话框 IDD_DIALOG1:对话框 ID 修改为 IDD_MYDLGBAR。对话框 style 选 Child(子窗口),Border 选为 None(无边框)。删除该对话框中缺省控件,添加下列控件:控件类型控件名称控件标识控件属性按钮静态文本框组合框 ClearColor列表字串:RedGreenBlue ID_CLEARTEXTIDC_STATICIDC_COMBO1 默认默认去除 Sort 选项 2 将 DialogBar 添加到主框架类中 在 CMainFrame 类中增加 CDialogBar 类对象保护成员:protected:CStatusBarm_wndStatusBar;CToolBarm_wndToolBar;CDialogBar m_dlgbar;在 CMainFrame:OnCreate 中增加下面的操作代码:int CMainFrame:OnCreate(LPCREATESTRUCT lpCreateStruct)if(!m_dlgbar.Create(this,IDD_MYDLGBAR,CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY,IDD_MYDLGBAR)TRACE0(Failed to create dialog barn);return-1;/fail to createm_dlgbar.EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_dlgbar);return 0;3 使用 ClassWizard 在 CDbView 类中添加消息响应函数 按钮 ID_CLEARTEXT 的消息响应函数 OnCleartext void CDbView:OnCleartext()SetWindowText(“”);/清除视图窗口 组合框 IDC_COMBO1 的选项处理函数 OnSelchangeCombo1 void CDbView:OnSelchangeCombo1()CMainFrame*pm=(CMainFrame*)AfxGetMainWnd();CComboBox*pcb=(CComboBox*)(CDialogBar*)(pm-GetControlBar(IDD_MYDLGBAR)-GetDlgItem(IDC_COMBO1);int index=pcb-GetCurSel();CString str;pcb-GetLBText(index,str);this-SetWindowText(str);4 对话框栏的隐藏/显示 要使自定义的对话框栏能像缺省工具栏那样具有隐藏和显示操作功能须在 CMainFrame 的定义和实现文件中添加代码:在主菜单 IDR_MAINFRAME 的弹出菜单View 中增加新的菜单项ID_VIEW_DIALOGBAR 使用 ClassWizard 为 ID_VIEW_DIALOGBAR 定义命令响应函数和用户界面更新函数:void CMainFrame:OnViewDialogbar()ShowControlBar(&m_dlgbar,m_dlgbar.IsWindowVisible()?FALSE:TRUE,FALSE);void CMainFrame:OnUpdateViewDialogbar(CCmdUI*pCmdUI)pCmdUI-SetCheck(m_dlgbar.IsWindowVisible();5 编译运行“”4.4 创建 ReBar ReBar 又称为伸缩栏。它支持停靠,不仅可以移动,还可以改变大小。伸缩栏可以包含多个段(Band)组成,每段可以由手柄(Gripper Bar),位图、文本标题和子窗口的组合而成,但每段的子窗口只能有一个。由于伸缩栏也是一种控制栏,它的创建与工具栏、状态栏等有相似之处,影响伸缩栏的风格的样式通常包括三类:标准窗口风格,如 WM_CHILD、WM_VISIBLE 等;通用控件风格,如 CCS_TOP、CCS_BOTTOM、CCS_VERT 等;伸缩栏控件风格,格式为 RBS_XXX,常用的风格如下:创建伸缩栏的步骤:创建伸缩栏各段的控件资源。定义一个 CReBar 类对象。调用 CReBar:Create 函数创建伸缩栏窗口。调用 CRebar:AddBar 或 CReBarCtrl:InsertBand 插入各段。风格标识风格含义RBS_BANDBORDERRBS_VERTICALGRIPPERRBS_AUTOSIZE 伸缩栏控件绘制相邻段之间的线条手柄在垂直伸缩栏中垂直显示当控制栏改变大小时,伸缩栏改变段的布局 4.4.1 利用AppWizard 生成的伸缩栏 只要在创建项目过程的 step 4 of 6 对话框中选定工具栏风格为 Internet Explorer Rebar 而不选 Normal 就可以在所创建的应用程序中生成一个伸缩栏,而不是一般工具栏。本例中的伸缩栏由一个工具栏和一个 对话框栏组成。4.4.2 手动生成伸缩栏1 创建一个名为“”的 SDI 应用程序。使用英文为资源语言。2 生成一个 DialogBar 资源 添加一个对话框模板资源 IDD_DIALOG1。修改对话框模板资源 IDD_DIALOG1:修改对话框 ID 为 IDD_MYDLGBAR;将对话框的 Style 选为 Child,Border 选为 None;在对话框中添加标识为 ID_BUTTON1 的按钮 BUTTON1 和标识为 ID_BUTTON2 的按钮 BUTTON2。3 使用 ClassWizard 为对话框资源 IDD_MYDLGBAR 定义相应的类CMyDlgBar。由于在 VC 6.0 中 ClassWizard 不支持 CDialogBar,所以在创建 CMyDlgBar 的过程中先选基类为 CDialog,待创建后,再用 CDialogBar 替换 CMyDlgBar 的定义和实现代码中所有的CDialog。注意,构造函数的初始化表代码需要去掉。CMyDlgBar:CMyDlgBar(CWnd*pParent/*=NULL*/)/AFX_DATA_INIT(CMyDlgBar)/NOTE:the ClassWizard will add member initialization here/AFX_DATA_INIT4 在 CMyDlgBar 中使用 ClassWizard 为按钮 BUTTON1 和 BUTTON2 的 BN_CLICKED 消息添加响应函数:5 将 DialogBar 添加到主框架窗口类中 在 CMainFrame 的定义文件添加包含文件:#include“MyDlgBar.h”在CMainFrame 类中添加CMyDlgBar 类对象的保护成员:CMyDlgBar m_mydlgbar;在CMainFrame:OnCreate 中增加创建DialogBar 的代码:if(!m_mydlgbar.Create(this,IDD_MYDLGBAR,WS_CHILD|WS_VISIBLE,IDD_MYDLGBAR)TRACE0(Failed to create dialog barn);return-1;6 创建其他段(Band)创建将加入伸缩栏其他段(Band)的控件。本例要加入的另一个控件就是已经自动创建的工具栏,所以无须增加代码,但需要将设置工具栏停靠特性的语句注解掉或删除。7 创建伸缩栏窗口 为 CMainFrame 增加一个 CReBar 类对象的保护成员:CReBar m_myReBar;在 CMainFrame:OnCreate 中增加创建伸缩栏窗口的代码:if(!m_myReBar.Create(this)TRACE0(Failed to create rebarn);return-1;8 在 CMainFrame:OnCreate 增加将已经成功创建的工具栏和 DialogBar 添加到伸缩栏中的代码:m_myReBar.AddBar(&m_wndToolBar,MAP,NULL,RBBS_GRIPPERALWAYS|RBBS_FIXEDBMP);m_myReBar.AddBar(&m_mydlgbar,MAP,NULL,RBBS_GRIPPERALWAYS|RBBS_FIXEDBMP);9 编译运行“Rb”此时,发现 DialogBar 的按钮的灰色的,这是因为我们对按钮的响应处理是定义在 CMyDlgBar中的,而命令处理过程没有将消息传给 DialogBar,从而搜索 CMyDlgBar 的消息映射表所致。解决的方法是重载 CMainFrame:OnCmdMsg,将消息传给 CMyDlgBar 类对象:BOOL CMainFrame:OnCmdMsg(UINT nID,int nCode,void*pExtra,AFX_CMDHANDLERINFO*pHandlerInfo)if(m_mydlgbar.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo)return TRUE;return CFrameWnd:OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);4.5 菜单界面操作 在本节中,通过一个示例程序介绍如何使用菜单类 CMenu 对框架窗口中的菜单进行各种灵活的操作,以便达到改善界面的目的。这些操作主要有:不同菜单之间的切换;隐藏和显示菜单;添加和删除菜单项;为菜单项添加图象标签;创建浮动的弹出式环境菜单。首先通过 AppWizard 创建一个名为“”的 SDI 应用程序。在创建过程中,除了在 Step 1 of 6 对话框中选择 Single Document 和英语作为资源语言外,其余均为默认选项。根据示例程序要达到的目的,在已经产生的程序框架中进行如下的编程工作:4.5.1 添加资源1 在框架默认的主菜单 IDR_MAINFRAME 中增加子菜单 Menu 用于发出实现对菜单的各项操作的命令:菜单中的各项命令要完成的操作如下表:菜单项命令名菜单项标识命令操作描述Menu Disappear ID_MENU_DISAPPEAR隐藏当前的框架主菜单 Menu ChangeID_MENU_CHANGE切换当前的框架主菜单 Default MenuID_MENU_DEFAULT恢复程序运行初始时的默认主菜单 Append Popup in TopID_POPUP_APPEND_TOP在主菜单顶层添加弹出式子菜单 Append Popup in SubmenuID_POPUP_APPEND_SUB在Menu子菜单中添加弹出式子菜单 Insert New ItemID_ITEM_INSERT在菜单的特定位置插入新的菜单项 Remove Specified ItemID_ITEM_REMOVE从菜单中删除已插入的特定菜单项 Add Bitmap to ItemID_BITMAP_ADD_ITEM将位图作为标签加到特定菜单项2 添加一个新的主菜单 IDR_NEWMENU 用于与程序框架默认的主菜单 IDR_MAINFRAME 之间的切换。该菜单资源是在复制IDR_MAINFRAME 的基础上删除其中的 Edit 子菜单,以示两个菜单之间的区别。3 增加一个新菜单 IDR_POPUP 作为动态加入到主菜单的弹出式子菜单以及浮动的环境菜单。该菜单资源实际上是在复制主菜单中的 Edit 子菜单的基础上,增加 Redo 和 Select All 菜单命令以及 Select All 命令与其他命令之间的分隔线。4 在工具条中增加一个工具按钮 ID_MENU_APPEAR 用于当前主菜单被隐藏后,恢复主菜单操作,并且为此按钮定义一个键盘加速键 Ctrl+M。注意,该按钮没有对应的菜单项。5 增加位图 IDB_PRINT 作为加入到特定菜单项 ID_FILE_PRINT 的位图标签和插入的图形菜单项。6 为准备插入的菜单项确定标识值:ID_ITEM_SEPARATOR、ID_NEW_ITEM1 和 ID_NEW_ITEM2。4.5.2 实现菜单的隐藏、显示和切换1 使用 ClassWizard 为菜单项标识值为:ID_MENU_DISAPPEAR、ID_MENU_APPEAR、ID_MENU_CHANGE 和 ID_MENU_DEFAULT 的命令定义响应函数并建立消息映射:在CMainFrame 类的头文件 MainFrm.h 中增加了如下消息响应函数和用户界面更新函数的原型声明:afx_msg void OnMenuDisappear();afx_msg void OnUpdateMenuDisappear(CCmdUI*pCmdUI);afx_msg void OnMenuAppear();afx_msg void OnUpdateMenuAppear(CCmdUI*pCmdUI);afx_msg void OnMenuChange();afx_msg void OnMenuDefault();在源文件 MainFrm.cpp 中加入了上述函数的空定义体并且在CMainFrame 类的消息映射表中增加了下列消息映射条目:ON_COMMAND(ID_MENU_DISAPPEAR,OnMenuDisappear)ON_UPDATE_COMMAND_UI(ID_MENU_DISAPPEAR,OnUpdateMenuDisappear)ON_COMMAND(ID_MENU_APPEAR,OnMenuAppear)ON_UPDATE_COMMAND_UI(ID_MENU_APPEAR,OnUpdateMenuAppear)ON_COMMAND(ID_MENU_CHANGE,OnMenuChange)ON_COMMAND(ID_MENU_DEFAULT,OnMenuDefault)2 在 CMainFrame 类中加入与这些操作有关的保护数据成员:HMENU m_hOldMenu;/用于保存程序框架旧的主菜单句柄 HMENU m_hNewMenu;/用于保存程序框架新的主菜单句柄 HMENU m_hCurMenu;/用于保存程序框架当前的主菜单句柄 CMenu m_CurMenu;/辅助菜单对象用于各类菜单操作 在 CMainFrame 类构造函数中对这些数据成员进行初始化:m_hCurMenu=NULL;/使该菜单句柄无效 CMenu menu;menu.LoadMenu(IDR_NEWMENU);/装载用于切换操作的菜单资源 m_hNewMenu=menu.Detach();/获得用于切换操作的菜单句柄注意:在构造函数中添加语句:m_bAutoMenuEnable=FALSE;这将使得命令用户界面更新消息失效,即使没有对应的命令消息响应函数,菜单项也不会变灰(无效)。3 完成各个响应函数的编码:隐藏主菜单:void CMainFrame:OnMenuDisappear()m_hCurMenu=GetMenu()-Detach();/保存主菜单句柄,并使其与主菜单对象分离。SetMenu(NULL);/设置框架的主菜单对象为空,使菜单消失。void CMainFrame:OnUpdateMenuDisappear(CCmdUI*pCmdUI)pCmdUI-Enable(m_wndToolBar.IsWindowVisible();/当工具栏可见时,该命令有效。显示主菜单:void CMainFrame:OnMenuAppear()ASSERT(m_hCurMenu);m_CurMenu.Attach(m_hCurMenu);/将保存的主菜单句柄与当前菜单对象相关 SetMenu(&m_CurMenu);/设置菜单对象,使菜单显示。m_hCurMenu=NULL;/将保存主菜单句柄的变量置空void CMainFrame:OnUpdateMenuAppear(CCmdUI*pCmdUI)pCmdUI-Enable(m_hCurMenu!=NULL);/当主菜单被隐藏的状态时,该命令有效。切换主菜单:void CMainFrame:OnMenuChange()CString str;CMenu*curMenu=GetMenu();ASSERT_VALID(curMenu);curMenu-GetMenuString(1,str,MF_BYPOSITION);/获取主菜单顶层位置为1 的子菜单项字串 if(str=“&Edit”)/判断当前主菜单是否为缺省主菜单 ASSERT(m_hNewMenu);m_hOldMenu=curMenu-Detach();/分离并保存缺省主菜单句柄 m_CurMenu.Attach(m_hNewMenu);/切换当前的主菜单为新主菜单 else ASSERT(m_hOldMenu);m_hNewMenu=curMenu-Detach();/分离并保存当前的主菜单句柄 m_CurMenu.Attach(m_hOldMenu);/切换当前的主菜单为缺省主菜单 SetMenu(&m_CurMenu);/设置框架窗口的当前菜单对象,显示切换后的的菜单。恢复框架默认的主菜单:void
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 成人自考


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!