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);
}