Implement OLE In-Place Support in the View Class

To implement OLE in-place support in the view class, you must:

Before Scribble was enhanced to be an OLE in-place editing server, it was lazy about its device context coordinates using MM_LOENGLISH: Scribble did not adjust for how many logical pixels per inch were on the screen display. Most serious Windows applications scale their screen output because small fonts are rarely readable when displayed in their true (physical) size. Applications can adjust for the number of pixels in the logical inch by applying the kind of logic illustrated by the following code sample. This logic relies primarily on values returned by CDC::GetDeviceCaps(LOGPIXELSX) and GetDeviceCaps(LOGPIXELSY). Now that Scribble is an OLE server, it should scale according to logical pixels per inch. Otherwise, you (and your user) will notice a difference in the scaling of a Scribble drawing when the Scribble server is fully open versus its scaling when it is displayed embedded in the container.

Suggested Reading in the Microsoft Foundation Class Reference

To implement logical MM_LOENGLISH rather than physical MM_LOENGLISH

  1. From the View menu, click ClassWizard.

  2. If necessary, click the Message Maps tab and ensure that CScribbleView is selected in the Class name and Object IDs boxes.

  3. In the Messages box, click OnPrepareDC, and click the Add Function button.

  4. Click Edit Code.

  5. Implement the override of OnPrepareDC as follows:
    void CScribbleView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
    {
    CScribbleDoc* pDoc = GetDocument();
    CScrollView::OnPrepareDC(pDC, pInfo);
    
    pDC->SetMapMode(MM_ANISOTROPIC);
    CSize sizeDoc = pDoc->GetDocSize();
    sizeDoc.cy = -sizeDoc.cy;
    pDC->SetWindowExt(sizeDoc);    
    
    CSize sizeNum, sizeDenom;
    pDoc->GetZoomFactor(&sizeNum, &sizeDenom);
    
    int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);
    int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);
    
    long xExt = (long)sizeDoc.cx * xLogPixPerInch * sizeNum.cx;
    xExt /= 100 * (long)sizeDenom.cx;
    long yExt = (long)sizeDoc.cy * yLogPixPerInch * sizeNum.cy;
    yExt /= 100 * (long)sizeDenom.cy;
    pDC->SetViewportExt((int)xExt, (int)-yExt);
    }
    

In the following procedure, you’ll implement the ResyncScrollSizes helper function mentioned previously.

To adjust the scroll view’s scroll bars to reflect the use of the logical MM_LOENGLISH mapping mode

  1. In ClassView, right-click CScribbleView.

  2. From the pop-up menu, click Add Member Function.

  3. In the Add Member Function dialog box, specify the following:
    • In the Function Type box, type void .

    • In the Function Declaration box, type ResyncScrollSizes().

    • In the Access area, click Public.

    Click OK.

  4. Fill in the starter definition with the following code:
    CClientDC dc(NULL);
    OnPrepareDC(&dc);
    CSize sizeDoc = GetDocument()->GetDocSize();
    dc.LPtoDP(&sizeDoc);
    SetScrollSizes(MM_TEXT, sizeDoc);
    
  5. Use ClassView to jump to CScribbleView::OnInitialUpdate and replace the call to CScrollView::SetScrollSizes with the call to the helper function, ResyncScrollSizes:
    void CScribbleView::OnInitialUpdate()
    {
    ResyncScrollSizes();
    CScrollView::OnInitialUpdate();
    }
    

    In the next several steps you’ll use WizardBar to add a function that updates the scroll bars appropriately when the window is sized.

  6. Switch to ScribbleView.cpp in the editor.

  7. In the WizardBar Class list box, click CScribbleView

  8. Click the Action arrow, located on the right end of WizardBar.

  9. On the menu, click Add Windows Message Handler.

    The New Windows Message and Event Handlers dialog box appears.

  10. In the New Windows messages/events list, click WM_SIZE.

  11. Click Add Handler to add WM_SIZE to the Existing message/event handlers list.

  12. Click Edit Existing.

  13. Replace the //TODO comment with a call to ResyncScrollSizes:
    ResyncScrollSizes();        //  ensure that scroll info is up-to-date
    
  14. Use ClassView to jump to the CScribbleView constructor and replace the comment with the following code:
    SetScrollSizes(MM_TEXT, CSize(0,0));
    

    You must initialize the scroll sizes in the CScribbleView constructor to default values, so that the extent is defined before the first call to OnPrepareDC.

When Scribble’s view finishes adding a new stroke in CScribbleView::OnLButtonDown, it calls the document’s UpdateAllViews to inform other views that they need to invalidate a portion of the client area occupied by the new stroke. This notification is fine for Scribble when it is running stand-alone, but it is not adequate when Scribble is fully opened and editing an embedded object. In the latter case, Scribble needs to inform the container that the object has changed. This requires an additional call to COleServerDoc::NotifyChanged.

To notify OLE when the embedded item changes