MFC 视图类(CView)介绍

2024-06-18 22:48
文章标签 介绍 mfc 视图 cview

本文主要是介绍MFC 视图类(CView)介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        视图是程序设计中使用率最高的窗口对象,它是用户的主要操作界面。因为它通常以某种形式表示文档数据,所以称之为视图。一个视图对象只关联一个文档对象;一个文档对象可以关联多个视图,每个视图对象以不同形式表示文档数据。

  从文档类中将文档中的数据取出后显示给用户;接受用户对文档中数据的编辑和修改;将修改的结果反馈给文档类,由文档类将修改后的内容保存到磁盘文件中。

  文档负责了数据真正在永久介质中的存储和读取工作,视图呈现只是将文档中的数据以某种形式向用户呈现,因此一个文档可对应多个视图。

  Invalidate(TRUE)将整个窗口设置为需要重绘的无效区域,它会产生WM_PAINT消息,这样OnDraw将被调用。

  假如文档中的数据发生了变化,必须通知所有链接到该文档的视图,这时候文档类的UpdateAllView函数需要被调用。

  然而,除了打印和打印预览外,视图类显示得很简单。

关联文档对象

  前面已经提到,视图需要表示文档数据,所以文档对象与视图对象必须建立关联。这样,当文档数据发生变化时,它可以及时通知视图;当视图需要显示不同的文档数据时,它可以从文档对象中提取。

  在文档/视图框架程序中,文档对象总是在视图之前建立,而在视图的WM_CREATE消息处理函数中,建立了它与文档对象的关联。代码如下:

  Int CView::OnCreate (LPCREATESTRUCT lpcs)

  {

  if (CWnd::OnCreate(lpcs) == -1)

  return -1;

  // m_pDocuemnt视图成员,用于存储相应文档对象的指针,此时为空

  ASSERT(m_pDocument == NULL);

  CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;

  // pContext->m_pCurrentDoc是已经建立的文档对象的指针

  if (pContext != NULL && pContext->m_pCurrentDoc != NULL)

  {

  // 将当前视图加入文档对象的视图列表中,因为一个文档可关联多个视图

  pContext->m_pCurrentDoc->AddView(this);

  /* 在文档的AddView()函数中,已经将当前文档对象指针赋给m_pDocument视图成员。这样,在视图建立之初,二者就建立了关联。*/

  ASSERT(m_pDocument != NULL);

  }

  else

  {

  TRACE(“Warning: Creating a pane with no CDocument.\n”);

  }

  return 0; // ok

  }

  同时,视图类定义了成员函数GetDocument(),返回文档对象的指针。代码如下:

  CDocument* CView::GetDocument() const

  {

  ASSERT(this != NULL);

  return m_pDocument;

  }

  视图总是在文档对象之前销毁,在视图的析构函数中,与文档对象解除关联。代码如下:

  CView::~CView()

  {

  if (m_pDocument != NULL)

  m_pDocument->RemoveView(this);

  }

视图的绘制

  窗口的绘制工作总是在WM_PAINT消息处理中进行的,当窗口需要绘制时,它会收到系统发来的WM_PAINT消息。在绘制过程中,首先要准备显示设备句柄,最后要释放句柄。众所周知,在视图窗口中绘制,无需重载WM_PAINT消息处理函数OnPaint(),因为有一个更加友好的绘制新口:OnDraw()。该函数的实参是一个已经准备好的显示设备,最后无需释放。其实,这一切还是WM_PAINT消息处理函数OnPaint()为我们准备的,代码如下:

  void CView::OnPaint()

  {

  // CPaintDC类维护显示设备

  CPaintDC dc(this);

  OnPrepareDC(&dc);

  OnDraw(&dc);

  }

  OnPrepareDC()是一个虚拟函数,它总是在OnDraw()之前执行,可以重载它,设置绘图模式。因为OnDraw()每次执行,都使用不同的CPaintDC对象,所以本次绘图模式的状态不能保留到下一次。

  OnDraw()在视图基类CView中定义为纯虚函数。例如:

  virtual void OnDraw(CDC* pDC) = 0;

  所以CView是抽象基类,不能实例化,而派生类必须重载OnDraw()

虚函数 OnUpdate

  当文档数据发生变化时,文档对象调用CDocument::UpdateAllView()通知所有视图,作为响应,视图的OnUpdate()成员被调用。所以,重载的OnUpdate()应该能够根据需要,将文档数据的变化反映在视图中。CView::OnUpdate()只是简单地使客户区无效,导致客户区重画。例如:

  void CView::OnUpdate(CView* pSender, LPARAM, CObject*)

  {

  ASSERT(pSender != this);

  UNUSED(pSender); // unused in release builds

  Invalidate(TRUE);

  }

虚函数 OnInitialUpdate()

  在初始创建、调用OnCreate()之后,或者在File/NewFile/Open命令后被框架调用。基类CView::OnInitialUpdate()只是简单地调用OnUpdate(),可以重载它完成初始化工作。但注意,它可能被多次调用。

  void CView::OnInitialUpdate()

  {

  OnUpdate(NULL, 0, NULL);

  }

虚函数 CalcWindowRect

  每当主框架窗口的客户区尺寸发生变化或控制条的位置发生变化,需要重新排列客户区时,调用该函数,根据视图客户区尺寸计算视图窗口的尺寸。

  我们知道,排列主窗口客户区是由CFrameWnd::RecalcLayout()完成的。显然,视图的CalcWindowRect()函数也是由它触发调用的。主窗口的客户区尺寸减掉所有控制占用的部分,剩下的区域分给视图,这部分区域作为实参传入CalcWindowRect()。在CalcWindowRect()函数内,需要计算视图窗口的尺寸。代码如下:

  void CView::CalcWindowRect(LPRECT lpClientRect, UNIT nAdjustType)

  {

  // lpClientRect此时是整个视图客户区的尺寸

  // 需要为滚动条增加尺寸吗

  if (nAdjustType != 0)

  {

  // 调用API,根据窗口风格计算窗口尺寸

  ::AdjustWindowRectEx(lpClientRect, 0, FALSE, GetExStyle());

  DWORD dwStyle = GetStyle();

  if (dwStyle & WS_VSCROLL)

  {

  // 为垂直滚动条增加尺寸

  int nAdjust = afxData.csVScroll;

  if (dwStyle & WS_BORDER)

  nAdjust -= CX_BORDER;

  lpClientRect->right += nAdjust;

  }

  if (dwStyle & WS_HSCROLL)

  {

  // 为水平滚动条增加尺寸

  int nAdjust = afxData.cyHScroll;

  if (dwStyle & WS_BORDER)

  nAdjust -= CY_BORDER;

  lpClientRect->bottom += nAdjust;

  }

  return;

  }

  // 无需为滚动条增加尺寸,调用基类成员完成计算

  CWnd::CalcWindowRect(lpClientRect, nAdjustType);

  }

虚函数PostNcDestroy

  在视图窗口关闭时最后调用的成员函数,它与CFrameWnd::PostNcDestroy完成相同的功能,即删除视图对象。代码如下:

  void CView::PostNcDestroy()

  {

  delete this;

  }

  这样,可以不必关心视图的释放工作,即使它在堆中构造。

虚函数OnCmdMsg

  在讨论CFrameWnd::OnCmdMsg()时已经了解过该函数,下面只给出它的代码:

  BOOL CView::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)

  {

  // 首先查找自身的命令消息映射

  if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))

  return TRUE;

  // 如果视图本身没有处理该命令,将机会留给与其关联的文档对象

  if (m_pDocument != NULL)

  {

  CPushRoutingView push(this);

  return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);

  }

  return FALSE;

  }

虚函数 OnActivateView

  当视图被激活为活动视图,或由活动转为非活动时,调用该函数通知视图。基类的实现只是设置该视图为焦点。代码如下:

  void CView::OnActivateView(BOOL bActivate, CView* pActivateView, CView*)

  {

  UNUSED(pActivateView); // unused in release builds

  if (bActivate) // 当前状态为活动吗

  {

  ASSERT(pActivateView == this);

  // 如果其父窗口也是活动的,则设置焦点。(在MDI中,其父框架可能是非活动的)

  if (IsTopParentActive())

  SetFocus();

  }

  }

MFC中丰富的CView派生类

  MFC提供了丰富的CView派生类,各种不同的派生类实现了对不同种类控件的支持,以为用户提供多元化的显示界面。

  CScrollView: 提供滚动支持;

  CCtrlView: 支持treelistrich edit控件;

  CDaoRecordView: dialog-box控件中显示数据库记录;

  CEditView: 提供了一个简单的多行文本编辑器视图;

  CFormView: 包含dialog-box控件,可滚动,基于对话框模板资源;

  CListView: 支持列表控件视图;

  CRecordView: dialog-box控件中显示数据库记录;

  CRichEditView: 支持富文本编辑的控件视图;

   CTreeView: 支持重点在树控件的文档 /视图结构的视图。

这篇关于MFC 视图类(CView)介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073281

相关文章

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

zookeeper端口说明及介绍

《zookeeper端口说明及介绍》:本文主要介绍zookeeper端口说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、zookeeper有三个端口(可以修改)aVNMqvZ二、3个端口的作用三、部署时注意总China编程结一、zookeeper有三个端口(可以

Python中win32包的安装及常见用途介绍

《Python中win32包的安装及常见用途介绍》在Windows环境下,PythonWin32模块通常随Python安装包一起安装,:本文主要介绍Python中win32包的安装及常见用途的相关... 目录前言主要组件安装方法常见用途1. 操作Windows注册表2. 操作Windows服务3. 窗口操作

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)

《MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)》掌握多表联查(INNERJOIN,LEFTJOIN,RIGHTJOIN,FULLJOIN)和子查询(标量、列、行、表子查询、相关/非相关、... 目录第一部分:多表联查 (JOIN Operations)1. 连接的类型 (JOIN Types)