Framework Support: Ambient Properties

 < Free Open Study > 



Now onto the other relevant feature provided by CComControlBase: the support for ambient properties. Here is the scoop. An ActiveX control container will have a GUI style all its own. For example, it might have a green background and use an 18-point, bold italic MS Sans Serif font. Currently, the ShapesControl begins life with a 12-point, Times New Roman font. Figure 14-32 illustrates the initial problem:


Figure 14-32: Two competing fonts.

If we, as the control designer, want to ensure that our control "looks and feels" like the container it is living in, we need to ask the container what its current look and feel is via ambient properties. Ambient properties are properties on the container that we might make use of in the logic of the control. By doing so, we allow our control to have the correct look and feel of its host. Not only is this a great way to avoid any ugly GUI clashes, but it also saves the user of your controls the bother of setting the properties by hand. The complete set of ambient methods defined by CComControlBase is defined in online help, but here are some of the more interesting ambient methods:

CComControlBase Ambient Method

Meaning in Life

GetAmbientAppearance()

Gets the container's APPEARANCE property.

GetAmbientBackColor()

Gets the container's BACKCOLOR property.

GetAmbientDisplayName()

Gets the container's DISPLAYNAME property.

GetAmbientFont()

Gets the container's FONT properties.

GetAmbientForeColor()

Gets the container's FORECOLOR property.

GetAmbientTextAlign()

Gets the container's TEXTALIGN property.

GetAmbientUserMode()

Gets the container's USERMODE property.

To illustrate the use of ambient methods, assume we want to ensure that the font used by ShapesControl was the same font as used by the container which is using it. We would need to change our current implementation of OnDraw() to obtain the container's HFONT via GetAmbientFont(), rather than our default font assembled in our constructor. Here is the updated OnDraw():

 // Drawing our text with the container's current font. HRESULT CShapesControl::OnDraw(ATL_DRAWINFO& di) { ...      // Draw the Caption stock property with the AMBIENT font.      // CComQIPtr<IFont, &IID_IFont> pFont(m_pFont);      // if (pFont != NULL)      // {      IFont* pFont;      GetAmbientFont(&pFont);      pFont->get_hFont(&newFont);      pFont->AddRefHfont(newFont);      oldFont = (HFONT) SelectObject(hdc, newFont);      // ...      SetTextAlign(hdc, TA_CENTER|TA_BASELINE);      SetBkMode(hdc, TRANSPARENT);      TextOut(hdc, (rc.left + rc.right)/2, (rc.top + rc.bottom)/2,                W2A(m_bstrCaption), m_bstrCaption.Length());      // Reset DC & clean up.      SelectObject(hdc, oldPen);      SelectObject(hdc, oldBrush);      SelectObject(hdc, oldFont);      pFont->ReleaseHfont(newFont);      pFont->Release();      return S_OK; } 

With this code change, we can now rest assured that when someone uses our control, our font is the same as the container's. Now, just because you can use ambient properties does not mean you have to. You may wish to have your control maintain a unique look and feel, and force the users of your control to set individual properties. However, when you do use ambient properties, you typically can save yourself and the control user a bit of work. Figure 14-33 shows the results of the above code changes.


Figure 14-33: One unified font.

Responding to Ambient Changes

The final note on using ambient properties is to realize that the values of a given ambient may change at any time. Just because the background color of a container may be purple today does not guarantee it will be tomorrow. To ensure that your control is informed when the container changes the value of a given ambient, your control may override the OnAmbientPropertyChange() method defined by IOleControlImpl<>. The default implementation of this method simply returns S_OK; however, you may test the incoming DISPID of the ambient property, and program accordingly. The DISPID constants for each ambient property are listed within <olectl.h>, and all have the "_AMBIENT_" infix. As an example, here is how we can discover that a container just changed the background color:

// Overriding OnAmbientPropertyChange() to respond to a change in the // ambient properties. STDMETHOD(OnAmbientPropertyChange)(DISPID dispid) {      if(dispid == DISPID_AMBIENT_BACKCOLOR)      {           ATLTRACE("The client changed the background color again...\n");           // Redraw, or whatever you need to do...      }      return S_OK; }



 < Free Open Study > 



Developer's Workshop to COM and ATL 3.0
Developers Workshop to COM and ATL 3.0
ISBN: 1556227043
EAN: 2147483647
Year: 2000
Pages: 171

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net