第7章 单文档应用程序
7.1.3 View类
视图类用于显示文档数据,一个文档可以与 多个视图关联,但一个视图只能关联一个文 档,多个视图可共用一个框架窗口,如Word 中可在左边显示目录,右边显示正文,两个 视图共用一个框架窗口。 当文档数据发生改变后,通过文档类的 UpdateAllViews函数通知视图需要更新,在 内部调用View类的OnUpdate函数,默认情 况下,OnUpdate函数在内部调用Invalidate 函数,使整个视图无效并重绘。
7.2.4 右键菜单
右键菜单也称为环境(Context)菜单, 可在屏幕任意位置显示,一般在窗口右 键单击鼠标时弹出。系统的默认消息处 理函数DefWindowProc,在处理 WM_RBUTTONUP和 WM_NCRBUTTONUP消息时,自动发 送WM_CONTEXTMENU消息,可添加 该消息的处理函数,实现右键菜单。 【范例7-3】新建一个单文档工程名为 Sdi062,在视图窗口中使用右键菜单设 置背景色。
7.1.5 类联系方式
(3)在框架(CMainFrame)中访问视 图(View) CSdi061View* pView=(CSdi061View*)GetActiveView(); (4)在框架(CMainFrame)中访问文 档(Doc) CSdi061Doc* pDoc=(CSdi061Doc*)GetActiveDocume nt(); (5)在视图(View)中访问文档(Doc)
7.2 菜单
菜单(Menu)是Windows程序的一个标 准元素,每个菜单项可以包含弹出式子 菜单,可为某个子菜单项添加消息处理 函数,单击该项后,自动调用关联函数。 可以禁用、勾选菜单项,AppWizard自动 生成的单文档程序自带有一个菜单资源, 可修改该菜单资源,添加消息映射函数。
7.2.1 添加菜单资源
7.1.5 类联系方式
(6)在文档(Doc)中访问关联的所有 视图(View) POSITION pos = GetFirstViewPosition(); while (pos != NULL) { CSdi061View* pView = (CSdi061View*)GetNextView(pos); //相关操作 }
7.4.1 设置分区
【范例7-5】新建一个单文档工程名为 Sdi064,在状态栏同步显示鼠标坐标位 置和颜色信息。
7.4.2 更新内容
在程序运行时,可动态更新状态栏窗格 显示的文本,用于显示各种提示信息, 如当前鼠标位置、当前位置的颜色信息 等。SetPaneText函数设置窗格显示的文 本,格式如下: BOOL CStatusBar::SetPaneText(int nIndex,LPCte=TRUE) 参数: nIndex:要更新的窗格的位置索引。 lpszNewText:新文本值。
7.1.1 App类
【范例7-1】新建一个单文档工程名为 Sdi061,了解AppWizard自动生成的几 个类。
7.1.2 Doc类
文档类负责文件的读取和存储,一个文 档可以与多个视图关联,如有一组数据, 在视图1中用表格形式显示,在视图2中 用折线图形式显示,CDocument类提供 两个函数用于循环访问其关联的视图类。 GetFirstViewPosition函数获取与文档关 联的视图列表的第一个视图,格式如下: POSITION CDocument::GetFirstViewPosition() const 返回值:第一个视图的位置。
7.1.3 View类
Invalidate函数设置整个CWnd窗口的客 户区无效,格式如下: void CWnd::Invalidate(BOOL bErase=TRUE) 参数: bErase:是否擦除客户区的背景,默认 为TRUE。 GetDocument函数获取与视图关联的文 档类对象的指针,格式如下: CDocument* CView::GetDocument()
7.1 了解生成类
使用MFC应用程序向导创建一个单文档 程序后,自动生成5个类,其中 CMainFrame、App、Doc、View四个类 是单文档程序的基础支架,CMainFrame 类负责程序窗口的框架显示,包括菜单、 工具栏、状态栏等元素,App类负责程序 的启动和退出,Doc类负责文件的读取和 保存,View类负责数据的显示、编辑, 以及与用户的交互操作等,了解这几个 基本类有助于快速掌握单文档程序的开 发。
7.1.3 View类
ASSERT断言宏用于判断其参数表达式 是否为真,如ASSERT(1==0); 会弹出一 个错误窗口,并退出程序。类似的断言 宏VERIFY具有同样的功能,区别在于 ASSERT宏只能在Debug模式下可用,在 Release版本中失效,而VERIFY宏在 Release版本仍然被执行,但不会中断程 序。 #ifndef和#endif是预编译指令,用于预编 译判断,根据条件决定要编译哪些语句, #ifndef判断是否没有定义某个宏,即if no
7.1.2 Doc类
文档/视图的功能很强大,但也很复杂, MFC框架在后台完成了大量工作,若仅 通过AppWizard自动生成的一些代码,是 无法了解文档/视图如何实现的,有必要 阅读MFC源代码,简要的了解工作流程, 对于自身能力的提升非常有帮助。 注:MFC框架的源代码是公开的,MFC 的函数功能及调用流程,在源代码中得 到完全体现,若不确定某个函数的内部 实现,可打开源代码,找到函数定义处, 阅读后便可柳暗花明。源代码路径
7.1.3 View类
OnPaint函数内部先获取视图窗口的设备 环境,用于在DC上绘制图形。 OnPrepareDC函数在实际绘制图形前调 用,用于设置设备环境的属性。OnDraw 函数用于图形的重绘实现,格式如下: virtual void OnDraw(CDC* pDC) = 0 参数: pDC:设备环境的指针。 CView类中OnDraw函数被声明为纯虚函 数,在派生类中必须重写该函数,否则
7.1.3 View类
非调试版本使用inline关键字声明为内联 函数,在头文件中定义,代码如下: #ifndef _DEBUG inline CSdi061Doc* CSdi061View::GetDocument() //内联函数 { return (CSdi061Doc*)m_pDocument; } #endif
第7章 单文档应用程序
单文档是一种常见的文件处理程序,如 Windows自带的画图、记事本等。相对 于对话框简单的拖放控件,单文档程序 提供强大的文件读取显示功能,其核心 为文档/视图结构,文档用于读取、保存 文件中的数据,视图用于数据的显示、 编辑,在该框架基础上,添加需要的功 能,可快速实现强大的文件处理显示功 能。
【范例7-2】在工程Sdi061上添加菜单资 源,并实现程序运行时,动态添加、移 除、更新、禁用、勾选菜单项。
7.2.2 更新菜单
菜单一般在框架窗口的顶部显示,可在 程序运行时动态改变菜单项,通过 SetMenu和GetMenu函数设置、获取窗 口使用的菜单。 SetMenu函数设置窗口使用的菜单,格 式如下: BOOL CWnd::SetMenu(CMenu* pMenu) 参数: pMenu:新菜单的CMenu类指针,若为 NULL,当前菜单被清除。
7.1.3 View类
当视图窗口失效,或被其他窗口遮盖后 重新显示时,需要重新绘制,Windows 发送WM_PAINT消息到视图窗口,自动 调用OnPaint()重绘函数,函数代码如下: void CView::OnPaint() //重绘函 数 { CPaintDC dc(this); //视图窗口的设 备环境 OnPrepareDC(&dc); //绘制图形前设 置属性
7.3.1 添加工具栏资源
【范例7-4】新建一个单文档工程名为 Sdi063,添加一个工具栏,实现鼠标交 互式绘点、绘线功能。
7.3.3 添加按钮处理函数
若尚未为按钮添加消息处理函数,则按 钮变灰不可用,可使用类向导,为工具 栏按钮添加消息处理函数,实现交互式 绘点、绘线功能。
7.4 状态栏
状态栏作为控制条的一种,一般停靠在 程序窗口的底部,不可移动,常用来显 示各种提示信息,如鼠标经过一个工具 按钮或菜单项时,会在状态栏显示功能 提示信息。不同于工具栏,状态栏只有 一个,可修改系统自带的状态栏,显示 特定信息。
7.2.2 更新菜单
GetMenu函数获取窗口的菜单指针,格 式如下: CMenu* CWnd::GetMenu() const 返回值:菜单的CMenu类指针,若无菜 单返回NULL. DrawMenuBar函数用于重绘窗口的菜单, 应在改变菜单项后调用,格式如下: void CWnd::DrawMenuBar() CMenu类用于操作菜单资源,提供一系 列方法如创建、添加、删除、更新菜单
7.1.3 View类
AppWizard自动生成的CView派生类重定 义了GetDocument函数,且分为Debug 和非Debug内联两种版本,Debug版本在 cpp文件中定义,代码如下: CSdi061Doc* CSdi061View::GetDocument() { ASSERT(m_pDocument>IsKindOf(RUNTIME_CLASS(CSdi061 Doc))); //断言宏 return (CSdi061Doc*)m_pDocument;
7.1.2 Doc类
当文档内容更新后,文档所关联的视图 也应同步更新,UpdateAllViews函数用 于刷新关联的所有视图,格式如下: void CDocument::UpdateAllViews(CView* pSender,LPARAM lHint=0L,CObject* pHint=NULL) 参数: pSender:要更新的视图的指针,若为 NULL更新所有视图。 lHint:包含修改的信息。
7.1.2 Doc类
GetNextView函数获取当前位置视图的指 针,格式如下: CView* CDocument::GetNextView(POSITION& rPosition) const 参数: rPosition:当前视图的POSITION值引用, 调用该函数后,该值指向下一个位置。 注:默认情况下,单文档程序只有一个 文档、一个视图,但可以通过切换视图