深入浅出MFC文档/视图架构之文档模板(1)

来源:互联网 发布:mac os官方壁纸 编辑:程序博客网 时间:2024/05/17 23:05
 
 文档模板管理者类CDocManager

  在"文档/视图"架构的MFC程序中,提供了文档模板管理者类CDocManager,由它管理应用程序所包含的文档模板。我们先看看这个类的声明:

/////////////////////////////////////////////////////////////////////////////
// CDocTemplate manager object
class CDocManager : public CObject
{
 DECLARE_DYNAMIC(CDocManager)
 public:

  // Constructor
  CDocManager();

  //Document functions
  virtual void AddDocTemplate(CDocTemplate* pTemplate);
  virtual POSITION GetFirstDocTemplatePosition() const;
  virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const;
  virtual void ReGISterShellFileTypes(BOOL bCompat);
  void UnregisterShellFileTypes();
  virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); // open named file
  virtual BOOL SaveAllModified(); // save before exit
  virtual void CloseAllDocuments(BOOL bEndSession); // close documents before exiting
  virtual int GetOpenDocumentCount();

  // helper for standard commdlg dialogs
  virtual BOOL DoPromptFileName(CString& fileName, UINT nIDSTitle,
  DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate);

  //Commands
  // Advanced: process async DDE request
  virtual BOOL OnDDECommand(LPTSTR lpszCommand);
  virtual void OnFileNew();
  virtual void OnFileOpen();

  // Implementation
 protected:
  CPtrList m_templateList;
  int GetDocumentCount(); // helper to count number of total documents

 public:
  static CPtrList* pStaticList; // for static CDocTemplate objects
  static BOOL bStaticInit; // TRUE during static initialization
  static CDocManager* pStaticDocManager; // for static CDocTemplate objects

 public:
  virtual ~CDocManager();
  #ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
  #endif
};

  从上述代码可以看出,CDocManager类维护一个CPtrList类型的链表m_templateList(即文档模板链表,实际上,MFC的设计者在MFC的实现中大量使用了链表这种数据结构),CPtrList类型定义为:

class CPtrList : public CObject
{
 DECLARE_DYNAMIC(CPtrList)

 protected:
  struct CNode
  {
   CNode* pNext;
   CNode* pPrev;
   void* data;
  };
 public:

  // Construction
  CPtrList(int nBlockSize = 10);

  // Attributes (head and tail)
  // count of elements
  int GetCount() const;
  BOOL IsEmpty() const;

  // peek at head or tail
  void*& GetHead();
  void* GetHead() const;
  void*& GetTail();
  void* GetTail() const;

  // Operations
  // get head or tail (and remove it) - don't call on empty list!
  void* RemoveHead();
  void* RemoveTail();

  // add before head or after tail
  POSITION AddHead(void* newElement);
  POSITION AddTail(void* newElement);

  // add another list of elements before head or after tail
  void AddHead(CPtrList* pNewList);
  void AddTail(CPtrList* pNewList);

  // remove all elements
  void RemoveAll();

  // iteration
  POSITION GetHeadPosition() const;
  POSITION GetTailPosition() const;
  void*& GetNext(POSITION& rPosition); // return *Position++
  void* GetNext(POSITION& rPosition) const; // return *Position++
  void*& GetPrev(POSITION& rPosition); // return *Position--
  void* GetPrev(POSITION& rPosition) const; // return *Position--

  // getting/modifying an element at a given position
  void*& GetAt(POSITION position);
  void* GetAt(POSITION position) const;
  void SetAt(POSITION pos, void* newElement);

  void RemoveAt(POSITION position);

  // inserting before or after a given position
  POSITION InsertBefore(POSITION position, void* newElement);
  POSITION InsertAfter(POSITION position, void* newElement);

  // helper functions (note: O(n) speed)
  POSITION Find(void* searchValue, POSITION startAfter = NULL) const;
  // defaults to starting at the HEAD
  // return NULL if not found
  POSITION FindIndex(int nIndex) const;
  // get the 'nIndex'th element (may return NULL)

  // Implementation
 protected:
  CNode* m_pNodeHead;
  CNode* m_pNodeTail;
  int m_nCount;
  CNode* m_pNodeFree;
  struct CPlex* m_PBlocks;
  int m_nBlockSize;

  CNode* NewNode(CNode*, CNode*);
  void FreeNode(CNode*);

 public:
  ~CPtrList();
  #ifdef _DEBUG
   void Dump(CDumpContext&) const;
   void AssertValid() const;
  #endif
  // local typedefs for class templates
  typedef void* BASE_TYPE;
  typedef void* BASE_ARG_TYPE;
};
很显然,CPtrList是对链表结构体
struct CNode
{
 CNode* pNext;
 CNode* pPrev;
 void* data;
};

  本身及其GetNext、GetPrev、GetAt、SetAt、RemoveAt、InsertBefore、InsertAfter、Find、FindIndex等各种操作的封装。

  作为一个抽象的链表类型,CPtrList并未定义其中节点的具体类型,而以一个void指针(struct CNode 中的void* data)巧妙地实现了链表节点成员具体类型的"模板"化。很显然,在Visual C++6.0开发的年代,C++语言所具有的语法特征"模板"仍然没有得到广泛的应用。
而CDocManager类的成员函数

virtual void AddDocTemplate(CDocTemplate* pTemplate);
virtual POSITION GetFirstDocTemplatePosition() const;
virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const;

  则完成对m_TemplateList链表的添加及遍历操作的封装,我们来看看这三个函数的源代码:

void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)
{
 if (pTemplate == NULL)
 {
  if (pStaticList != NULL)
  {
   POSITION pos = pStaticList->GetHeadPosition();
   while (pos != NULL)
   {
    CDocTemplate* pTemplate = (CDocTemplate*)pStaticList->GetNext(pos);
    AddDocTemplate(pTemplate);
   }
   delete pStaticList;
   pStaticList = NULL;
  }
  bStaticInit = FALSE;
 }
 else
 {
  ASSERT_VALID(pTemplate);
  ASSERT(m_templateList.Find(pTemplate, NULL) == NULL);// must not be in list
  pTemplate->LoadTemplate();
  m_templateList.AddTail(pTemplate);
 }
}
POSITION CDocManager::GetFirstDocTemplatePosition() const
{
 return m_templateList.GetHeadPosition();
}
CDocTemplate* CDocManager::GetNextDocTemplate(POSITION& pos) const
{
 return (CDocTemplate*)m_templateList.GetNext(pos);
原创粉丝点击