Document/View Without Templates


Click here to change the theme.

For many (probably most for most people) applications, the MFC Document/View Architecture is not flexible enough. It is designed assuming that data are in files such that, for example, the CFileDialog class is useful for determining the data to be stored and restored. In my opinion, the problem is not the document class or view classes; the problem is the other classes, in particular CSingleDocTemplate, CMultiDocTemplate and related classes such as the undocumented CDocManager class. Quite often, a dialog-based solution is used due to it's initial simplicity. However a dialog-based application can get unnecessarily complicated when it needs to provide capabilities that are provided by default by MFC SDI applications. This article describes how to convert an application that was generated by the AppWizard as a MFC SDI application without Document/View Architecture support to an application that uses a view. The result is an application that can be a reasonable alternative to a dialog-based solution.

I have attempted to be as accurate and thorough as possible but since this is the first version of these instructions there might be some corrections necessary. Please feel free to email me at "feedback" at SimpleSamples.Info. Some of the following must be done in the order described but not all must be done in this exact order. There are many alternative ways to do most of these things so you can certainly try other things too.

Note that I recommend using a document A document does not complicate things and can make some things easier; for one thing, it makes communication with the view from the application much easier.

  1. Use the AppWizard to generate a MFC SDI application without Document/View Architecture support. See the summary below of the application I started with; not all features are required.
  2. Usually we will use CFormView for the view, and if you do, create a dialog template for the form
  3. Create a class derived from CFormView (use the ClassWizard "Add Class" button for that and use the dialog template of course) then the constructor and destructor public
  4. In MainFrame.h, change the view (CChildView) to the new view's name
  5. Delete the generated (old) view (the CChildView.cpp and CChildView.h files) from the project
  6. Delete the generated (old) view (the CChildView.cpp and CChildView.h files)
  7. In the CMainFrame class, the overrides of PreCreateWindow, OnSetFocus and OnCmdMsg can all be deleted. If you have use of any of them, then you can first remove the code in them; be sure to leave the call to the base class function unless you definitely don't need to call them. Also in CMainFrame, in the OnCreate override, remove the call to Create (m_wndView.Create()).
  8. If you will be using a document (I suggest you do) create a class derived from CDocument (use the ClassWizard "Add Class" button to do  that) and then make the constructor public
  9. If you will be using a document, then you will need to store a pointer to it. The application class is one place to do that, so add something such as the following wherever you decide to:
    CNonTemplatedDocument *m_pNonTemplatedDocument;
  10. In InitInstance, replace:
    pFrame->LoadFrame(IDR_MAINFRAME,
    	WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
    	NULL);

    with:

    m_pNonTemplatedDocument = new CNonTemplatedDocument;
    CCreateContext CreateContext;
    CreateContext.m_pNewViewClass = RUNTIME_CLASS(CNonTemplatedView);
    CreateContext.m_pCurrentFrame = pFrame;
    CreateContext.m_pCurrentDoc = m_pNonTemplatedDocument;
    if (!pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW,
    		NULL, &CreateContext)) {
    	AfxMessageBox("Frame Load Error");
    	return FALSE;
    }
    pFrame->InitialUpdateFrame(m_pNonTemplatedDocument, TRUE);

    where:

    m_pNonTemplatedDocument
    is the pointer to the document
    CNonTemplatedView
    is the view class you created

  11. There are many #include statements that must be added to the cpp files. The following table shows the #includes for the project I built to write this article. Also, delete the #include for the old view from MainFrm.h.
    NonTemplatedDocument.cpp

    stdafx.h

    NonTemplatedDocument.h

    NonTemplated.h

    NonTemplated.cpp

    stdafx.h

    NonTemplatedDocument.h

    NonTemplated.h

    NonTemplatedView.h

    MainFrm.h

    NonTemplatedView.cpp

    stdafx.h

    NonTemplatedDocument.h

    NonTemplated.h

    NonTemplatedView.h

    MainFrm.cpp

    stdafx.h

    NonTemplatedDocument.h

    NonTemplated.h

    NonTemplatedView.h

    MainFrm.h

The project should compile and work after the changes above were made. There are miscellaneous improvements that are useful but this will get a basic application working. I will add suggestions for other improvements later.

Summary of the Application I Started With

Initial toolbar in main frame
Initial status bar in main frame
3D Controls
Uses shared DLL implementation (MFC42.DLL)
ActiveX Controls support enabled
Localizable text in: English [United States]
No Document/View
No Database support
Normal toolbars
Comments

Sample Project

Download NonTemplated.zip for the project I built to write this article. I added a few lines that show put data into the document and how to show the data in the view.