IOleControl and IOleControlSite

These interfaces extend the communication that usually occurs between a container and an object in OLE Documents for the purpose of handling control mnemonics, ambient properties, and extended controls:


interface IOleControl : IUnknown
{
HRESULT GetControlInfo(CONTROLINFO *pCtrlInfo);
HRESULT OnMnemonic(LPMSG pMsg);
HRESULT OnAmbientPropertyChange(DISPID dispID);
HRESULT FreezeEvents(BOOL fFreeze);
}

interface IOleControlSite : public IUnknown
{
HRESULT OnControlInfoChanged(void);
HRESULT LockInPlaceActive(BOOL fLock);
HRESULT GetExtendedControl(IDispatch **pIDispatch);
HRESULT TransformCoords(POINTL *ptlHimetric
, POINTF *ptlContainer, DWORD dwFlags);
HRESULT TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers);
HRESULT OnFocus(BOOL fGotFocus);
HRESULT ShowPropertyFrame(void);
}

The GetControlInfo and OnMnemonic members of IOleControl and the OnControlInfoChanged, TranslateAccelerator, and OnFocus members of IOleControlSite are described later in this chapter under "Keyboard Handling, Mnemonics, and ISimpleFrameSite." We can mention that IOleControlSite::OnFocus notifies a site when its control either gains or loses the focus. IOleControlSite::GetExtendedControl gives a control a way to access a container's extended control and retrieve any properties it might have. (We'll cover this in more detail in the following section.)

That leaves only a few other methods to discuss briefly here. First is IOleControl::OnAmbientPropertyChange, which a container calls whenever it changes an ambient property. It passes the dispID of the property that changed (see the section "Standard dispIDs for Controls" later in this chapter for predefined dispIDs) or DISPID_UNKNOWN to indicate that multiple properties changed. In response, a control retrieves the new property (or properties) as necessary and updates itself. This notification mechanism doesn't involve connection points because there is little need for extensibility. Although control properties and events vary widely, the set of ambient properties is relatively small and varies little from container to container. And whereas a container needs notifications from many objects, a control needs notifications only from a single container. There's no need for overkill simply for ambient properties.

Whenever a control should display its property pages (for example, in response to OLEIVERB_PROPERTIES), it should first call IOleControlSite::ShowPropertyFrame. The reason for this is that the container might have an extended control built around the control that received the verb. Calling ShowPropertyFrame allows the container to include any of its own property pages along with those the control specifies through ISpecifyPropertyPages::GetPages. If the container returns an error from ShowPropertyFrame, however, the control should proceed to show its own property pages—do not expect the container to always implement the function.

IOleControl::FreezeEvents allows the container to turn off (freeze) and turn on (thaw) a control's events. When the events are frozen, the control will not fire them—it might queue them or discard them, but it won't fire them. The choice is up to the control itself.

The other two members of IOleControlSiteLockInPlaceActive and TransformCoords—generally have to do with events as well. LockInPlaceActive(TRUE) tells the container that a control wants to stay in the active state until LockInPlaceActive(FALSE) is called. This is primarily to prevent crashing problems when an in-place window is destroyed and messages are still coming to that window. A control will often call LockInPlaceActive before and after an event is fired if destroying the in-place window would cause problems.

TransformCoords handles the presentation of a uniform coordinate system to the container through all events, methods, and properties while allowing controls to choose whichever coordinate system they want. For example, if a MouseDown event is fired, the container should receive the coordinates in a system it understands instead of in whatever system the control is using. Windows programmers have always taken this for granted—any message or event coming from Windows had coordinates expressed in client-area units. But because events can come from any number of vastly different controls, all controls must take whatever coordinates they have in HIMETRIC and send them to IOleControlSite::TransformCoords to convert them to the container's units. Those units are then sent with the event itself.