[C++ – MFC] Structure – App/Document/View

MFC(Microsoft Foundation Classes) is a class library for building GUI (Graphical User Interface) on Windows operating systems.

MFC actually a wrapper of Windows APIs in an object-oriented way. MFC follows the concept of the famous MVC pattern, maybe roughly. It has documents (data), views, and a document template (controller). But by allowing handling events in a view, MFC code becomes quite complex. If you develop a new GUI application, I recommend you to use CLI (.NET) applications. MFC should be restricted just for legacy applications.  

 

1. Documents

A document in MFC can be regarded as a collection of data you want to manipulate. The name “Document” seems to imply the textual data, but in MFC a document is a generic term for any data. In MFC, a document class is derived from the “CDocument” class.

An application can handle only one document at a time or multiple documents at the same time.

  • SDI (Single Document Interface)
  • MDI (Multiple Document Interface)

 

2. Views

A view is always relates to a particular document and is responsible to display the data to a user. In MFC, a view class is derived from the “CView” class and the window in which a view appears is called a “frame window“.

 

3. Document Template: Linking Views and Documents

The connection between documents and views are not the relationship just between two of them. The frame window stores a pointer to the currently active view.

Now we have 3 players: a document, a view, and a frame window. what’s behind of them? Who create these?

The controller object is a “document template“. An application(CWinApp) object create a document template object. The document template creates a document object and a frame window object. A frame window object is responsible to create a view object.

  • SDI: CSingleDocTemplate, CFrameWnd
  • MDI: CMultiDocTemplate, CMDIFrameWnd
CMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
    CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass);

Look at the constructor of the “CMultiDocTemplate” class. You need to pass the doc/view/frame classes as arguments.

 

4. How does the Program Work – Where’s the main()

If you search the “main()” function in your MFC application, you might be surprised that you cannot find it.

So how in the world does the application work?

The “main()” function is hidden in the MFC library (MFC has WinMain() as a starting point). When you start the application, MFC creates your application object (derived from CWinApp).

Here’s how MFC works:

  1. Create an Application object
  2. Call “CWinApp::InitInstance()
  3. Call “CWinApp::Run()
  4. Call “CWinApp::ExitInstance()

– Tasks of InitInstance()

  • WinMain calls InitInstance() every time a new instance of the application starts
  • As its central action, creates the document templates that in turn create documents, views, and frame windows
  • For an MDI application, creates a main frame window
  • Processes the command line arguments.

– Tasks of Run() –

  • MFC applications spend most of their time in the Run() function
  • After initialization, WinMain calls Run() to process the message loop
  • If a message is available, Run dispatches it for action
  • If no messages are available, Run calls OnIdle() to do any idle-time processing
  • When the application terminates, Run calls ExitInstance().

– Tasks of OnIdle() –

  • Updates the state of UI objects
  • performs cleanup of temporary objects

– Tasks of ExitInstance() –

  • The ExitInstance() is called each time a copy of your application terminates
  • Override this to clean up resources

 

5. Overriding CWinApp Member Functions

The InitInstance(), Run(), ExitInstance(), and OnIdle() functions are virtual, therefore you can override them and provide your implementation.

  • virtual BOOL InitInstance();
  • virtual int Run();
  • virtual BOOL OnIdle( LONG lCount );
  • virtual int ExitInstance());
BOOL CMyApp::InitInstance()
{
  CWinApp::InitInstance();

  // Create a Template

  // create a framework window

  // Process command line arguments

  return TRUE;
}

int CMyApp::Run()
{
  int nRet = 0;
  try
  {
    nRet = CWinApp::Run();
  }
  catch (...)
  {
    TRACE("Error!!");
  }
  return nRet;
}

BOOL CMyApp::OnIdle(LONG lCount)
{
  // In most applications, you should let the
  // base class CWinApp::OnIdle complete its processing before
  // you attempt any additional idle loop processing.
  if (CWinApp::OnIdle(lCount))
    return TRUE;

  // The base class CWinApp::OnIdle reserves the lCount values 0
  // and 1 for the framework's own idle processing. If you wish
  // to share idle processing time at a peer level with the
  // framework, then replace the above if-statement with a
  // straight call to CWinApp::OnIdle; and then add a case
  // statement for lCount value 0 and/or 1.
  // Study the base class implementation first to
  // understand how your idle loop tasks will compete with the
  // framework's idle loop processing.

  switch (lCount)
  {
  case 2:
    Task1();
    return TRUE; // next time give Task2 a chance
  case 3:
    Task2();
    return TRUE; // next time give Task3 and Task4 a chance
  case 4:
    Task3();
    Task4();
    return FALSE; // cycle through the idle loop tasks again
  }
  return FALSE;
}

int CMyApp::ExitInstance()
{
  // clean up your resources here

  return CWinApp::ExitInstance();
}

One thought on “[C++ – MFC] Structure – App/Document/View

  1. Thanks for sharing this useful information,In future if you decide to publish any new article about MFC structure kindly let me k.ow

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s