List-View Backgrounds

The background of a List-View is a composition: a simple background to which may be applied various decorations.

Simple Backgrounds

Except where noted otherwise, simple backgrounds are supported even in the oldest known COMCTL32 versions. Broadly speaking, there are three types:

Background Colour

The simplest background that a List-View control can have is a solid colour. The control starts with COLOR_WINDOW as its background colour while enabled and COLOR_BTNFACE while disabled. The background colour that is to show while the control is enabled can be changed by sending the control an LVM_SETBKCOLOR message. A matching LVM_GETBKCOLOR message reports which colour is currently configured to be used when the background is next redrawn while the control is enabled. The background colour of a disabled List-View control is not subject to either message (but see below for a loophole in version 6.10).

Custom Background

Somewhat less simple is to have no background colour. This is represented programmatically as a special value, CLR_NONE, of background colour. The practical effect is that drawing the background is left to the control’s parent window. Whenever the control would paint a solid colour for its background, it instead sends its parent a WM_ERASEBKGND message. This has long been an opportunity to customise the background of a List-View control (but follow the link to learn of a complication to watch for).

Transparent Background

Version 6.10 introduces an extended style, LVS_EX_TRANSPARENTBKGND, which elaborates the case of having no background colour. Indeed, setting this style clears the background colour—and setting a background colour clears the style, not that any of this is mentioned in Microsoft’s documentation. If the control has this transparent-background style, then whenever it would draw a simple background, it first sends its parent a WM_PRINTCLIENT message (with PRF_ERASEBKGND as the drawing options). If this message returns zero, the control falls back to sending a WM_ERASEBKGND message, as above.

The code for setting the LVS_EX_TRANSPARENTBKGND style provides the only known way to give a disabled control a simple background other than the solid COLOR_BTNFACE. When LVM_SETBKCOLOR is sent to a disabled control to clear the background colour, it affects only the colour that is to show should the control be re-enabled. The current background colour is untouched. By contrast, when the LVS_EX_TRANSPARENTBKGND style is set while the control is disabled, it clears the current background colour. Microsoft may eventually see this as a coding error, and fix it. Meanwhile, it means that the parent of a List-View control can arrange to be sent WM_PRINTCLIENT or WM_ERASEBKGND messages, and thence give the control a custom background, even if the control is disabled.

Decorations

The simple background, which may already be visually elaborate, is then subject to various decorations:

Each of these has at least some variation, mostly configurable.

Background Image

The oldest decoration, supported since version 4.71, is to overlay the simple background, partially or completely, with an arbitrary image. Programmatically, the configuration is represented by an LVBKIMAGE structure, passed to and from the control via LVM_SETBKIMAGE and LVM_GETBKIMAGE messages.

Sources

The structure has always provided for specifying the background image in two ways:

That said, specification from a bitmap handle does not actually work until version 6.0. In earlier versions, the LVM_SETBKIMAGE message fails when given a bitmap handle, but that is not the end of it. A subsequent LVM_GETBKIMAGE will report the rejected bitmap handle as being in use for the background image. Worse, a second LVM_SETBKIMAGE to set another background image, whether from a bitmap handle or URL, will delete the rejected bitmap handle. Whatever caused this muddle, it is correct that the first LVM_SETBKIMAGE should fail: these versions of COMCTL32 have no code for getting the image drawn!

Perhaps the coding was abandoned in favour of the other case, with the image known from a URL. Right from version 4.71, COMCTL32 handles this case with just the very little code that is required for directing work that is all done externally. Interpreting the URL, loading the image and rendering the image are all done through a COM class. COMCTL32 is so little involved that it neither knows nor cares which types of image are supported. This is good separation, but it is at least unsatisfactory that in any standard Windows configuration, the server for this COM class is MSHTML. Yes, until version 6.0 finally works for setting a background image from a bitmap handle, applying a background image to a List-View control requires Internet Explorer, even if the list is generated without Internet access, or the URL is for a file on the local computer, or the user has installed some other web browser. (Strictly speaking, the last phrase is not quite true. Any manufacturer of an alternative web browser is presumably welcome to implement the relevant COM class, IImgCtx, and replace MSHTML for this purpose. Mind you, documentation is unsurprisingly scarce.)

Styles

There is a choice whether to draw the image just once in the List-View control’s client area or to fill the area by repeating the image horizontally and vertically (which process is called tiling).

Placement

The normal style has always provided for specifying where to place the one image. The placement is described in terms of offsets from the left and top (to the right and bottom) of the unscrolled client area, meaning here the client area as would be seen were the content scrolled fully to the left and top. Each offset is given as a percentage of the margins that would be available to the left and top of the image were the image placed at the bottom right of the unscrolled client area. Thus, 0, 50 and 100 place the image at the top or left, the centre and the bottom or right, respectively, of the unscrolled client area. Note that a background image in the normal style necessarily moves with the content when scrolled.

Like the normal style, the tiled style is available from version 4.71 onwards. However, the tiled style does not provide for placement until version 6.0. The default for versions 6.0 and higher is that a tiled image remains in place while the content is scrolled, i.e., the content scrolls over its background. The placement is again described by offsets, but these now measure how far, in pixels, the first tile is displaced to the left and top from the top left of the client area. Only if the ListviewScrollOver effect is disabled in the List-View registry settings does the image move with the content, and the offsets then apply from the top left of the unscrolled client area. Versions before 6.0 have none of this configurability: tiled background images behave as if the offsets are zero and the scroll-over effect is disabled.

Watermark

A different sort of background image, called a watermark, is supported in versions 6.0 and higher. The main difference visually is that the watermark is constrained to the bottom right corner of the client area, and remains there while scrolling. A significant difference programmatically is that the watermark can be set only from a bitmap handle.

Like the ordinary background image, the watermark is operated on through the LVM_GETBKIMAGE and LVM_SETBKIMAGE messages. A flag in the LVBKIMAGE structure, as given on input to these messages, indicates which type of image they operate on. A List-View control can have both a watermark and a background image simultaneously, but the background image has precedence.

When drawing the background, the watermark is skipped if any of the following is true:

The second of these, which is anyway irrelevant before version 6.10, is perhaps a coding error. The visual consequences can be very silly: if the List-View is managed such that a column is selected by clicking it and unselected by clicking it again, then repeated clicking of a column makes the watermark come and go.

Alpha-Blending

Version 6.10 introduces what is so far the only configurability for a watermark, namely to specify that the watermark be drawn with a very particular alpha-blending. In terms of the BLENDFUNCTION structure used for the GDI function GdiAlphaBlend, the SourceConstantAlpha is 0xFF and the AlphaFormat is AC_SRC_ALPHA.

Selected Column

A new feature for version 6.0 is that one column may be selected for a distinguished visual appearance when the list is in Details view. The selected column is represented in LVM_GETSELECTEDCOLUMN and LVM_SETSELECTEDCOLUMN messages by a 0-based index, with -1 meaning that no column is selected. Because a typical use for the selected column is to show which column provides the keys for sorting the list, the selected column is also referred to as the sort column, e.g., in documentation of the IVisualProperties interface.

One way that the selected column may be distinguished is by decorating its background. There are two types of decoration. In one, the selected column has the same background as it would have if not selected, but with a slight modification of colour. In the other type of decoration, the selected column is filled with a solid colour.

Saturation

If a background image is set and has successfully loaded, then the selected column is decorated only if the background image is tiled. Where the pixels in the background image also lie in the selected column, their red, green and blue components are each increased by 10 percent, if possible, else to the maximum of 255.

If the List-View has the LVS_EX_TRANSPARENTBKGND style (in versions 6.10 and higher), this same saturation is applied to the simple background. As noted above, no watermark is drawn in this case.

Solid Sort-Column Color

With neither a successfully loaded background image nor the LVS_EX_TRANSPARENTBKGND style, the background in the selected column is set to a solid colour which is ordinarily chosen by COMCTL32. Because the remaining cases allow that the List-View can have a custom background, a watermark, or both, COMCTL32’s choice of solid colour for the selected column may have nothing to do with the background that the column would have if not selected, and may not join well with the background in unselected columns on either side. The visual effect can be especially silly when the selected column overlaps a watermark but does not completely obscure it.

Starting with version 6.10, the sort-column color is configurable. List-View controls in these versions are COM objects, implementing various COM interfaces which can be queried by sending an undocumented message, here named LVM_QUERYINTERFACE (Microsoft’s name not being known). One of these interfaces is IVisualProperties, whose GetColor and SetColor methods operate on any of four types of colour. One of these is the sort-column colour. Set it to something other than CLR_DEFAULT and it is what COMCTL32 will use (even while the control is disabled).

Otherwise (and always in version 6.0), COMCTL32 calculates from the current background colour. If this is black, the colour for the selected column is grey (meaning that red, blue and green are all 128). Except if the current background colour is black, the following steps are taken for each of the red, blue and green components of the current background colour to produce the corresponding component of the selected-column colour:

A colour is considered bright if all its red, blue and green components exceed 240. Note that the colour for the selected column may be brighter than the current background colour, or darker. It may be a coding oversight, but the programmatic value CLR_NONE that stands for having no background colour is interpreted for these calculations as white.

Themed Column Edges

One more decoration is applied in version 6.10 and higher, if the List-View is in Details view and has a custom theme. This decoration lies outside the present scope of this article.