Register for EarthWeb's Million Dollar Sweepstakes!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Now we’ve stored the characters the user has typed. The next step is to display them in OnDraw().

Displaying Text in MDI

In the OnDraw() function, we display the text in the text[] array. First, we set up a loop over all the lines in the text[] array.

void CMDIView::OnDraw(CDC* pDC)

{
    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    for(int loop_index = 0; loop_index <= pDoc->number_lines; loop_index++){
                                                                ⇐
        .
        .
        .
    }                                                         ⇐

}

To display multiline text, we need to determine how high each line is on the screen, and we do that with a TEXTMETRIC structure. The tmHeight member of that structure indicates how high each line of text is in the current font. We set up the TEXTMETRIC structure for the current device context as follows:

void CMDIView::OnDraw(CDC* pDC)

{
    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    TEXTMETRIC tm;                                              ⇐

    pDC->GetTextMetrics(&tm);                              ⇐

    for(int loop_index = 0; loop_index <= pDoc->number_lines; loop_index++){
        .
        .
        .
    }

}

We can loop over the text lines, displaying each line in its correct screen position, as shown in the following example:

void CMDIView::OnDraw(CDC* pDC)

{
    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    TEXTMETRIC tm;

    pDC->GetTextMetrics(&tm);

    for(int loop_index = 0; loop_index <= pDoc->number_lines; loop_index++){
        pDC->TextOut(0, loop_index * tm.tmHeight, pDoc->text[loop_index]);                                      
                                                                           ⇐
    }

}

Run the program now, as shown in Figure 2.2. As you type text, such as “This is the text,” one word per line, that text appears in the document’s MDI child window. Open a new view into the document now using the New Window item in the Window menu. Our text, “This is the text,” appears in the second view as well as the first.

However, if you type additional text into the second view, that text appears in the second view only. Although the text is being stored in the document, the first view is not updated as we type, which is a problem.

It’s time to fix this problem, which we do by coordinating the views.

Coordinating MDI Views

You can coordinate views by updating them with the UpdateAllViews() function. This function takes three arguments: a pointer to the view doing the updating (so it is not updated); a long value, which is called a hint; and a pointer to an object, which is also part of that hint. We see how to use hints in a moment, but for now, set these last two parameters to 0. Here’s how we use UpdateAllViews():

void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{
    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
  
    if(nChar != '\r'){
        pDoc->text[pDoc->number_lines] += nChar;
        Invalidate();

    }

    else{
        pDoc->number_lines++;      
    }
  
    pDoc->UpdateAllViews(this, 0L, NULL);                    ⇐

    CView::OnChar(nChar, nRepCnt, nFlags);

}


Figure 2.2  The MDI project, first try.

With the preceding code, all the views connected to this document are updated when the user types anything. To update all the views, the document calls each view’s OnUpdate() function, and by default, that function simply calls the view’s OnDraw() function. This means that we can type into either view and the other one will be automatically updated, as shown in Figure 2.3.

Each time a view is updated this way, however, the entire view is redrawn. There’s a more efficient way of doing things: making use of hints.

Using View Hints

You may recall that the UpdateAllViews() function takes two hint parameters: a long integer and a pointer. Using hints, you can indicate to the other views exactly what part of the view needs to be updated. For example, the pointer can point to a data object that holds the new data.


Figure 2.3  Coordinating MDI views.

By using hints in our MDI program, we can pass the line number that’s been modified to the other views, and they can redisplay only that line. This is of minimal importance if you’re only displaying a few lines of text, but if you have a 1000-line document, you shouldn’t redraw the whole document each time the user types a new key.

To pass the number of the modified line to other views, then, we convert that number to a long integer and pass it to UpdateAllViews().

void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{
    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
  
    if(nChar != '\r'){
        pDoc->text[pDoc->number_lines] += nChar;
        Invalidate();
    }
    else{
        pDoc->number_lines++;      
    }
  
    pDoc->UpdateAllViews(this, (long) pDoc->number_lines, NULL);   ⇐

    CView::OnChar(nChar, nRepCnt, nFlags);

}

Now we can make use of that hint in other views, and we do that in the OnUpdate() function.

Using OnUpdate() in MDI Programs

To decipher the hint we’re passing to other views, we use ClassWizard to override the OnUpdate() function.

void CMDIView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

{

    // TODO: Add your specialized code here and/or call the base class
  

}

In this case, we want to redraw the line whose number is passed to us in the lHint parameter. To do that, we first need a device context for this view, and we get that with the CClientDC class.

void CMDIView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

{
    CClientDC dc(this);                   ⇐
        .
        .
        .
}

To accurately place the line on the screen, we need to know the line’s height, and we get that with a TEXTMETRIC structure. We set up a pointer to the document so we can read the line’s new text as follows:

void CMDIView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

{
    CClientDC dc(this);
    TEXTMETRIC tm;                      ⇐

    CMDIDoc* pDoc = GetDocument();      ⇐
    ASSERT_VALID(pDoc);                 ⇐

    dc.GetTextMetrics(&tm);             ⇐
         .
         .
         .
}

Now we simply redisplay the line referred to by the hint—and only that line—this way:

void CMDIView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

{
    CClientDC dc(this);
    TEXTMETRIC tm;

    CMDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    dc.GetTextMetrics(&tm);

    dc.TextOut(0, (int) lHint * tm.tmHeight, pDoc->text[lHint]);   ⇐

}


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.