///////////////////////////////////////////////////////////////////////////// // 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 }; |
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是對鏈表結(jié)構(gòu)體 struct CNode { CNode* pNext; CNode* pPrev; void* data; }; |
virtual void AddDocTemplate(CDocTemplate* pTemplate); virtual POSITION GetFirstDocTemplatePosition() const; virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const; |
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); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
///////////////////////////////////////////////////////////////////////////// // class CDocument is the main document data abstraction class CDocument : public CCmdTarget { DECLARE_DYNAMIC(CDocument) public: // Constructors CDocument(); // Attributes public: const CString& GetTitle() const; virtual void SetTitle(LPCTSTR lpszTitle); const CString& GetPathName() const; virtual void SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU = TRUE); CDocTemplate* GetDocTemplate() const; virtual BOOL IsModified(); virtual void SetModifiedFlag(BOOL bModified = TRUE); // Operations void AddView(CView* pView); void RemoveView(CView* pView); virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION& rPosition) const; // Update Views (simple update - DAG only) void UpdateAllViews(CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL); // Overridables // Special notifications virtual void OnChangedViewList(); // after Add or Remove view virtual void DeleteContents(); // delete doc items etc // File helpers virtual BOOL OnNewDocument(); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); virtual void OnCloseDocument(); virtual void ReportSaveLoadException(LPCTSTR lpszPathName, CException* e, BOOL bSaving, UINT nIDPDefault); virtual CFile* GetFile(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError); virtual void ReleaseFile(CFile* pFile, BOOL bAbort); // advanced overridables, closing down frame/doc, etc. virtual BOOL CanCloseFrame(CFrameWnd* pFrame); virtual BOOL SaveModified(); // return TRUE if ok to continue virtual void PreCloseFrame(CFrameWnd* pFrame); // Implementation protected: // default implementation CString m_strTitle; CString m_strPathName; CDocTemplate* m_pDocTemplate; CPtrList m_viewList; // list of views BOOL m_bModified; // changed since last saved public: BOOL m_bAutoDelete; // TRUE => delete document when no more views BOOL m_bEmbedded; // TRUE => document is being created by OLE #ifdef _DEBUG virtual void Dump(CDumpContext&) const; virtual void AssertValid() const; #endif //_DEBUG virtual ~CDocument(); // implementation helpers virtual BOOL DoSave(LPCTSTR lpszPathName, BOOL bReplace = TRUE); virtual BOOL DoFileSave(); virtual void UpdateFrameCounts(); void DisconnectViews(); void SendInitialUpdate(); // overridables for implementation virtual HMENU GetDefaultMenu(); // get menu depending on state virtual HACCEL GetDefaultAccelerator(); virtual void OnIdle(); virtual void OnFinalRelease(); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo); friend class CDocTemplate; protected: // file menu commands //{{AFX_MSG(CDocument) afx_msg void OnFileClose(); afx_msg void OnFileSave(); afx_msg void OnFileSaveAs(); //}}AFX_MSG // mail enabling afx_msg void OnFileSendMail(); afx_msg void OnUpdateFileSendMail(CCmdUI* pCmdUI); DECLARE_MESSAGE_MAP() }; |
void CDocument::AddView(CView* pView) { ASSERT_VALID(pView); ASSERT(pView->m_pDocument == NULL); // must not be already attached ASSERT(m_viewList.Find(pView, NULL) == NULL); // must not be in list m_viewList.AddTail(pView); ASSERT(pView->m_pDocument == NULL); // must be un-attached pView->m_pDocument = this; OnChangedViewList(); // must be the last thing done to the document } |
void CDocument::RemoveView(CView* pView) { ASSERT_VALID(pView); ASSERT(pView->m_pDocument == this); // must be attached to us m_viewList.RemoveAt(m_viewList.Find(pView)); pView->m_pDocument = NULL; OnChangedViewList(); // must be the last thing done to the document } |
void CDocument::OnChangedViewList() { // if no more views on the document, delete ourself // not called if directly closing the document or terminating the app if (m_viewList.IsEmpty() && m_bAutoDelete) { OnCloseDocument(); return; } // update the frame counts as needed UpdateFrameCounts(); } |
void CDocument::DisconnectViews() { while (!m_viewList.IsEmpty()) { CView* pView = (CView*)m_viewList.RemoveHead(); ASSERT_VALID(pView); ASSERT_KINDOF(CView, pView); pView->m_pDocument = NULL; } } |
POSITION CDocument::GetFirstViewPosition() const { return m_viewList.GetHeadPosition(); } CView* CDocument::GetNextView(POSITION& rPosition) const { ASSERT(rPosition != BEFORE_START_POSITION); // use CDocument::GetFirstViewPosition instead ! if (rPosition == NULL) return NULL; // nothing left CView* pView = (CView*)m_viewList.GetNext(rPosition); ASSERT_KINDOF(CView, pView); return pView; } |
CFile* CDocument::GetFile(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError) { CMirrorFile* pFile = new CMirrorFile; ASSERT(pFile != NULL); if (!pFile->Open(lpszFileName, nOpenFlags, pError)) { delete pFile; pFile = NULL; } return pFile; } void CDocument::ReleaseFile(CFile* pFile, BOOL bAbort) { ASSERT_KINDOF(CFile, pFile); if (bAbort) pFile->Abort(); // will not throw an exception else pFile->Close(); delete pFile; } |
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName) { if (IsModified()) TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n"); CFileException fe; CFile* pFile = GetFile(lpszPathName, CFile::modeRead|CFile::shareDenyWrite, &fe); if (pFile == NULL) { ReportSaveLoadException(lpszPathName, &fe,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); return FALSE; } DeleteContents(); SetModifiedFlag(); // dirty during de-serialize CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete); loadArchive.m_pDocument = this; loadArchive.m_bForceFlat = FALSE; TRY { CWaitCursor wait; if (pFile->GetLength() != 0) Serialize(loadArchive); // load me loadArchive.Close(); ReleaseFile(pFile, FALSE); } CATCH_ALL(e) { ReleaseFile(pFile, TRUE); DeleteContents(); // remove failed contents TRY { ReportSaveLoadException(lpszPathName, e,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); } END_TRY DELETE_EXCEPTION(e); return FALSE; } END_CATCH_ALL SetModifiedFlag(FALSE); // start off with unmodified return TRUE; } ///////////////////////////////////////////////////////////////////////////////////// |
class CView : public CWnd { DECLARE_DYNAMIC(CView) // Constructors protected: CView(); // Attributes public: CDocument* GetDocument() const; // Operations public: // for standard printing setup (override OnPreparePrinting) BOOL DoPreparePrinting(CPrintInfo* pInfo); // Overridables public: virtual BOOL IsSelected(const CObject* pDocItem) const; // support for OLE // OLE scrolling support (used for drag/drop as well) virtual BOOL OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll = TRUE); virtual BOOL OnScrollBy(CSize sizeScroll, BOOL bDoScroll = TRUE); // OLE drag/drop support virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject,DWORD dwKeyState, CPoint point); virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject,DWORD dwKeyState, CPoint point); virtual void OnDragLeave(); virtual BOOL OnDrop(COleDataObject* pDataObject,DROPEFFECT dropEffect, CPoint point); virtual DROPEFFECT OnDropEx(COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point); virtual DROPEFFECT OnDragScroll(DWORD dwKeyState, CPoint point); virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL); virtual void OnInitialUpdate(); // called first time after construct protected: // Activation virtual void OnActivateView(BOOL bActivate, CView* pActivateView,CView* pDeactiveView); virtual void OnActivateFrame(UINT nState, CFrameWnd* pFrameWnd); // General drawing/updating virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); virtual void OnDraw(CDC* pDC) = 0; // Printing support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); // must override to enable printing and print preview virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); // Advanced: end print preview mode, move to point virtual void OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point,CPreviewView* pView); // Implementation public: virtual ~CView(); #ifdef _DEBUG virtual void Dump(CDumpContext&) const; virtual void AssertValid() const; #endif //_DEBUG // Advanced: for implementing custom print preview BOOL DoPrintPreview(UINT nIDResource, CView* pPrintView,CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState); virtual void CalcWindowRect(LPRECT lpClientRect,UINT nAdjustType = adjustBorder); virtual CScrollBar* GetScrollBarCtrl(int nBar) const; static CSplitterWnd* PASCAL GetParentSplitter(const CWnd* pWnd, BOOL bAnyState); protected: CDocument* m_pDocument; public: virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo); protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual void PostNcDestroy(); // friend classes that call protected CView overridables friend class CDocument; friend class CDocTemplate; friend class CPreviewView; friend class CFrameWnd; friend class CMDIFrameWnd; friend class CMDIChildWnd; friend class CSplitterWnd; friend class COleServerDoc; friend class CDocObjectServer; //{{AFX_MSG(CView) afx_msg int OnCreate(LPCREATESTRUCT lpcs); afx_msg void OnDestroy(); afx_msg void OnPaint(); afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message); // commands afx_msg void OnUpdateSplitCmd(CCmdUI* pCmdUI); afx_msg BOOL OnSplitCmd(UINT nID); afx_msg void OnUpdateNextPaneMenu(CCmdUI* pCmdUI); afx_msg BOOL OnNextPaneCmd(UINT nID); // not mapped commands - must be mapped in derived class afx_msg void OnFilePrint(); afx_msg void OnFilePrintPreview(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; |
CView::~CView() { if (m_pDocument != NULL) m_pDocument->RemoveView(this); } |
///////////////////////////////////////////////////////////////////////////// // CExampleView drawing void CExampleView::OnDraw(CDC* pDC) { CExampleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } CView::PreCreateWindow負責(zé)View的初始化: ///////////////////////////////////////////////////////////////////////////// // CView second phase construction - bind to document BOOL CView::PreCreateWindow(CREATESTRUCT & cs) { ASSERT(cs.style & WS_CHILD); if (cs.lpszClass == NULL) { VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background } if (afxData.bWin4 && (cs.style & WS_BORDER)) { cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; } return TRUE; } |
void CView::OnUpdate(CView* pSender, LPARAM /*lHint*/, CObject* /*pHint*/) { ASSERT(pSender != this); UNUSED(pSender); // unused in release builds // invalidate the entire pane, erase background too Invalidate(TRUE); } |
![]() ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
![]() 圖5.1 在AppWizard中選擇框架窗口 |
![]() 圖5.2 CFrameWnd、CMDIFrameWnd、CMDIChildWnd類的層次 |
BOOL CFrameWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, LPCTSTR lpszMenuName, DWORD dwExStyle, CCreateContext *pContext) { HMENU hMenu = NULL; if (lpszMenuName != NULL) { // load in a menu that will get destroyed when window gets destroyed HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU); if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL) { TRACE0("Warning: failed to load menu for CFrameWnd.\n"); PostNcDestroy(); // perhaps delete the C++ object return FALSE; } } m_strTitle = lpszWindowName; // save title for later if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd ->GetSafeHwnd(), hMenu, (LPVOID)pContext)) { TRACE0("Warning: failed to create CFrameWnd.\n"); if (hMenu != NULL) DestroyMenu(hMenu); return FALSE; } return TRUE; } |
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd *pParentWnd, CCreateContext *pContext) { // only do this once ASSERT_VALID_IDR(nIDResource); ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource); m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE) CString strFullString; if (strFullString.LoadString(nIDResource)) AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); // attempt to create the window LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource); LPCTSTR lpszTitle = m_strTitle; if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext)) { return FALSE; // will self destruct on failure normally } // save the default menu handle ASSERT(m_hWnd != NULL); m_hMenuDefault = ::GetMenu(m_hWnd); // load accelerator resource LoadAccelTable(MAKEINTRESOURCE(nIDResource)); if (pContext == NULL) // send initial update SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); return TRUE; } |
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT &cs) { if (cs.lpszClass == NULL) { VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background } if ((cs.style &FWS_ADDTOTITLE) && afxData.bWin4)cs.style |= FWS_PREFIXTITLE; if (afxData.bWin4) cs.dwExStyle |= WS_EX_CLIENTEDGE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////// |
從該對象 | 如何訪問其他對象 |
全局函數(shù) | 調(diào)用全局函數(shù)AfxGetApp可以得到CWinApp應(yīng)用類指針 |
應(yīng)用 | AfxGetApp()->m_pMainWnd為框架窗口指針;用CWinApp::GetFirstDocTemplatePostion、CWinApp::GetNextDocTemplate來遍歷所有文檔模板 |
文檔 | 調(diào)用CDocument::GetFirstViewPosition,CDocument::GetNextView來遍歷所有和文檔關(guān)聯(lián)的視圖;調(diào)用CDocument:: GetDocTemplate 獲取文檔模板指針 |
文檔模板 | 調(diào)用CDocTemplate::GetFirstDocPosition、CDocTemplate::GetNextDoc來遍歷所有對應(yīng)文檔 |
視圖 | 調(diào)用CView::GetDocument 得到對應(yīng)的文檔指針; 調(diào)用CView::GetParentFrame 獲取框架窗口 |
文檔框架窗口 | 調(diào)用CFrameWnd::GetActiveView 獲取當(dāng)前得到當(dāng)前活動視圖指針; 調(diào)用CFrameWnd::GetActiveDocument 獲取附加到當(dāng)前視圖的文檔指針 |
MDI 框架窗口 | 調(diào)用CMDIFrameWnd::MDIGetActive 獲取當(dāng)前活動的MDI子窗口(CMDIChildWnd) |
CMyApp *pMyApp = (CMyApp*)AfxGetApp(); //得到應(yīng)用程序指針 POSITION p = pMyApp->GetFirstDocTemplatePosition();//得到第1個文檔模板 while (p != NULL) //遍歷文檔模板 { CDocTemplate *pDocTemplate = pMyApp->GetNextDocTemplate(p); POSITION p1 = pDocTemplate->GetFirstDocPosition();//得到文檔模板對應(yīng)的第1個文檔 while (p1 != NULL) //遍歷文檔模板對應(yīng)的文檔 { CDocument *pDocument = pDocTemplate->GetNextDoc(p1); POSITION p2 = pDocument->GetFirstViewPosition(); //得到文檔對應(yīng)的第1個視圖 while (p2 != NULL) //遍歷文檔對應(yīng)的視圖 { CView *pView = pDocument->GetNextView(p2); } } } |
![]() 圖6.1 多文檔/視圖框架MFC程序的組成 |
![]() 圖6.2 文檔/視圖框架程序類的層次關(guān)系 |
![]() 圖6.3文檔/視圖的三種關(guān)系 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
![]() 圖7.1 最初的Example工程界面 |
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by EXAMPLE.RC // #define IDD_ABOUTBOX 100 #define IDR_MAINFRAME 128 //#define IDR_EXAMPLTYPE 129 #define IDR_TEXTTYPE 10001 #define IDR_BMPTYPE 10002 … #endif STRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_MAINFRAME "Example" IDR_EXAMPLTYPE "\nExampl\nExampl\n\n\nExample.Document\nExampl Document" IDR_TEXTTYPE "\nTEXT\nTEXT\nExampl 文件 (*.txt)\n.txt\nTEXT\nTEXT Document" IDR_BMPTYPE "\nBMP\nBMP\nExampl 文件 (*.bmp)\n.bmp\nBMP\nBMP Document" END |
BOOL CExampleApp::InitInstance() { … CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TEXTTYPE, //對應(yīng)文本文件的字符串 RUNTIME_CLASS(CExampleDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CExampleView)); AddDocTemplate(pDocTemplate); … } |
class CExampleDoc : public CDocument { … CString m_Text; //在文檔類中定義成員變量用于存儲TXT文件中的字符串 … } //重載文檔類的Serialize,讀取字符串到m_Text中 void CExampleDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here ar.ReadString(m_Text); } } //重載視圖類的OnDraw函數(shù),顯示文檔中的字符串 ///////////////////////////////////////////////////////////////////////////// // CExampleView drawing void CExampleView::OnDraw(CDC* pDC) { CExampleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->TextOut(0,0,pDoc->m_Text); } |
![]() 圖7.2 打開TXT文件的界面 |