ListView ownerdraw column headers

C

campk

I have a question for anyone who might be able to help... I am in the
process of building a custom listview, and am dealing with sorting, and
wanting to use the asc/desc sort indicators in the column header... i
have tried setting the parent's SmallImageList property and using those
images as sort order indicators, but the ListView items also try to use
those images, which screw up the way the ListView renders in some
situations.

Drawing the column header is an easy enough way around this, but I am
running into trouble with dealing with the mouse over behaviour. I
attempt to access the MousePosition, and then test if the bounds of the
columnheader contain that point. This works just fine - however...

When you are moving from one column to another, from right to left
(this is the important part), the rightmost column (the one you just
came from) still evaluates the
e.Bounds.Contains(this.PoiintToClient(Control.MousePosition))
expression to 'True'...

Additionally, in the same Right to left motion, the columns' "hover"
seems to be off by one (delayed) as you mouse over...
So, if we have 4 columns {0,1,2,3} and we are moving Right to Left,
without leaving the vertical bounds of the ListView's column header...
If the mouse cursor is over column...

[3] --> [3] is "highlighted"
[2] --> [3] is "highlighted"
[1] --> [3] and [2] are "highlighted"
[0] --> [3] [2] [1] are all highlighted.


I don't understand entirely why this might be. Since it doesn't
exhibit any of this behaviour at all when you move over the columns
from Left to Right, I am guessing that the column header might
"virtually" extend all the way to the left, or something like that...
Is there a better way to determine whether or not the mouse is hovering
over the specific bounds of the column header?

Find the ColumnHeader OwnerDraw code below...

Thanks for any help you might be able to provide...


protected override void
OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e) {
e.DrawDefault = false;

Color normal = SystemColors.Control;
Color hover = SystemColors.ButtonHighlight;
Color hoverPress = Color.LightGreen;
Color normalBorder = SystemColors.InactiveBorder;
Color hoverBorder = Color.FromArgb(227,145,79);
Color verticalDiv = SystemColors.Highlight;

RectangleF txtRect = RectangleF.Empty;

Point mPoint = this.PointToClient(Control.MousePosition);
bool MouseHover = e.Bounds.Contains(mPoint);

Brush bgBrush;

if (MouseHover)
bgBrush = new SolidBrush(hover);
else
bgBrush = new SolidBrush(normal);

e.Graphics.FillRectangle(bgBrush, e.Bounds);

SizeF txtSize = e.Graphics.MeasureString(e.Header.Text, this.Font);

switch (e.Header.TextAlign) {
case HorizontalAlignment.Left:
txtRect = new RectangleF(
4 + e.Bounds.Left,
(e.Bounds.Height - txtSize.Height) / 2,
txtSize.Width,
txtSize.Height
);
break;
case HorizontalAlignment.Center:
txtRect = new RectangleF(
(e.Bounds.Width - txtSize.Width) / 2 + e.Bounds.Left,
(e.Bounds.Height - txtSize.Height) / 2,
txtSize.Width,
txtSize.Height
);
break;
case HorizontalAlignment.Right:
txtRect = new RectangleF(
(e.Bounds.Width - (e.Bounds.Width - txtSize.Width)) +
e.Bounds.Left,
(e.Bounds.Height - txtSize.Height) / 2,
txtSize.Width,
txtSize.Height
);
break;
}

e.Graphics.DrawString(e.Header.Text, this.Font, Brushes.Black,
txtRect);


Brush divBrush = new SolidBrush(SystemColors.Highlight);
Brush borderBrush = new SolidBrush(normalBorder);

//Draw the vertical divider if we aren't hovering
if (MouseHover)
borderBrush = new SolidBrush(hoverBorder);
if (!MouseHover)
e.Graphics.DrawLine(new Pen(divBrush, 1.25F), e.Bounds.Right - 2,
e.Bounds.Top + (0.20F * e.Bounds.Height), e.Bounds.Right - 2,
e.Bounds.Bottom - e.Bounds.Height / 3);

// draw bottom border
e.Graphics.DrawLine(new Pen(borderBrush, 2.0F), e.Bounds.Left,
e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);



base.OnDrawColumnHeader(e);
}
 
J

Jared

You may find it easiest to prep text with symbol '>' and '<' for asc.

i.e. column.headertext = "<" + column.headertext

actually looks quite good.
 
C

Claes Bergefall

campk said:
I have a question for anyone who might be able to help... I am in the
process of building a custom listview, and am dealing with sorting, and
wanting to use the asc/desc sort indicators in the column header... i
have tried setting the parent's SmallImageList property and using those
images as sort order indicators, but the ListView items also try to use
those images, which screw up the way the ListView renders in some
situations.

In what situations and how does it screw up the rendering? Having them in
the imagelist is by far the easiest way to accomplish this. Just make sure
you don't assign a sorting arrow index to a listview item. Should be
trivial..

/claes
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top