Microsoft Foundation Classes

O modelo de Model/View/Controller nas MFC´s

CCISEL 2001

Advanced MFC

1 de 20

Application Framework

Document template Model: Os dados - providenciam uma interface para consultas e alterações View: Uma forma de visualizar os dados Controller: Interface com o utilizador sobre uma View

Frame O modelo SDI (Single Document Interface) View Document

CCISEL 2001

Advanced MFC

2 de 20

Uma aplicação MDI simples (scribble)

CCISEL 2001

Advanced MFC

3 de 20

A aplicação Scribble
#include "resource.h" class CScribbleApp : public CWinApp { public: virtual BOOL InitInstance(); afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() }; CScribbleApp theApp; BOOL CScribbleApp::InitInstance() { // Register the application's document templates. CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_SCRIBBTYPE, RUNTIME_CLASS(CScribbleDoc), // custom MDI child frame RUNTIME_CLASS(CChildFrame), // custom MDI view RUNTIME_CLASS(CScribbleView)); AddDocTemplate(pDocTemplate); // create main MDI Frame window CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; OnFileNew(); // Abrir uma frame filha inicial pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE;

#include #include #include #include #include #include

"stdafx.h" "Scribble.h" "MainFrm.h" "ChildFrm.h" "ScribDoc.h" "ScribVw.h"

BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) } END_MESSAGE_MAP()

CCISEL 2001

Advanced MFC

4 de 20

Especialização de vector da biblioteca STL com serialização MFC

template <class T> class MFCVector : public std::vector<T> { public: void Serialize(CArchive &ar) { int vSize; if (ar.IsStoring()) { vSize = size(); ar << vSize; for (iterator it = begin(); it != end(); ++it) ar << *it; } else { clear(); ar >> vSize; reserve(vSize*2); for (int i= 0; i < vSize; ++i) { T val; ar >> val; push_back(val); } } } };

CCISEL 2001

Advanced MFC

5 de 20

A classe documento (CScribbleDoc)
class CScribbleDoc : public CDocument { // construção virtual DECLARE_DYNCREATE(CScribbleDoc) private: UINT m_nPenWidth; // current user-selected pen width CPen m_penCur; // pen created according // user-selected pen style (width) MFCVector <CStroke *> m_strokeList; public: CStroke* NewStroke(); typedef MFCVector<CStroke*>::iterator StrokeIterator; StrokeIterator beginIterator() { return m_strokeList.begin(); } StrokeIterator endIterator() { return m_strokeList.end(); } CPen* GetCurrentPen() { return &m_penCur; } virtual BOOL OnNewDocument(); virtual void Serialize(CArchive& ar); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual void DeleteContents(); protected: void InitDocument(); };

class CStroke : public CObject { protected: CStroke(); DECLARE_SERIAL(CStroke) protected: UINT m_nPenWidth;

// one pen width applies to entire // stroke MFCVector <CPointt> m_pointArray; // series of points

public: CStroke(UINT nPenWidth); BOOL DrawStroke(CDC* pDC); void add(CPoint &point) { m_pointArray.push_back(point); } virtual void Serialize(CArchive& ar); };

CCISEL 2001

Advanced MFC

6 de 20

A classe CStroke (implementação)
IMPLEMENT_SERIAL(CStroke, CObject, 1) CStroke::CStroke(UINT nPenWidth) { m_nPenWidth = nPenWidth; } void CStroke::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << (WORD) m_nPenWidth; m_pointArray.Serialize(ar); } else { WORD w; ar >> w; m_nPenWidth = w; m_pointArray.Serialize(ar); } } BOOL CStroke::DrawStroke(CDC* pDC) { CPen penStroke; if (!penStroke.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0))) return FALSE; CPen* pOldPen = pDC->SelectObject(&penStroke); pDC->MoveTo(m_pointArray[0]); for (int i=1; i < m_pointArray.GetSize(); i++) { pDC->LineTo(m_pointArray[i]); } pDC->SelectObject(pOldPen); return TRUE; }

CCISEL 2001

Advanced MFC

7 de 20

A classe CScribbleDoc (implementação)
#include "stdafx.h" #include "Scribble.h" #include "ScribDoc.h" IMPLEMENT_DYNCREATE(CScribbleDoc, CDocument) BOOL CScribbleDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; InitDocument(); return TRUE; }

void CScribbleDoc::InitDocument() { m_nPenWidth = 6; // default 2 pixel pen width, solid, black pen m_penCur.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0)); void CScribbleDoc::Serialize(CArchive& ar) { m_strokeList.Serialize(ar); } }

BOOL CScribbleDoc::OnOpenDocument(LPCTSTR lpszPathName) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; InitDocument(); return TRUE; CStroke* CScribbleDoc::NewStroke() { } CStroke* pStrokeItem = new CStroke(m_nPenWidth); m_strokeList.push_back(pStrokeItem); void CScribbleDoc::DeleteContents() { SetModifiedFlag(); while (!m_strokeList.empty()) { // Mark the document as having been modified, for CStroke *stroke = m_strokeList.front(); // purposes of confirming File Close. m_strokeList.pop_front(); return pStrokeItem; delete stroke; } } CDocument::DeleteContents(); }

CCISEL 2001

Advanced MFC

8 de 20

A classe que representa as frames filhas (CChildFrame)

class CChildFrame : public CMDIChildWnd { DECLARE_DYNCREATE(CChildFrame) };

#include "stda x.h" #include "Scribble.h" #include "ChildFrm.h" IM LEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

CCISEL 2001

Advanced MFC

9 de 20

A classe view ( CSCribbleView)

class CScribbleView : public CView { DECLARE_DYNCREATE(CScribbleView) private: CStroke* m_pStrokeCur; // the stroke in progress CPoint m_ptPrev; // the last mouse pt in the stroke in progress public: CScribbleDoc* GetDocument(); virtual void OnDraw(CDC* pDC); // overridden to draw this view protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() };

CCISEL 2001

Advanced MFC

10 de 20

A classe CScribbleView (implementação 1)
#include #include #include #include "stdafx.h" "Scribble.h" "ScribDoc.h" "ScribVw.h"

IMPLEMENT_DYNCREATE(CScribbleView, CView) BEGIN_MESSAGE_MAP(CScribbleView, CView) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() END_MESSAGE_MAP() void CScribbleView::OnDraw(CDC* pDC) { CScribbleDoc* pDoc = GetDocument(); // The view delegates the drawing of individual strokes to CStroke::DrawStroke(). for ( CScribbleDoc::StrokeIterator it = pDoc->beginIterator(); it != pDoc->endIterator(); ++it) { CStroke* pStroke = *it; pStroke->DrawStroke(pDC, false); } } CScribbleDoc* CScribbleView::GetDocument() { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CScribbleDoc))); return (CScribbleDoc*)m_pDocument; }

CCISEL 2001

Advanced MFC

11 de 20

A classe CScribbleView (implementação 2)
void CScribbleView::OnLButtonDown(UINT, CPoint point) m_pStrokeCur = GetDocument()->NewStroke(); m_pStrokeCur->add(point); SetCapture(); m_ptPrev = point; return; } void CScribbleView::OnLButtonUp(UINT, CPoint point) { if (GetCapture() != this) return; CScribbleDoc* pDoc = GetDocument(); CClientDC dc(this); CPen* pOldPen = dc.SelectObject(pDoc->GetCurrentPen()); dc.MoveTo(m_ptPrev); dc.LineTo(point); dc.SelectObject(pOldPen); m_pStrokeCur->add(point); ReleaseCapture(); return; } void CScribbleView::OnMouseMove(UINT, CPoint point) { if (GetCapture() != this) return; CClientDC dc(this); m_pStrokeCur->add(point); CPen* pOldPen = dc.SelectObject(GetDocument()->GetCurrentPen()); dc.MoveTo(m_ptPrev); dc.LineTo(point); dc.SelectObject(pOldPen); m_ptPrev = point; return; }

CCISEL 2001

Advanced MFC

12 de 20

Métodos da classe CDocument

AddView GetDocTemplate GetFirstViewPosition GetNextView GetPathName GetTitle IsModified RemoveView SetModifiedFlag SetPathName SetTitle UpdateAllViews Overridables. DeleteContents OnChangedViewList OnCloseDocument OnNewDocument OnOpenDocument OnSaveDocument

Attaches a view to the document. Returns a pointer to the document template that describes the type of the document. Returns the position of the first in the list of views; used to begin iteration. Iterates through the list of views associated with the document. Returns the path of the document¶s data file. Returns the document¶s title. Indicates whether the document has been modified since it was last saved. Detaches a view from the document. Sets a flag indicating that you have modified the document since it was last saved. Sets the path of the data file used by the document. Sets the document¶s title. Notifies all views that document has been modified. Called to perform cleanup of the document. Called after a view is added to or removed from the document. Called to close the document. Called to create a new document. Called to open an existing document. Called to save the document to disk.

CCISEL 2001

Advanced MFC

13 de 20

CDocTemplate Class Members

SetContainerInfo SetServerInfo GetFirstDocPosition GetNextDoc LoadTemplate AddDocument RemoveDocument GetDocString Overridables MatchDocType CreateNewDocument CreateNewFrame InitialUpdateFrame SaveAllModified CloseAllDocuments OpenDocumentFile SetDefaultTitle

Determines the resources for OLE containers when editing an in-place OLE item. Determines the resources and classes when the server document is embedded or edited in-place. Retrieves the position of the first document associated with this template. Retrieves a document and the position of the next one. Loads the resources for a given CDocTemplate or derived class. Adds a document to a template. Removes a document from a template. Retrieves a string associated with the document type. Determines the degree of confidence in the match between a document type and this template. Creates a new document. Creates a new frame window containing a document and view. Initializes the frame window, and optionally makes it visible. Saves all documents associated with this template which have been modified. Closes all documents associated with this template. Opens a file specified by a pathname. Displays the default title in the document window¶s title bar.

CCISEL 2001

Advanced MFC

14 de 20

CView Class Members

GetDocument OnInitialUpdate Overridables OnActivateView OnActivateFrame OnBeginPrinting OnDraw

Returns the document associated with the view. Called after a view is first attached to a document.

Called when a view is activated. Called when the frame window containing the view is activated or deactivated. Called when a print job begins; override to allocate graphics device interface (GDI) resources. Called to render an image of the document for screen display, printing, or print preview. Implementation required.

OnUpdate

Called to notify a view that its document has been modified.

CCISEL 2001

Advanced MFC

15 de 20

A classe CObject
A classe CObject dá suporte à construção virtual, RTTI e serialização de objectos. As classes MFC que pretenderem estas caracteristicas terão de providenciar uma instância de CRuntimeClass que contem toda a informação de runtime necessária. Para simplificar o trabalho do programador, foram definidas um conjunto de macros que dão independentemente cada um dos níveis de suporte (por ordem de abrangência, RTTI, construção virtual e Serialização). Ver Slides seguintes
Diagnostics AssertValid Dump Serialization IsSerializable Serialize Miscellaneous GetRuntimeClass IsKindOf Returns the CRuntimeClass structure corresponding to this object¶s class. Tests this object¶s relationship to a given class. Tests to see whether this object can be serialized. Loads or stores an object from/to an archive. Validates this object¶s integrity. Produces a diagnostic dump of this object.

CCISEL 2001

Advanced MFC

16 de 20

A classe CRuntimeClass
struct CRuntimeClass { // Attributes LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; // schema number of the loaded class CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class CRuntimeClass* m_pBaseClass;

// Operations CObject* CreateObject(); BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; // Implementation void Store(CArchive& ar) const; static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum); // CRuntimeClass objects linked together in simple list CRuntimeClass* m_pNextClass; };

CCISEL 2001

Advanced MFC

17 de 20

Macros para MFC rtti, construção virtual e serialização

DECLARE_DYNAMIC( class_name ) IMPLEMENT_DYNAMIC( class_name, base_class_name )

DECLARE_DYNCREATE( class_name ) IMPLEMENT_DYNCREATE( class_name, base_class_name )

DECLARE_SERIAL( class_name ) IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )

CCISEL 2001

Advanced MFC

18 de 20

A classe CArchive

Close Basic Input/Output Flush operator >> operator << Read Write WriteString ReadString Status GetFile GetObjectSchema SetObjectSchema IsLoading IsStoring Object Input/Output ReadObject WriteObject

Flushes unwritten data and disconnects from the CFile. Flushes unwritten data from the archive buffer. Loads objects and primitive types from the archive. Stores objects and primitive types to the archive. Reads raw bytes. Writes raw bytes. Writes a single line of text. Reads a single line of text. Gets the CFile object pointer for this archive. Called from the Serialize function to determine the version of the object that is being deserialized. Sets the object schema stored in the archive object. Determines whether the archive is loading. Determines whether the archive is storing. .

Calls an object¶s Serialize function for loading. Calls an object¶s Serialize function for storing.

CCISEL 2001

Advanced MFC

19 de 20

Macros para MFC rtti, construção virtual e serialização (definição)

#define _DECLARE_DYNAMIC(class_name) \ public: \ static AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; #define DECLARE_DYNCREATE(class_name) \ DECLARE_DYNAMIC(class_name) \ static CObject* CreateObject();

#define DECLARE_SERIAL(class_name) \ DECLARE_DYNCREATE(class_name) \ AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb); #define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \ CObject* PASCAL class_name::CreateObject() \ { return new class_name; } \ _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \ class_name::CreateObject) \ AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \ CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \ { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \ return ar; }

CCISEL 2001

Advanced MFC

20 de 20