How to: Implement Tracking in Your Code

 

The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.

The latest version of this topic can be found at How to: Implement Tracking in Your Code.

To track an OLE item, you must handle certain events related to the item, such as clicking the item or updating the view of the document. In all cases, it is sufficient to declare a temporary CRectTracker object and manipulate the item by means of this object.

When a user selects an item or inserts an object with a menu command, you must initialize the tracker with the proper styles to represent the state of the OLE item. The following table outlines the conventions used by the OCLIENT sample. For more information on these styles, see CRectTracker.

Container Styles and States of the OLE Item

Style displayed State of OLE item
Dotted border Item is linked
Solid border Item is embedded in your document
Resize handles Item is currently selected
Hatched border Item is currently in-place active
Hatching pattern overlays item Item's server is open

You can handle this initialization easily using a procedure that checks the state of the OLE item and sets the appropriate styles. The SetupTracker function found in the OCLIENT sample demonstrates tracker initialization. The parameters for this function are the address of the tracker, pTracker; a pointer to the client item that is related to the tracker, pItem; and a pointer to a rectangle, pTrueRect. For a more complete example of this function, see the MFC OLE sample OCLIENT.

The SetupTracker code example presents a single function; lines of the function are interspersed with discussion of the function's features:

void CMainView::SetupTracker(CRectTracker* pTracker, CRectItem* pItem,
   CRect* pTrueRect)

The tracker is initialized by setting the minimum size and clearing the style of the tracker.

   // set minimum size for our OLE items
   pTracker->m_sizeMin.cx = 8;
   pTracker->m_sizeMin.cy = 8;

   pTracker->m_nStyle = 0;

The following lines check to see whether the item is currently selected and whether the item is linked to the document or embedded in it. Resize handles located on the inside of the border are added to the style, indicating that the item is currently selected. If the item is linked to your document, the dotted border style is used. A solid border is used if the item is embedded.

   // setup resize handles if item is selected
   if (pItem == m_pSelection)
      pTracker->m_nStyle |= CRectTracker::resizeInside;

   // put correct border depending on item type
   if (pItem->GetType() == OT_LINK)
      pTracker->m_nStyle |= CRectTracker::dottedLine;
   else
      pTracker->m_nStyle |= CRectTracker::solidLine;

The following code overlays the item with a hatched pattern if the item is currently open.

   // put hatching over the item if it is currently open
   if (pItem->GetItemState() == COleClientItem::openState ||
      pItem->GetItemState() == COleClientItem::activeUIState)
   {
      pTracker->m_nStyle |= CRectTracker::hatchInside;
   }

You can then call this function whenever the tracker has to be displayed. For example, call this function from the OnDraw function of your view class. This updates the tracker's appearance whenever the view is repainted. For a complete example, see the CMainView::OnDraw function of the MFC OLE sample OCLIENT.

In your application, events that require tracker code, such as resizing, moving, or hit detecting, will occur. These actions usually indicate that an attempt is being made to grab or move the item. In these cases, you will need to decide what was grabbed: a resize handle or a portion of the border between resize handles. The OnLButtonDown message handler is a good place to test the position of the mouse in relation to the item. Make a call to CRectTracker::HitTest. If the test returns something besides CRectTracker::hitOutside, the item is being resized or moved. Therefore, you should make a call to the Track member function. See the CMainView::OnLButtonDown function located in the MFC OLE sample OCLIENT for a complete example.

The CRectTracker class provides several different cursor shapes used to indicate whether a move, resize, or drag operation is taking place. To handle this event, check to see whether the item currently under the mouse is selected. If it is, make a call to CRectTracker::SetCursor, or call the default handler. The following example is from the MFC OLE sample OCLIENT:

BOOL CMainView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
   if (pWnd == this && m_pSelection != NULL)
   {
      // give the tracker for the selection a chance
      CRectTracker tracker;
      SetupTracker(&tracker, m_pSelection);
      if (tracker.SetCursor(this, nHitTest))
         return TRUE;
   }
   return CScrollView::OnSetCursor(pWnd, nHitTest, message);
}

See Also

Trackers: Implementing Trackers in Your OLE Application