MFC: MDI singleton doc/view application

What singleton means? In our case it’s MDI application where the user can’t have more than one document of a given type open at any time. In order to implement this in doc/view fashion we need 2 things.

First we need a public member in our CDocument delivered class that when called will tell us whatever view of supplied type already exists. Here is the implementation of this public member function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * @brief Check's if given view is already loaded.
 * @param rtClass - the runtime class of the view.
 */
BOOL CVPhoneBookDoc::NeedViewCreation(CRuntimeClass *rtClass)
{
	POSITION pos = GetFirstViewPosition();
	while(pos != NULL)
	{
		CView *pView = GetNextView(pos);
		if(pView->GetRuntimeClass() == rtClass)
		{
			CMDIChildWnd * pViewFrame = (CMDIChildWnd *)pView->GetParentFrame();
			((CMDIFrameWnd*)AfxGetMainWnd())->MDIActivate(pViewFrame);
			return FALSE; // Already exists
		}
	}
 
	return TRUE; // Allow creation
}

The function iterates over the views associated with the document and try’s to find one that’s match our supplied run-time class. If match is found the view is activated and FALSE is returned. Else view creation is allowed.

Second we need to implement a custom member function, for example in the CWinApp delivered class that will be called as replacement of OnNewDocument() or OnOpenDocument(). Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void CVPhoneBookApp::OnCreateContactVeiw()
{
	POSITION curTemplatePos = GetFirstDocTemplatePosition();
 
	while(curTemplatePos != NULL)
	{
		CDocTemplate* curTemplate =
			GetNextDocTemplate(curTemplatePos);
		CString str;
		curTemplate->GetDocString(str, CDocTemplate::docName);
		if(str == _T("Contacts"))
		{
			// We have only one document for template "Contacts"
			POSITION docPos = curTemplate->GetFirstDocPosition();
			if(docPos == NULL)
			{
				curTemplate->OpenDocumentFile(NULL);
			}
			else
			{
				CVPhoneBookDoc *pDoc = (CVPhoneBookDoc*)curTemplate->GetNextDoc(docPos);
				if(pDoc)
				{
					// Check if view of this type exists
					if(pDoc->NeedViewCreation(RUNTIME_CLASS(CContactsView)))
					{
						curTemplate->OpenDocumentFile(NULL);
					}
				}
			}
		}
	}
}

When called this function first checks if document is available. If it’s not available we call CDocTemplate member function OpenDocumentFile() else, we retrieve a pointer to the document class and checks if view of requested type need’s to be created.

If you liked this article and think it is useful use the buttons below.

Leave a Reply

Your email address will not be published. Required fields are marked *

*