Yes, I draw my own images and put them in an imagelist. Then assign the
imagelist to the ListView.SmallImageList
There doesn't seem to be a .NET way to right align the image though, so
you'll have to use some P/Invoke
1. Use LVM_GETHEADER to get a handle to the column header control
2. Use HDM_SETITEM to set a new format flag (the fmt member in the HDITEM
structure)) that includes HDF_BITMAP_ON_RIGHT
You should only need to do this once upon startup
Here's the code I use to create the image list with the arrows in it. It's
in VB.NET though, but should be easy to understand:
Private Function CreateSortingImages() As ImageList
Dim imgList As New ImageList
Dim imgUpArrow As New Bitmap(16, 16,
Drawing.Imaging.PixelFormat.Format32bppArgb)
Dim imgDownArrow As New Bitmap(16, 16,
Drawing.Imaging.PixelFormat.Format32bppArgb)
imgList.ImageSize = New Size(16, 16)
imgList.ColorDepth = ColorDepth.Depth8Bit
imgList.TransparentColor = SystemColors.Desktop
Dim penLeft As New Pen(SystemColors.ControlDark, 1)
Dim penRight As New Pen(SystemColors.ControlLightLight, 1)
Dim brushBackground As New SolidBrush(SystemColors.Control)
Dim brushTransparent As New SolidBrush(SystemColors.Desktop)
Dim dc As Graphics
Dim point1 As Point
Dim point2 As Point
Dim point3 As Point
Dim point4 As Point
Dim point5 As Point
Dim point6 As Point
' Up arrow image - Index 0
dc = Graphics.FromImage(imgUpArrow)
dc.FillRectangle(brushTransparent, 0, 0, 16, 16)
point1 = New Point(7, 5)
point2 = New Point(8, 5)
point3 = New Point(11, 10)
point4 = New Point(11, 11)
point5 = New Point(4, 11)
point6 = New Point(4, 10)
dc.FillPolygon(brushBackground, New Point() {point1, point2, point3,
point4, point5, point6})
dc.DrawLine(penLeft, point6, point1)
dc.DrawLine(penRight, point2, point3)
dc.DrawLine(penRight, point4, point5)
imgList.Images.Add(imgUpArrow, SystemColors.Desktop)
' Down arrow image - Index 1
dc = Graphics.FromImage(imgDownArrow)
dc.FillRectangle(brushTransparent, 0, 0, 16, 16)
point1 = New Point(4, 4)
point2 = New Point(11, 4)
point3 = New Point(11, 5)
point4 = New Point(8, 10)
point5 = New Point(7, 10)
point6 = New Point(4, 5)
dc.FillPolygon(brushBackground, New Point() {point1, point2, point3,
point4, point5, point6})
dc.DrawLine(penLeft, point1, point2)
dc.DrawLine(penRight, point2, point4)
dc.DrawLine(penLeft, point5, point6)
imgList.Images.Add(imgDownArrow, SystemColors.Desktop)
Return imgList
End Function
/claes
> This happens because I am using Graphics to draw the triangle after I
> compute where to put it.
[quoted text clipped - 28 lines]
>>> alwasy work ok (sometimes when one char is left displayed the column
>>> text variable is containing zero chars).
Walter Sobchak - 18 Jan 2008 14:32 GMT
Thanks for your help.
So far I used this code to initialize the image list:
IntPtr hc;
// Get a handle to the header control.
hc = Win32.SendMessage(aControl.Handle, Win32.LVM_GETHEADER, (UInt32)0,
(UInt32)0);
// Add the image list to the header control.
Win32.SendMessage(hc, Win32.HDM_SETIMAGELIST, (UInt32)0,
(UInt32)CreateSortingImages().Handle);
Now when I want to display an arrow I tried to use something like
lv.Columns[0].ImageIndex = 1;
But it doesn't work.
Can you show me your code for changing imageindex?
I don't know what I am doing wrong.
> Yes, I draw my own images and put them in an imagelist. Then assign the
> imagelist to the ListView.SmallImageList
[quoted text clipped - 100 lines]
>>>> alwasy work ok (sometimes when one char is left displayed the column
>>>> text variable is containing zero chars).
Walter Sobchak - 18 Jan 2008 14:49 GMT
Now I tried to set the imagelist to the listview instead of the column
header and it works. The problem is that I already have one imagelist
associated with the listview.
So I should be able to associate 2 image lists to listview or associate
one to the column header..
> Thanks for your help.
> So far I used this code to initialize the image list:
[quoted text clipped - 15 lines]
> Can you show me your code for changing imageindex?
> I don't know what I am doing wrong.
Walter Sobchak - 18 Jan 2008 15:37 GMT
> Thanks for your help.
> So far I used this code to initialize the image list:
[quoted text clipped - 8 lines]
> Win32.SendMessage(hc, Win32.HDM_SETIMAGELIST, (UInt32)0,
> (UInt32)CreateSortingImages().Handle);
Setting the imagelist to column header is the right thing to do.
The problem was that I didn't set the imageindex correctly.
This works:
for (int i = 0; i < lv.Columns.Count; i++)
{
// Use the LVM_SETCOLUMN message to set the
column's image index.
Win32.LVCOLUMN col;
// col.mask: include LVCF_FMT | LVCF_IMAGE
col.mask = Win32.LVCF_FMT | Win32.LVCF_IMAGE;
// LVCFMT_IMAGE
//col.fmt = Win32.LVCFMT_IMAGE;
col.fmt = Win32.LVCFMT_IMAGE |
Win32.HDF_BITMAP_ON_RIGHT;
// The image to use from the image list.
if (ColumnToSort == i)
{
if (OrderOfSort == SortOrder.Ascending)
{
col.iImage = 0;
}
else
{
col.iImage = 1;
}
}
else
col.iImage = -1;
// Initialize the rest to zero.
col.pszText = (IntPtr)0;
col.cchTextMax = 0;
col.cx = 0;
col.iSubItem = 0;
col.iOrder = 0;
// Send the LVM_SETCOLUMN message.
// The column that we are assigning the image to is
defined in the third parameter.
Win32.SendMessage(lv.Handle, Win32.LVM_SETCOLUMN,
(UInt32)i, ref col);
}
Claes, thank you very much for your help.
Claes Bergefall - 21 Jan 2008 10:19 GMT
Using the ColumnHeader.ImageIndex property apparently doesn't work as you
found out. The code I have was written for 1.1 where that property doesn't
exist, so it uses the exact same technique as you've shown below. Since that
still works I haven't bothered investigating why the .NET property doesn't
behave as expected (maybe someday I'll be bored enough to find out why :-)).
Anyway, glad to see you have a working solution.
/claes
>> Thanks for your help.
>> So far I used this code to initialize the image list:
[quoted text clipped - 57 lines]
>
> Claes, thank you very much for your help.