Cool Owner Draw Engine

Environment: Windows 95, Visual C++ 6 SP2

Here I present a class that helps writing Owner Draw Controls with basic – although
cute – text formatting capabilities.

The CCoolOwnerDrawEngine class is not a control class by its own, or even a CWnd
derived class. As a matter of fact, its objects work as aggregateable members of
Owner Draw Controls objects. By instantiating a CCoolOwnerDrawEngine as a member
object, such a control can rely on delegation to let the engine taking care of
the complex draw and format operations.

All we have to do is to redirect the control’s DrawItem method to the engine’s
DrawItem, providing it with the draw data (DRAWITEMSTRUCT), and the item’s
tagged text string.

The tagged item’s string describes both the text and the format, pretty much as
other tagged syntaxes do. Of course it’s not so powerful as HTML or Rich Text
Format. But, for the basic stuff, it’s pretty good.

Just to make it clear now, so I won’t disappoint you later: at this version, it’s
not possible to mix different font typefaces or font sizes. However, you still can
change the font color and any of its bold, italic or underline attributes.

For a glance, the text items in List 1, entered in the Cool Demo application,
will produce the visual output of Figure 1 – you must enter line by line.

List 1


  <0><-><j><#1010>Table<10>
  <#1000><0><|><j>Group A<5><|><j>Group B<10><|>
  <#1000><0><|><-><j>Col X<1><|><-><j>Col Y<2><|><-><j>Col Z<5><|><-><j>Col W<6><|><-><j>Col T<10><|>
  <0><|> <i0> <20> Thales <1><|><j><j><#5>10 <#><2><|><#1><b10><#><5><|>---<6><|>---<10><|>
  <0><|> <i0><i1><i2> <20> Ricardo <1><|><j><j><#5>100 <#><2><|><#1><b100><#><5><|>---<6><|>---<10><|>
  <0><|> <i0> <20> Pacheco <1><|><j><j><#5>20 <#><2><|><#1><b20><#><5><|>---<6><|>---<10><|>
  <0><|> <i0><i1> <20> Eloy <1><|><j><j><#5>50 <#><2><|><#1><b50><#><5><|>---<6><|>---<10><|>
  <0><|> <i2> <20> Marcio <1><|><j><j><#5>3 <#><2><|><#1><b3><#><5><|>---<6><|>---<10><|>
  <0><|><1><|><2><|><5><|><6><|><10><|>
  <0><-><|><1><-><|><2><-><|><5><-><|><6><-><|><10><|>
  <0><-><|><#1000><j><j> Total<#> <1><-><j><j><-><#5>11111 <#><2><|>

Figure 1

Figure 1

The Cool Demo application uses the CCoolDemoListBox, which is a
CCoolOwnerDrawEngine equipped
MFC Owner Draw CListBox.

Tags Overview

Here is a description of each existing tag.

<#n> – Select Style

This tag selects the style n for the subsequent drawing, where
n is a decimal identifier from 0 up to 4294967294. Each style has a
text color and a font attribute (either bold, italic, underline or any combination
of those). At this version (and probably this is the last one), it’s not possible
to change the font size, neither the font typeface.

Styles are independently configurable through the
CCoolOwnerDrawEngine::SetStyle member function.

I designed it to use externally configurable styles, rather than putting direct
tags to select font attributes and text colors, because I think styles are more
abstract. Therefore, you can change one style properties and all the affected
items will be changed automatically, without having to be reformatted and
reinserted in the control.

The selected style won’t persist from one item to other. Every time the engines
starts drawing a new item, it resets to the default style.

If a style doesn’t exist (it was not configured with
CCoolOwnerDrawEngine::SetStyle), the engine keeps using the current style.

You can use sparse style IDs (e.g. 1015 and 3). Internally, the engine keeps
them in an ordered CArray and uses binary search (which, for this particular purpose,
has better performance than the CMap, for both memory and speed).

<#> – Select Default Style

The default style is basically the style of the DC that’s provided for
CCoolOwnerDrawEngine::DrawItem.

<n> – Tab Stop

This tag aligns the current draw position with the tab stop n,
where n is a decimal identifier from 0 up to 4294967294.

Well, at first it’s a normal tab stop, but there’re three major differences:

– It has an ID. Therefore, you always know to which tab stop you’re going to advance
the drawing position. In an ID-less tab stop List Box, for instance, if the drawing
position is already beyond the desired tab stop (the previous text was too long),
it’ll advance to the next tab stop – if any -, and the item will show unaligned.

– Again, it has an ID. Another advantage of labeled tab stops is they affect only
the items that refer to them. Therefore, you might have different groups of items,
each one using a separate group of tab stops, and one will not get in the way of the other.

– The engine automatically resizes them, so the distance between any two different
tab stops is always enough to fit any text that happen to be between them. It makes
the tag useful to create simple tables.

<j> or <J> – Justification

This tag changes the justification alignment from left to center, and from center to
right, between two consecutive tab marks.

The engine stars aligning text to the left. If it finds this tag once, the subsequent
output will be aligned to the center, and, if it finds this tag twice or more, the subsequent
output will be aligned to the right.

For instance, List 2’s items will produce Figure 2’s output:

List 2


   Left <j> Center <j> Right
   Just Left
   <j> Just Center
   Left and... <j><j> Right

Figure 2

Figure 2

Since the output is once aligned to the right, extra Justification tags would have no effect.
However, do note that the Tab Stop tag will reset the alignment back to the left.

<in> or <In> – Icon Tag

Yes, you can attach a CImageList to the engine and instruct it to draw icons, using
this tag. Just give the icon index. By the way, there’s a member function to attach
the Image List.

<-> – Bottom Horizontal Border

This tag instructs the engine to draw a bottom border (a 1 pixel horizontal line)
between the current tab stops, using the current style color.

<|> – Vertical Border

This tag instructs the engine to draw a vertical border (a 1 pixel vertical line)
at the current drawing position.

<bw> or <Bw> – Bar

This tag instructs the engine to draw a bar w pixels wide.
It advances the current drawing position of w pixels to the right.
By the way, the bar is painted with the current style’s text color.

<<> – Less Than Character

This tag draws the ‘&lt’ character.

<>> – Greater Than Character

This tag draws the ‘&gt’ character.

Cool Demo Application Features

The demo application is just a dialog box with an edit box and a list box. The list box’s
stamina is a CCoolOwnerDrawEngine object. The edit box is just for entering tagged items strings
in the list. So, just type the text in the edit box and press <return>. You can
also delete an item by selecting it and pressing <del>. The dialog box is resizeable.

In the demo application, I use the following style ID pattern: biuC

Where b, i and u are the flags for font attribute bold, italic
and underline. These flags can be either 1 (on) or 0 (off). And C is the color
index, being 0 black, 1 light red, 2 light green, 3 light blue, 4 dark red, 5 dark
green, and 6 dark blue.

Therefore, such a tag as <#1003> will activate the blue bold font style.

But do note that you can program whatever combination you want.

I hope that some of you will find this engine useful and cute, and maybe you’ll
create some new Owner Draw Controls based on it. Perhaps, in the future, we’ll see
some of them here.

Downloads

Download demo application – 62 Kb
Download demo project – 19 Kb
Download source code – 6 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read