You already know that the document object holds the data and that the view object displays the data and allows editing. An SDI application has a document class derived from CDocument, and it has one or more view classes, each ultimately derived from CView. A complex handshaking process takes place among
the document, the view, and the rest of the application framework. To understand this process, you need to know about five important member functions in the document and view classes. Two are nonvirtual base class functions that you call in your derived classes; three are virtual functions that you often override in your derived classes. Let's look at these functions one at a time.
The CView::GetDocument Function
A view object has one and only one associated document object. The GetDocument function allows an application to navigate from a view to its document. Suppose a view object gets a message that the user has entered new data into an edit control. The view must tell the document object to update its internal data accordingly. The GetDocument function provides the document pointer that can be used to access document class member functions or public data embers.
The CDocument::GetNextView function navigates from the document to the view, but because a document can have more than one view, it's necessary to call this member function once for each view, inside a loop. You'll seldom call GetNextView because the application framework provides a better method of iterating through a document's views.
When AppWizard generates a derived CView class, it creates a special type-safe version of the GetDocument function that returns not a CDocument pointer but a pointer to an object of your derived class. This function is an inline function, and it looks something like this:
CMyDoc* GetDocument() { return (CMyDoc*) m_pDocument; }
When the compiler sees a call to GetDocument in your view class code, it uses the derived class version instead of the CDocument version, so you do not have to cast the returned pointer to your derived document class. Because the CView::GetDocument function is not a virtual function, a statement such as
pView->GetDocument(); // pView is declared CView*
calls the base class GetDocument function and thus returns a pointer to a CDocument object.
The CDocument::UpdateAllViews Function
If the document data changes for any reason, all views must be notified so that they can update their representations of that data. If UpdateAllViews is called from a member function of a derived document class, its first parameter, pSender, is NULL. If UpdateAllViews is called from a member function of a derived view class, set the pSender parameter to the current view, like this:
GetDocument()->UpdateAllViews(this);
The non-null parameter prevents the application framework from notifying the current view. The assumption here is that the current view has already updated itself.
The function has optional hint parameters that can be used to give view-specific and application-dependent information about which parts of the view to update. This is an advanced use of the function.
How exactly is a view notified when UpdateAllViews gets called? Take a look at the next function, OnUpdate.
The CView::OnUpdate Function
This virtual function is called by the application framework in response to your application's call to the CDocument::UpdateAllViews function. You can, of course, call it directly within your derived CView class. Typically, your derived view class's OnUpdate function accesses the document, gets the document's data, and then updates the view's data members or controls to reflect the changes. Alternatively, OnUpdate can invalidate a portion of the view, causing the view's OnDraw function to use document data to draw in the window. The OnUpdate function might look something like this:
void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { CMyDocument* pMyDoc = GetDocument(); CString lastName = pMyDoc->GetLastName(); m_pNameStatic->SetWindowText(lastName); // m_pNameStatic is // a CMyView data member }
The hint information is passed through directly from the call to UpdateAllViews. The default OnUpdate implementation invalidates the entire window rectangle. In your overridden version, you can choose to define a smaller invalid rectangle as specified by the hint information.
If the CDocument function UpdateAllViews is called with the
pSender parameter pointing to a specific view object, OnUpdate is called for all the document's views except the specified view.
The CView::OnInitialUpdate Function
This virtual CView function is called when the application starts, when the user chooses New from the File menu, and when the user chooses Open from the File menu. The CView base class version of OnInitialUpdate does nothing but call OnUpdate. If you override OnInitialUpdate in your derived view class, be sure that the view class calls the base class's OnInitialUpdate function or the derived class's OnUpdate function.
You can use your derived class's OnInitialUpdate function to initialize your view object. When the application starts, the application framework calls OnInitialUpdate immediately after OnCreate (if you've mapped OnCreate in your view class). OnCreate is called once, but OnInitialUpdate can be called many times.
The CDocument::OnNewDocument Function
The framework calls this virtual function after a document object is first constructed and when the user chooses New from the File menu in an SDI application. This is a good place to set the initial values of your document's data members. AppWizard generates an overridden OnNewDocument function in your derived document class. Be sure to retain the call to the base class function.