Suppose you write a program editor that uses the MDI architecture to allow the user to display multiple views of a source code file. If a change made to a file in one view is visible in the others, all views of that file should be updated to reflect the change. That's what UpdateAllViews is for. When a document's data is modified in a multiple-view application, someone—either the object that made the modification (usually a view object) or the document object—should call UpdateAllViews to update the views. UpdateAllViews iterates through the list of views associated with the document, calling each view's virtual OnUpdate function.
CView provides a trivial implementation of OnUpdate that invalidates the view and forces a call to OnDraw. If a full repaint is what you want, there's no need to override OnUpdate. If, however, you want to make updates as efficient as possible by repainting only the part of the view that changed, you can override OnUpdate in the view class and make use of hint information passed to UpdateAllViews. UpdateAllViews is prototyped as follows:
void UpdateAllViews (CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL) |
The function prototype for OnUpdate looks very similar:
virtual void OnUpdate (CView* pSender, LPARAM lHint, CObject* pHint) |
lHint and pHint carry hint information from UpdateAllViews to OnUpdate. How you use these parameters is highly application-specific. A simple use for hint information is to pass the address of a RECT structure or a CRect object specifying what part of the view needs updating. OnUpdate can use that information in a call to InvalidateRect, as demonstrated here:
// In the document class UpdateAllViews (NULL, 1, (CObject*) pRect); |
If the document's data consists of an array of CObjects and UpdateAllViews is called because a new CObject was added to the document, pHint might be used to pass the new CObject's address. The following example assumes that pLine holds a pointer to an instance of a CObject-derived class named CLine and that CLine includes a public member function named Draw that can be called to render the CLine on the screen:
// In the document class UpdateAllViews (NULL, 1, pLine); |
In both examples, OnUpdate forwards the call to the base class if lHint is anything other than the application-specific value passed to UpdateAllViews. That's important, because MFC sometimes calls OnUpdate itself with lHint equal to 0. You can use any nonzero value that you like for lHint. You can even define multiple "hint sets" that assign different meanings to pHint and use lHint to identify the hint type.
You can use UpdateAllViews' first parameter, pSender, to omit a view from the update cycle. If pSender is NULL, UpdateAllViews calls each view's OnUpdate function. If pSender is non-NULL, UpdateAllViews calls OnUpdate on every view except the one identified by pSender. When a function in the document class calls UpdateAllViews, it typically sets pSender to NULL so that all the views will be updated. If a view calls UpdateAllViews, however, it can set pSender to this to prevent its own OnUpdate function from being called. If the view has already updated itself in response to user input, its OnUpdate function doesn't need to be called. If, however, the view hasn't already updated itself because it performs all of its updating in OnUpdate, it should pass UpdateAllViews a NULL first parameter.
The sample program in the next section makes trivial use of UpdateAllViews by calling it without hint parameters. Secondary views are updated by the default implementation of OnUpdate. Later in this chapter, we'll develop a more ambitious multiple-view application that passes hint information to UpdateAllViews and makes use of that information in OnUpdate.