In-Place Interfaces for Containers

For a container to support in-place activation, it must implement the IOleInPlaceSite interface on its site object alongside IOleClientSite and IAdviseSink. The presence of IOleInPlaceSite tells embedded objects that its container is in-place capable. In addition, the container must also create a frame object that implements IOleInPlaceFrame. This object is separate from the site, and only one frame exists per container. Through IOleInPlaceFrame, an object merges its top-level user interface (such as menu items and toolbars) with the container's. If the container can provide separate document windows, as MDI applications can, each document must be an object that implements IOleInPlaceUIWindow. Through this interface, the object can display user interface tools inside document windows. The overall structure of an in-place–capable container is shown in Figure 22-1. If the container does not have separate document windows, IOleInPlaceUIWindow is not needed.

Figure 22-1.

The structure of an in-place–capable container.

All of these interfaces are derived from a common base interface named IOleWindow. It represents operations common to all parts of the container:


interface IOleWindow : IUnknown
{
HRESULT GetWindow(HWND *phwnd);
HRESULT ContextSensitiveHelp(BOOL fEnterMode);
};

GetWindow returns the handle of the window associated with whatever object is attached to this interface. A frame object would return the container's frame window, a document object would return the document window, and a site object would return whatever window is most closely associated with it, such as the document or some other client-area window.

ContextSensitiveHelp tells the object involved to enter or exit a mode in which mouse clicks, menu selections, and other user actions display help for that action instead of performing the action itself. The fEnterMode flag is set to TRUE when you should enter the mode, FALSE to exit the mode.

The other in-place interfaces are derived from IOleWindow as shown in the following code. IOleInPlaceFrame also derives from IOleInPlaceUIWindow:


interface IOleInPlaceSite : IOleWindow
{
HRESULT CanInPlaceActivate(void);
HRESULT OnInPlaceActivate(void);
HRESULT OnUIActivate(void);
HRESULT GetWindowContext(LPOLEINPLACEFRAME *ppFrame
, LPOLEINPLACEUIWINDOW *ppDoc, LPRECT prcPosRect
, LPRECT prcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo);
HRESULT Scroll(SIZE scrollExtent);
HRESULT OnUIDeactivate(BOOL fUndoable);
HRESULT OnInPlaceDeactivate(void);
HRESULT DiscardUndoState(void);
HRESULT DeactivateAndUndo(void);
HRESULT OnPosRectChange(LPCRECT prcPosRect);
};

interface IOleInPlaceUIWindow : IOleWindow
{
HRESULT GetBorder(LPRECT prcBorder);
HRESULT RequestBorderSpace(LPCBORDERWIDTHS pBW);
HRESULT SetBorderSpace(LPCBORDERWIDTHS pBW);
HRESULT SetActiveObject(LPOLEINPLACEACTIVEOBJECT pActiveObject
, LPCOLESTR pszObjName);
};

interface IOleInPlaceFrame : IOleInPlaceUIWindow)
{
HRESULT InsertMenus(HMENU hMenuShared
, LPOLEMENUGROUPWIDTHS lpMenuWidths);
HRESULT SetMenu(HMENU hMenuShared, HOLEMENU hOLEMenu
, HWND hWndActiveObj);
HRESULT RemoveMenus(HMENU hMenuShared);
HRESULT SetStatusText(LPCOLESTR pszStatusText);
HRESULT EnableModeless(BOOL fEnable);
HRESULT TranslateAccelerator(LPMSG pMsg, WORD wID);
};

In general, the members of IOleInPlaceSite represent the various events and requests that an in-place object sends to or requires of the container. IOleInPlaceSite::GetWindowContext is the function that the object uses to obtain its pointers to the other interfaces on the container's frame and document objects. Through IOleInPlaceUIWindow, the object can negotiate with the container for space in a document window for tools. It also provides the document with an IOleInPlaceActiveObject interface, which we'll see in the next section. Finally, an object can do everything with a document window that it can do with a frame window, so IOleInPlaceFrame is derived from IOleInPlaceUIWindow. The added member functions represent frame-specific user interface elements, such as the menu, the status line, and keyboard accelerators.

These, then, are the interfaces through which an in-place object accesses the services of an in-place container. Let's now look at the interfaces that a container uses to communicate with an in-place object.