Implementing Activation by Using a Mouse Click

Container has a standard user interface for selecting and activating embedded objects. A single click selects an object; a double-click activates it. If the object is selected, the user can move or resize it, or in general, manipulate the object as a whole. If the object is activated in place, the user can edit it.

Implementing the OnLButtonDown handler so that a single click selects the embedded object follows this scheme:

  • Call HitTestItems to find the CContainerItem at the point where the mouse was clicked.

  • Set the selection to be this CContainerItem. Note that if no CContainerItem is located at the point where the mouse was clicked, nothing (NULL) is selected.

  • If something is selected, set up a tracker rectangle (CRectTracker) around the selected object. A CRectTracker object is short lived. It exists only during the time a mouse event is being handled, or as you will see later, during the time a window is being repainted. In the case of a single click, the CRectTracker paints a rectangle with resize handles around the object.

    If the item is clicked, CRectTracker::Track captures the mouse, enabling the user to drag the tracker rectangle around on the screen and to:

    • Resize the item if the click was on a handle.

    • Drag the item if the click was inside the rectangle.

    When the user releases the mouse button, CRectTracker updates its public member variable, m_rect, which represents the new size of the object.

  • If the user has resized the object (indicated by a value of TRUE being returned from CRectTracker::Track), update the m_rect of the CContainerItem object.

To implement the OnLButtonDown mouse handler

  1. Using WizardBar, select CContainerView from the Class list.

  2. Click the action arrow located on the right end of WizardBar.

  3. Click Add Windows Message Handler.

    The New Windows Message and Event Handlers dialog box appears.

  4. From the New Windows messages/events list box, select WM_LBUTTONDOWN.

  5. Click Add and Edit.

  6. Implement CContainerView::OnLButtonDown in ContainerView.cpp by replacing the //TODO comments with the following code.

    CContainerItem* pItemHit = HitTestItems(point);
    SetSelection(pItemHit);
    
    if (pItemHit != NULL)
    {
    CRectTracker tracker;
    SetupTracker(pItemHit, &tracker);
    
    UpdateWindow();
    if (tracker.Track(this, point))
    {  
    Invalidate();
    pItemHit->m_rect = tracker.m_rect;
    GetDocument()->SetModifiedFlag();
    }
    }
    

    Note   Your code should come before, but not replace, the call to the base class (CView) that WizardBar adds to the starter handler.

    For now, the entire client area of the view is invalidated. Smarter invalidation is implemented in Step 2.

The helper function SetupTracker sets up the styles of the tracker rectangle according to the state of the CContainerItem object, such as whether it has been selected.

To implement the helper function CContainerView::SetupTracker

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

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

  3. Fill in the Add Member Function dialog box as follows:

    • In the Function Type box, type void.

    • In the Function Declaration box, type:

    SetupTracker(CContainerItem* pItem, CRectTracker* pTracker)
    
    • In the Access area, select Public, and click OK.
  4. Implement the helper function with the following code:

    pTracker->m_rect = pItem->m_rect;
    
    if (pItem == m_pSelection)
    pTracker->m_nStyle |= CRectTracker::resizeInside;
    
    if (pItem->GetType() == OT_LINK)
    pTracker->m_nStyle |= CRectTracker::dottedLine;
    else
    pTracker->m_nStyle |= CRectTracker::solidLine;
    
    if (pItem->GetItemState() == COleClientItem::openState ||
    pItem->GetItemState() == COleClientItem::activeUIState)
    {
    pTracker->m_nStyle |= CRectTracker::hatchInside;
    }
    

The OnLButtonDblClick handler needs to be implemented so that if the user double-clicks, the object is opened (OLEIVERB_OPEN). How the object is opened depends on whether the server supports in-place editing. If the user presses CTRL while double-clicking, the Open verb of the object should be called. Otherwise, call the primary verb, the meaning of which is determined by the server.

To implement the OnLButtonDblClick mouse handler

  1. Using WizardBar, select CContainerView from the Class list.

  2. Click the action arrow located on the right end of WizardBar.

  3. Click Add Windows Message Handler.

    The New Windows Message and Event Handlers dialog box appears.

  4. From the New Windows messages/events list box, select WM_LBUTTONDBLCLK.

  5. Click Add and Edit.

  6. Implement CContainerView::OnLButtonDblClk in ContainerView.cpp by replacing the //TODO comment inside the starter handler code that WizardBar generates with the following code:

    OnLButtonDown(nFlags, point);
    
    if (m_pSelection != NULL)
    {
    m_pSelection->DoVerb(GetKeyState(VK_CONTROL) < 0 ?
    OLEIVERB_OPEN : OLEIVERB_PRIMARY, this);
    }
    

    Note   Your code should come before, but not replace, the call to the base class (CView) that WizardBar adds to the starter handler.