Search code examples
delphivirtualtreeviewtvirtualstringtree

TVirtualStringTree - How to draw on header columns without using OwnerDraw?


I would like to draw on the TVirtualStringTree header columns but I have a problem. I need the tree columns to use it's "default draw" and add my own graphics on it.

If I use hoOwnerDraw with Header.Options and use OnHeaderDraw, I need to completely draw the columns myself (which is no good).

There is the OnAdvancedHeaderDraw which seems to be what I hope for (see example):

Used when owner draw is enabled for the header and a column is set to owner draw mode. But only if OnHeaderDrawQueryElements returns at least one element to be drawn by the application.

If I use OnAdvancedHeaderDraw (I must also use OnHeaderDrawQueryElements) I get what I want, but I need to substitute at-least one element in the OnHeaderDrawQueryElements (i.e. hpeBackground/hpeDropMark/hpeHeaderGlyph/hpeSortGlyph/hpeText) and draw it myself in the OnAdvancedHeaderDraw event.

When for example I return the hpeSortGlyph element, returning ShowSortGlyph := True in the var PaintInfo: THeaderPaintInfo of the OnAdvancedHeaderDraw does not make any difference, and the sort glyph is not painted, which means I must paint it myself. Since there is no DefaultDrawSortGlyph I need to reinvent to weal, so to speak, and copy big parts of code from VT source just to paint the sort glyph :/

I use/need all the elements in the columns, I just want to add my own graphics on top of the default column graphics (a drop down arrow) without substituting one of them. How can I avoid this behavior? Is it possible to draw on top of the exists column without patching the source?

I hope my question is clear.


Solution

  • Since VT 7.0 you can query and paint for the hpeOverlay header paint element.


    For older versions:

    There is no easy way to paint over the fully rendered header column at this time (VT 6.7.0). But a simple modification of the source code might be e.g. extending THeaderPaintElements flag set by for example hpeOverlay, and line:

    ActualElements := RequestedElements * [hpeHeaderGlyph, hpeSortGlyph, hpeDropMark,
      hpeText];
    

    change to:

    ActualElements := RequestedElements * [hpeHeaderGlyph, hpeSortGlyph, hpeDropMark,
      hpeText, hpeOverlay];
    

    Then you can query just for the hpeOverlay element in the OnHeaderDrawQueryElements event, all the elements will be painted by default and the OnAdvancedHeaderDraw event will be fired just for this new element.

    The main contributor Joachim Marder filed an enhancement issue to add this kind of extension, which has been commited to the repository, so the current version of VT supports the proposed enhancement.