Implement the Show Objects Command

Because embedded and linked objects look so much alike for most things a user might do with them in the container, it helps to have a way to differentiate the two. The Show Objects command allows the user to turn on and off extra graphical effects: solid lines drawn around embedded objects and dashed lines around linked objects, as shown in Figure 20-3 on page 952. The command itself, which is a toggle, should generally appear on an Edit menu but can appear elsewhere. In Patron, it is located on the Page menu, and some interaction between the frame and document objects (CPatronFrame::UpdateMenus in PATRON.CPP and CPatronDoc::ShowOrQueryObjectTypes in DOCUMENT.CPP) controls whether this menu item is checked. I'll leave it to you to follow the sequence of code for this.

Anyway, when you select this item, the frame routes the command down to CPage::ShowObjectTypes, which loops over all tenants in the page and calls CTenant::ShowObjectType. This function either includes or removes the flag TENANTSTATE_SHOWTYPE in the tenant's state flags:


void CTenant::ShowObjectType(BOOL fShow)
{
BOOL fWasShow;
DWORD dwState;
RECT rc;
HDC hDC;

fWasShow=(BOOL)(TENANTSTATE_SHOWTYPE & m_dwState);

dwState=m_dwState & ~TENANTSTATE_SHOWTYPE;
m_dwState=dwState œ ((fShow) ? TENANTSTATE_SHOWTYPE : 0);

/*
* If this wasn't previously shown, just add line;
* otherwise, repaint.
*/
if (!fWasShow && fShow)
{
RECTFROMRECTL(rc, m_rcl);
RectConvertMappings(&rc, NULL, TRUE);
OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);

hDC=GetDC(m_hWnd);
UIShowObject(&rc, hDC, (TENANTTYPE_LINKEDOBJECT==m_tType));
ReleaseDC(m_hWnd, hDC);
}

if (fWasShow && !fShow)
Repaint();

return;
}

If the state changes, the tenant immediately calls the helper function UIShowObject (in INOLE.DLL, INOLE\UIEFFECT.CPP), which calls the Windows function Rectangle with the appropriate pen type according to the type of object. A tenant with a linked object will have the type TENANTTYPE_LINKEDOBJECT, as used in the preceding code.

CTenant::Draw also calls UIShowObject whenever it repaints the object later. This works well for existing tenants, but when we create a new tenant on the page, we have to be sure it knows about the current Show Objects state. So CPage::TenantCreate now calls CTenant::ShowObjectType as a step in its tenant initialization process. The m_fShowTypes flag in CPages contains the current state of the menu item.

In addition, tenants will be loaded and unloaded as you move from page to page in a Patron document. Whenever Patron loads a tenant, it also tells it about the current state of Show Objects so it can immediately reflect the proper user interface.

When you test this feature in your own container, be sure to verify that newly created and loaded objects react appropriately to the current state of Show Objects. I forgot to do this when I first wrote Patron, but fortunately it's not one of those bugs that is hard to find and fix.