14.5 绘制草图
构成草图的所有元素都安全地存储在文档对象中。现在需要一种方式在视图中显示草图。CSketcherView中的OnDraw()函数可以完成这个任务。显然,它需要访问文档对象拥有的草图数据,理想情况下,它访问这些数据时,文档对象不需要把这些数据提供给外界,以进行修改。为此,一种方式是文档对象使用const迭代器。草图的迭代器类型名称有点长,在#include指令的后面给SketcherDoc.h添加如下类型定义,可以减少输入工作:
- typedef std::list<std::shared_ptr<CElement>>::const_iterator SketchIterator;
现在可以在代码中使用SketchIterator为草图列表容器指定const迭代器的类型了。在CSketcherDoc类定义中添加如下函数,就可以让视图对象获得绘制草图所需的迭代器:
- // Provide a begin iterator for the sketch
- SketchIterator begin() const { return std::begin(m_Sketch); }
- // Provide an end iterator for the sketch
- SketchIterator end() const { return std::end(m_Sketch); }
这些迭代器应是public,可以把它们放在CSketcherDoc的Operations部分。const迭代器可以递增,也可以解除引用,但不能用于修改它指向的内容。使用这些函数可以实现CSketcherView的OnDraw()成员:
- void CSketcherView::OnDraw(CDC* pDC)
- {
- CSketcherDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (!pDoc)
- return;
- // Draw the sketch
- for(auto iter = pDoc->begin() ; iter != pDoc->end() ; ++iter)
- {
- std::shared_ptr<CElement> pElement(*iter);
- if(pDC->RectVisible(pElement->GetEnclosingRect())) // Element visible
- pElement->Draw(pDC); // Yes, draw it.
- }
- }
文档对象的begin()成员所返回的迭代器指向一个列表元素,它是指向草图元素的智能指针。必须解除迭代器的引用,存储得到的智能指针,才能调用元素对象的函数。我们只希望元素在视图的工作区中可见时绘制它。绘制在视图中不可见的元素只会浪费处理器的时间。如果传递为参数的矩形的任意部分在工作区中,CDC对象的RectVisible()成员就返回True,否则返回False。在if语句中调用这个函数,可确保只绘制可见的元素。把指向设备上下文的指针作为参数调用Draw()成员,就绘制了一个草图元素。