17.3.1 记录文档修改(1)

2013-10-07 16:13:15 · 作者: · 浏览: 68

17.3  应用序列化

要在Sketcher应用程序中实现序列化,必须在CSketcherDoc类中实现Serialize()函数,以便这个函数可以处理该类的所有数据成员。对于指定可能要包括在文档中的对象的每个类,都需要添加序列化。开始在应用程序类中添加序列化之前,应当对Sketcher程序做一些小的修改,以记录用户对草图文档所做的修改。虽然这并非完全必要,但是强烈建议这样做,因为这能够防止程序在没有保存修改的情况下关闭文档。

17.3.1  记录文档修改(1)

已经有一种机制用于记录文档的修改;它使用CSketcherDoc的一个继承成员SetModifiedFlag()。每次修改文档时都调用这个函数,可以把文档已被修改的事实记录在文档类对象的数据成员中。如果试图在没有保存已修改文档的情况下退出应用程序,就会自动显示一个提示消息。SetModifiedFlag()函数的参数是一个BOOL型的值,默认值是TRUE。如果偶尔要说明文档未被修改,那么可以用参数FALSE调用这个函数。

修改文档对象中草图的情况只有4种:

调用CSketcherDoc的成员AddElement()添加新元素。

调用CSketcherDoc的成员DeleteElement()删除元素。

调用文档对象的SendToBack()函数

移动元素。

这4种情况都容易处理。需要做的仅仅是针对这些操作中所涉及的每个函数添加对SetModified- Flag()的调用。AddElement()的定义出现在CSketcherDoc类定义中。可以把这个定义扩展为:

  1. void AddElement(std::shared_ptr<CElement>& pElement)        // Add an element to the list  
  2. {  
  3. m_Sketch.push_back(pElement);  
  4. UpdateAllViews(nullptr, 0, pElement.get());                             // Tell all the views  
  5. SetModifiedFlag();                                                                                                                  // Set the modified flag  
  6. }  

DeleteElement()函数的定义也在CSketcherDoc定义中。应当在这个定义中添加一行如下所示的代码:
 

  1. void DeleteElement(std::shared_ptr<CElement>& pElement)  
  2. {  
  3. m_Sketch.remove(pElement);  
  4. UpdateAllViews(nullptr, 0, pElement.get());                             // Tell all the views  
  5. SetModifiedFlag();                                                                                                                  // Set the modified flag  
  6. }  

SendToBack()函数也需要添加这行代码:
 

  1. void SendToBack(std::shared_ptr<CElement>& pElement)  
  2. {  
  3. if(pElement)  
  4. {  
  5. m_Sketch.remove(pElement);                                                              // Remove the element from the list  
  6. m_Sketch.push_back(pElement);                                                   // Put a copy at the end of the list  
  7. SetModifiedFlag();                                                                                      // Set the modified flag  
  8. }  
  9. }  

在视图对象中,移动元素的操作出现在由WM_MOUSEMOVE消息处理程序调用的MoveElement()成员中,但是只有在按下鼠标左按钮时才能修改文档。如果右击鼠标,那么元素将返回其原来的位置,所以只需要在OnLButtonDown()函数中添加对文档的SetModifiedFlag()函数的调用,如下所示:
 

  1. void CSketcherView::OnLButtonDown(UINT nFlags, CPoint point)  
  2. {  
  3. CClientDC aDC(this);                                                                                                                // Create a device context  
  4. OnPrepareDC(&aDC);                                                                                                                  // Get origin adjusted  
  5. aDC.DPtoLP(&point);                                                                                                             // convert point to Logical  
  6. CSketcherDoc* pDoc = GetDocument();                                                         // Get a document pointer  
  7. if(m_MoveMode)  
  8. { // In moving mode, so drop the element  
  9. m_MoveMode = false;                                                                                                         // Kill move mode  
  10. auto pElement(m_pSelected);                                                                             // Store selected address  
  11. m_pSelected = nullptr;                                                                                              // De-select the element  
  12. pDoc->UpdateAllViews(nullptr, 0, pElement.get());   // Redraw all the views  
  13. pDoc->SetModifiedFlag();                                                                                        // Set the modified flag  
  14. }  
  15. // Rest of the function as before...  
  16. }