This document describes palette management for ActiveX® objects, specifically ActiveX Controls and Active Document objects. The palette management rules described herein allow multiple controls inside a form or an HTML page to display correctly, while still leaving enough flexibility to allow a control to demand palette control. In general, containers are responsible for palette management, and contained objects (for example, controls) should only realize their palettes in the background.
This section describes how ActiveX controls and containers should manage the palette.
Because there may be more than one control on a page or form, it is up to the container to choose a common palette, and every control should realize its palette in the background. Anything else would result in chaos as each control realized its palette while painting. The display would flicker madly and most controls would look awful.
Ultimately it is the container's responsibility to choose the common palette. Some containers might use the UI active object's palette; others might compute the palette at run-time.
The container makes its palette available to contained controls through an ambient property: DISPID_AMBIENT_PALETTE. This property is defined as part of the OLE Controls 96 specification and is implemented by Microsoft® Internet Explorer. Controls can receive the value of this ambient initially by implementing IOleObject::SetClientSite or IObjectWithSite::SetSite, then querying the container client site for IDispatch, and finally calling IDispatch::Invoke on the property to obtain its value. Afterwards, controls can receive notification of changes to this property by implementing IOleControl::OnAmbientPropertyChange.
Containers should realize the ambient palette before calling this function or IViewObject2::Draw. Older containers that do not implement this property will typically iterate through their controls, forwarding the WM_QUERYNEWPALETTE message until a control returns TRUE (indicating it has realized a palette). Containers that implement DISPID_AMBIENT_PALETTE should never send WM_QUERYNEWPALETTE to their controls.
Palette-aware controls that need to be notified of changes to the ambient palette should implement IOleControl::OnAmbientPropertyChange and handle DISPID_AMBIENT_PALETTE and DISPID_UNKNOWN. DISPID_UNKNOWN is sent when the values of more than one ambient property change. When this happens, controls should explicitly check for a changed palette.
Older containers that do not define an ambient palette will send WM_PALETTECHANGED messages. Controls are encouraged to handle this message as well.
Note that controls can still realize a different palette (in the background). The ambient palette property is useful only if a control needs to optimize its display to the palette of the container. If this is not necessary, the control should ignore the ambient palette property.
All palette-aware controls should implement IViewObject2::GetColorSet if they want to specify a palette preference. Containers can use the return value to determine if a control is palette-aware. Containers can also use the color information returned to choose what palette to realize.
E_NOTIMPL | The control is not palette-aware. |
S_FALSE | The control is palette-aware but does not have a palette at this time. |
S_OK | The control is palette-aware and has returned its palette to the container. |
It should be noted that the container does not have to call IViewObject2::GetColorSet. The container can determine its palette independently of its controls.
Older OLE guidelines allowed the UI active object to realize its own palette in the foreground. Revised guidelines disallow this practice.
Controls should realize their palette in the foreground only when receiving a WM_QUERYNEWPALETTE message. In every other situation, the control must realize its palette in the background. Containers that implement DISPID_AMBIENT_PALETTE will never send this message.
Summary
The following sections describe issues related to palette management by OLE document objects. In general, the palette management scheme for document objects is the same as the scheme used for controls, except that document objects do not receive ambient properties from their container.
Palette management for document objects is similar to palette management for controls. The following are the responsibilities of the document object:
The only difference between the responsibilities of controls and document objects is that document objects do not handle the DISPID_AMBIENT_PALETTE property.
In the most common cases, a document object container will activate only one document object at a time. In such a situation, it is acceptable that the activated document object should have complete control over the palette, which includes managing palette issues for any controls or content within that document.
The document object container in this case has nothing to do with palettes and need not be concerned with palette issues. It should leave palette handling up to the document objectin other words, it should forward all Microsoft Windows® palette management messages on to the document object.
The following is example code for the window procedure of the document object host.
case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: { HWND hwnd; IOleWindow *pOleWindow; if (pDocObj && SUCCEEDED(pDocObj->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow))) { LRESULT lres = 0; if (SUCCEEDED(pOleWindow->GetWindow(&hwnd))) { lres = SendMessage(hwnd, uMsg, wParam, lParam); } pOleWindow->Release(); return lres; } break; }
In rare cases, a document object container might be able to activate more than one document object at a time within multiple container frames. While this user interface is discouraged at this time, it can be achieved.
However, no palette-management solution exists for this scenario because there is currently no protocol for communicating palettes between a document object and its container. Therefore, the container cannot create a palette suitable to all document objects that it has activated.
Because of this, the activated document object in the foreground has control over the palette and should use foreground palette rendering. Other activated document objects in the background use background palette rendering. The document object container itself does not participate in palette management at all.