四、视图类简介

1.   文档/视图模式简介:

       a. 该模式的宗旨就是将数据操作和数据呈现在物理和逻辑上实现分离;

       b. 文档只负责数据的存储和操作,而视图则负责将文档中的数据以图形化的形式显示给用户看,比如对话框、列表、各种框等等,显示的形式可以是多种多样的;

       c. 文档/视图的对应关系:

            i.   文档是视图的材料和基础;

            ii.  因此文档对视图是一种一对多的关系;

            iii. 即一个文档可以对应多个视图对象,而一个视图对象只能对应一个文档对象;

        d. 视图类的三大用途:

            i.   将数据从文档中取出,并且通过各种各样的形式呈现给用户;

            ii.  为用户对数据的修改等提供一个图形界面,用户可在这些界面上描述对数据的操作;

            iii. 视图再将这些界面上用户对数据的操作回馈给对应的文档类对象,在存储介质上对数据的真正的操作还是交由文档类对象执行;


2.   CView类简介:

       a. 即视图类,是创建的工程中CTestView类的基类;

       b. WM_PAINT消息:

            i.   是Windows窗口的一种重要消息,该消息可触发对窗口进行重画的操作;

            ii.  向指定窗口发送WM_PAINT消息的时机:

                  *1. 第一次创建(即打开)窗口时;

                  *2. 窗口大小发生改变时,比如最大化、最小化窗口、利用下拉箭头等的拖动改变窗口大小比例;

                  *3. 把目标窗口从另一个窗口背后移出来时;

            iii. 产生WM_PAINT消息的方法:

                  *1. 使用Invalide函数:该函数的作用就是告诉窗口,你里面的内容已经无效了,需要重新绘制,比如一个窗口被前台窗口遮住了,那么遮住部分将无效,因此当用户将该窗口移出时,系统就会调用该函数以发送WM_PAINT消息,触发重绘操作;

                  *2. 使用UpdateWindow函数:就是直接提示目标窗口,让其立即重绘,说到底作用和Invalide函数一模一样,只不过对他们取不同的名字可以在逻辑上更加清晰而已,而其唯一的区别就是Invalide函数是需要排队的,而UpdateWindow函数可以直接插队,说得明白点就是在同一时间段中,不仅仅只会产生WM_PAINT一种消息,很有可能产生多种消息,但是WM_PAINT消息是所有消息中优先级最低的,Invalide函数是将WM_PAINT消息插在消息队列的尾部,而UpdateWindow则是直接将WM_PAINT消息直接插在消息队列的头部,可以使得窗口立即实施重绘操作;

                   *3. 使用UpdateAll函数:调用该函数可以向一个文档的所有视图对象发送WM_PAINT消息,而上面的两个函数都只能向一个窗口发送WM_PAINT消息,该函数一般是在文档数据发生大规模改变时会被调用;

        c. 实施重绘:

             i.    即相应WM_PAINT消息;

             ii.   通过OnPaint函数相应:

CView::OnPaint(void)
{
	CPaintDC dc(this);//创建一个显示(即画图)设备对象与具体的画图设备关联
	OnPrepareDC(&dc);//对该设备对象初始化(即准备)
	OnDraw(&dc);//使用OnDraw函数,利用相应的显示设备显示(画出)图像
}
             iii. 可以看出OnPaint函数只是OnDraw函数的设配器,并且为OnDraw函数准备画画的工具(作用就和画笔一样,只不过这里的是某台具体的显示设备在程序中的一种抽象,被抽象成了一种对象,就像所有硬件设备在操作系统中都被抽象成了文件一样);

             iv. 因此真正的重绘工作需要交给OnDraw函数实施,一下是一个例子:

                  *1. 先在Doc类中创建一个成员变量m_showStr,然后在OnDraw函数中显示文档中的该数据,添加方法是在类视图中的Doc类上右键,点击“添加成员变量”,然后在对话框中输入名字和类型即可;

                  *2. 一下是Serialize和OnDraw函数的实现:

void CTestDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
		int i;
		char ch;
		double f;
		CString str;

		ar >> i >> ch >> f >> str;
		m_showStr.Format("%d, %c, %f, %s", i, ch, f, str);
	}
}

void CTestView::OnDraw(CDC* pDC)//CDC就是显示设备抽象成的类,pDC就是该显示设备对象的指针
{
	CTestDoc* pDoc = GetDocument();//由于要绘的数据存在Doc文档中,因此要先获得文档对象的指针才能调出其中的数据
	                               //这里要获得的数据就是m_showStr,即pDoc->m_showStr
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	pDC->TextOut(200, 200, pDoc->m_showStr);//使用绘图设备对象的TextOut函数,将字符串显示在屏幕的(200,200)坐标处
}
                *3. 调试时点击打开按钮打开上一节中创建的文件,即可在绘图区的相应位置显示出这些信息了;

3.   总结在给类中获得其它类指针的方法:

       a. 视图类中获得文档类的方法:GetDocument();

       b. 文档类中获得视图类中的方法:

            i.   由于一个文档可以对应多个视图,因此在文档中获得视图指针将会是多个;

            ii.  先用GetFirstViewPosition()获得第一个视图的指针,当然该函数返回的是视图类对象的POSITION;

            iii. 再使用while循环,并在循环判断中调用GetNextView函数,其原型为:CView *GetNextView( POSITION &rPosition )

                 传入当前视图的POSITION然后返回当前视图的指针,同时将实参输出为下一张视图的POSITION,如果下一张视图不存在(即视图已经遍历完毕),将返回NULL;

            注:如果文档中的数据发生变化,则需要调用Doc类的成员函数UpdateAllViews函数通知各个视图更新其中的数据以和文档数据适配,当然在UpdateAllViews函数作用与各个视图后,各个视图将会调用格子相应的函数根据文档中的数据进行更新;

        c. 框架类中获得当前处于激活状态(以后简称为当前的)视图所对应的文档的指针:

             i.   CMainFrame类派生于CFrameWnd类,其继承了里面的虚函数GetActiveDocument();

             ii.  通过该函数可以获取当前视图所对应的文档的指针,返回类型是CDocument *;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值