Я удивлен ответом Джеффри Тана в этом посте. Его решение не может работать, так как код пытается нарисовать за пределами клиентской области управления заголовком. hDC
, используемый в пользовательском чертеже (и, следовательно, в чертеже владельца), предназначен для клиентской области элемента управления и поэтому не может использоваться для рисования в не клиентской области. Область справа от самого правого столбца в элементе управления заголовком находится за пределами клиентской области. Поэтому вам нужно другое решение.
Возможные решения
- Высокотехнологичный и частично эффективный
Вы можете включить рисование вне клиентской области, используя GetDC()
WinAPI call:
[System.Runtime.InteropServices.DllImport("user32")]
private static extern IntPtr GetDC(IntPtr hwnd);
[System.Runtime.InteropServices.DllImport("user32")]
private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
public static IntPtr GetHeaderControl(ListView list) {
const int LVM_GETHEADER = 0x1000 + 31;
return SendMessage(list.Handle, LVM_GETHEADER, 0, 0);
}
В обработчике события рисования вашего столбца вам понадобится что-то вроде этого:
if (e.ColumnIndex == 3) //last column index
{
ListView lv = e.Header.ListView;
IntPtr headerControl = NativeMethods.GetHeaderControl(lv);
IntPtr hdc = GetDC(headerControl);
Graphics g = Graphics.FromHdc(hdc);
// Do your extra drawing here
Rectangle rc = new Rectangle(e.Bounds.Right, //Right instead of Left - offsets the rectangle
e.Bounds.Top,
e.Bounds.Width,
e.Bounds.Height);
e.Graphics.FillRectangle(Brushes.Red, rc);
g.Dispose();
ReleaseDC(headerControl, hdc);
}
Но проблема в том, что поскольку ваш чертеж находится за пределами клиентской области, Windows не всегда знает, когда его следует рисовать. Поэтому он иногда исчезает, а затем перерисовывается, когда Windows считает, что заголовок необходимо перекрасить.
- Низкотехнологичный, но уродливый
Добавьте дополнительный пустой столбец в свой элемент управления, владелец нарисуйте его так, как вы хотите, сделайте его очень широким и отключите горизонтальную прокрутку (необязательно).
Я знаю, что это ужасно, но вы ищете предложения:)
- Наиболее эффективно, но все еще не идеально
Использовать ObjectListView . Эта обертка вокруг .NET ListView позволяет добавлять наложения в ваш список - наложение может рисовать в любом месте ListView, включая заголовок. [Декларация: я автор ObjectListView, но я все еще думаю, что это лучшее решение]
public class HeaderOverlay : AbstractOverlay
{
public override void Draw(ObjectListView olv, Graphics g, Rectangle r) {
if (olv.View != System.Windows.Forms.View.Details)
return;
Point sides = NativeMethods.GetColumnSides(olv, olv.Columns.Count-1);
if (sides.X == -1)
return;
RectangleF headerBounds = new RectangleF(sides.Y, 0, r.Right - sides.Y, 20);
g.FillRectangle(Brushes.Red, headerBounds);
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
g.DrawString("In non-client area!", new Font("Tahoma", 9), Brushes.Black, headerBounds, sf);
}
}
Это дает это:
[Читая этот ответ, я думаю, что это пример слишком больших усилий :) Надеюсь, вы найдете здесь что-то полезное.]