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.
<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><|>
The Cool Demo application uses the CCoolDemoListBox, which is a CCoolOwnerDrawEngine equipped MFC Owner Draw CListBox.
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:
Left <j> Center <j> Right Just Left <j> Just Center Left and... <j><j> Right
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 '<' character.<>> - Greater Than Character
This tag draws the '>' 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.
DownloadsDownload demo application - 62 Kb
Download demo project - 19 Kb
Download source code - 6 Kb