Implementing Hit Testing and Selection

The AppWizard-provided starter application initially supports only one embedded object. This part of the tutorial adds support for multiple objects by implementing hit testing and selection. Hit testing determines which of the multiple objects lies at a given point.

In the next two procedures, you’ll use ClassView to add two helper functions to class CContainerView: HitTestItems and SetSelection. These functions implement hit testing and selection.

To implement hit testing

  1. In ClassView, right-click the CContainerView class icon.

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

    The Add Member Function dialog box appears.

  3. Fill in the dialog box as follows:

    • In the Function Type box, type CContainerItem*.

    • In the Function Declaration box, type the following:

      HitTestItems(CPoint point)
      
    • In the Access area, select Public.

    • Click OK.

    ClassWizard adds the declaration to the header file and creates a starter definition in the implementation file.

  4. In ContainerView.cpp, type the following code to fill in the function definition for HitTestItems:

    CContainerDoc* pDoc = GetDocument();
    CContainerItem* pItemHit = NULL;
    POSITION pos = pDoc->GetStartPosition();
    while (pos != NULL)
    {
    CContainerItem* pItem = (CContainerItem*)pDoc->GetNextItem(pos);
    if (pItem->m_rect.PtInRect(point))
    pItemHit = pItem;
    }
    return pItemHit;    // return top item at point
    

To implement selection

  1. Repeat steps 1 and 2 from the previous procedure to invoke the Add Member Function dialog box.

  2. Fill in the dialog box as follows:

    • In the Function Type box, type void.

    • In the Function Declaration box, type the following:

      SetSelection(CContainerItem* pItem)
      
    • In the Access area, select Public.

    • Click OK.

  3. In ContainerView.cpp, fill in the implementation code for SetSelection:

    // close in-place active item
    if (pItem == NULL || m_pSelection != pItem)
    {
    COleClientItem* pActiveItem
    = GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL && pActiveItem != pItem)
    pActiveItem->Close();
    }
    Invalidate();
    m_pSelection = pItem;
    
  4. Save the header and implementation files.

The above implementation is “lazy” in that it invalidates the entire client area of the view whenever the selection changes. In Container Step 2, this implementation is replaced with smarter invalidation.