Implementing Caption Drawing Behavior

Now that all the required properties are in place, you can implement caption drawing. To draw the caption text, you must modify the CCircCtrl::OnDraw function in CIRCCTL.CPP.

The drawing code changes require that the device context passed to the OnDraw function be modified to reflect the background and foreground colors, stored as values of the BackColor and ForeColor properties, respectively. The font contained in the Font property must also be selected into the device context before the caption text can be drawn. The InternalGetText function retrieves the caption text drawn using the ExtTextOut function.

To implement caption drawing in the Circle control

The code added in the first block in the preceding example starts by declaring three new local variables. The pOldFont variable holds the old font from the device context. The tm variable holds text metric information about the font used to draw the text. The strCaption variable is the text to be drawn. It is initialized by calling the InternalGetText function to get the value of the Caption property. The InternalGetText function should be used instead of the GetText function whenever the returned text will not be modified. This is because GetText returns a string of type BSTR, containing a copy of the caption text, that must be freed.

    CFont* pOldFont;
    TEXTMETRIC tm;
    const CString& strCaption = InternalGetText();

The text color of the device context is set to the current value of the ForeColor property. The OLE_COLOR value returned by the GetForeColor function is translated by the TranslateColor function into a COLORREF value. This value is then passed as a parameter to the SetTextColor function to set the text color in the device context. OLE_COLOR values must be translated by the TranslateColor function whenever a COLORREF value is required.

    pdc->SetTextColor(TranslateColor(GetForeColor()));

The background mode of the text is made transparent in the device context by calling the SetBkMode function.

    pdc->SetBkMode(TRANSPARENT);

In the second block of code added in the previous example, calling the SelectStockFont function (defined in the COleControl base class) selects the current font, stored as the value of the stock Font property, into the device context. The font that used to be selected into the device context is kept in the pOldFont variable to be selected back into the device context later.

    pOldFont = SelectStockFont(pdc);

The text metrics for the font in the device context are retrieved by calling the GetTextMetrics function and are used to center the text vertically. The text alignment of the device context is set using the SetTextAlign function, and this centers the text horizontally. The text is drawn by calling the ExtTextOut function. The text is clipped to the bounding rectangle of the circle or ellipse (which may be different from the bounding rectangle of the control if the CircleShape property is TRUE) and centered both horizontally and vertically. Note that any function affecting the device context passed to the OnDraw function must be among the subset of functions that are allowed for both metafile device contexts and standard device contexts.

    pdc->GetTextMetrics(&tm);
    pdc->SetTextAlign(TA_CENTER | TA_TOP);
    pdc->ExtTextOut((rc.left + rc.right) / 2, (rc.top + rc.bottom - tm.tmHeight) / 2,
        ETO_CLIPPED, rc, strCaption, strCaption.GetLength(), NULL);

The font that used to be selected in the device context is replaced using the SelectObject function.

    pdc->SelectObject(pOldFont);