MFC Document View Architecture Example

///////////////////////////////////////////////////////////////////////////
//Microsoft Visual Studio generated resource script.
///////////////////////////////////////////////////////////////////////////

IDR_MAINFRAME MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "New", ID_FILE_NEW
MENUITEM "Open", ID_FILE_OPEN
MENUITEM "Save", ID_FILE_SAVE
MENUITEM "Save ", ID_FILE_SAVE_AS
MENUITEM SEPARATOR
MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
MENUITEM SEPARATOR
MENUITEM "Exit", ID_APP_EXIT
END
POPUP "Select"
BEGIN
MENUITEM "View1", IDR_VIEW1
MENUITEM "View2", IDR_VIEW2
END
END
/////////////////////////////////////////////////////////////////////////////
#include "resource.h"

//application class declaration
class App : public CWinApp
{
public:
virtual BOOL InitInstance();
void SwapView1();
void SwapView2();
void Switchviews(CRuntimeClass*);
DECLARE_MESSAGE_MAP()
};

//document class declaration
class Doc : public CDocument
{
protected:
DECLARE_DYNCREATE(Doc)
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
SetNewValue(int,int);
int px[100];
int py[100];
int clickcount;
};

//frame window class declaration
class CMainFrame : public CFrameWnd
{
protected:
DECLARE_DYNCREATE(CMainFrame)
DECLARE_MESSAGE_MAP()
};

//first view class declaration
class View : public CView
{
protected:
DECLARE_DYNCREATE(View)
DECLARE_MESSAGE_MAP()
public:
Doc* GetDocument();
void OnLButtonDown(UINT,CPoint);
virtual void OnDraw(CDC* pDC); // overridden to draw this view
};

//second view class declaration
class View1 : public CView
{
protected:
DECLARE_DYNCREATE(View1)
DECLARE_MESSAGE_MAP()
public:
Doc* GetDocument();
void OnLButtonDown(UINT,CPoint);
virtual void OnDraw(CDC* pDC);
};

// enable CObject-derived classes to be created dynamically at run time
IMPLEMENT_DYNCREATE(View1, CView)
IMPLEMENT_DYNCREATE(View, CView)
IMPLEMENT_DYNCREATE(Doc, CDocument)
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

//message map for the application window
BEGIN_MESSAGE_MAP(App, CWinApp)
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
ON_COMMAND(IDR_VIEW1, SwapView1)
ON_COMMAND(IDR_VIEW2, SwapView2)
END_MESSAGE_MAP()

//message map for the frame window
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()

//message map for the document window
BEGIN_MESSAGE_MAP(Doc, CDocument)
END_MESSAGE_MAP()

//message map for the first view window
BEGIN_MESSAGE_MAP(View, CView)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

//message map for the second view window
BEGIN_MESSAGE_MAP(View1, CView)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

App theApp;//instantiate the application

// Application initialization
BOOL App::InitInstance()
{
//Enable and load the list of most recently used (MRU) files
LoadStdProfileSettings();
//defines a document template that implements the single document interface
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(Doc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(View));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}

//responds to swapview request view1
void App::SwapView1()
{
CRuntimeClass* crtclView = RUNTIME_CLASS(View);
Switchviews(crtclView);
}

//responds to swapview request view2
void App::SwapView2()
{
CRuntimeClass* crtclView = RUNTIME_CLASS(View1);
Switchviews(crtclView);
}

//stitches application views
void App::Switchviews(CRuntimeClass* pNewView)
{
CFrameWnd* pMainWnd = (CFrameWnd*)AfxGetMainWnd();
CView* pOldActiveView = pMainWnd->GetActiveView();
CDocument* pOldActiveDoc = pMainWnd->GetActiveDocument();
CString m_temp;
if (pOldActiveView->IsKindOf(pNewView))
return ;
SetWindowLong(pOldActiveView->m_hWnd, GWL_ID, 0);
CCreateContext context;
context.m_pNewViewClass = pNewView;
context.m_pCurrentDoc = pOldActiveDoc;
CView* pDisplayView = STATIC_DOWNCAST(CView, pMainWnd->CreateView(&context));
if (pDisplayView != NULL)
{
pDisplayView->ShowWindow(SW_SHOW);
pDisplayView->OnInitialUpdate();
pMainWnd->SetActiveView(pDisplayView);
pMainWnd->RecalcLayout();
pOldActiveView->ShowWindow(SW_HIDE);
}
}

//sets array to position of click
Doc::SetNewValue(int x,int y)
{
clickcount=clickcount+1;
if (clickcount<10)
{
px[clickcount]=x;
py[clickcount]=y;
}
}

//new document request
BOOL Doc::OnNewDocument()
{
clickcount=0;
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}

//deals with loading or saving the document
void Doc::Serialize(CArchive& ar)
{
//used for saving document data
if (ar.IsStoring())
{
ar<< clickcount;
for (int i=1;i<=clickcount;i++)
{
ar<<px[i];
ar<<py[i];
}
}
//loading document data
else
{
ar >> clickcount;
for (int i=1;i<=clickcount;i++)
{
ar>>px[i];
ar>>py[i];
}
}
}

//draws to first view
void View::OnDraw(CDC* pDC)
{
Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int x=0,y=0;
int totalclicks=pDoc->clickcount;
for (int i=1;i<=totalclicks;i++)
{
x=pDoc->px[i];
y=pDoc->py[i];
pDC->TextOut(x, y, "x", 1);
}
}

//deals with left buttons click in first view
void View::OnLButtonDown(UINT nFlags, CPoint point )
{
Doc* pDoc = GetDocument();
pDoc->SetNewValue(point.x,point.y);
pDoc->UpdateAllViews(NULL);
}

Doc* View::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(Doc)));
return (Doc*)m_pDocument;
}

//draws to second view
void View1::OnDraw(CDC* pDC)
{
Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int x=0,y=0;
int totalclicks=pDoc->clickcount;
for (int i=1;i<=totalclicks;i++)
{
x=pDoc->px[i];
y=pDoc->py[i];
pDC->TextOut(x, y, "*", 1);
}
}
//deals with left buttons click in second view
void View1::OnLButtonDown(UINT nFlags, CPoint point )
{
Doc* pDoc = GetDocument();
pDoc->SetNewValue(point.x,point.y);
pDoc->UpdateAllViews(NULL);
}

Doc* View1::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(Doc)));
return (Doc*)m_pDocument;
}