Pergunta

É possível OwnerDraw toda a seção cabeçalho da coluna de um listview? (Incluindo a região à direita dos cabeçalhos da coluna)? ListView está em Detalhes.

Uma resposta aqui indica que o espaço restante pode ser desenhado juntamente com o último cabeçalho de coluna: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

Mas não parece trabalho em tudo -. Nada é desenhado área de cabeçalho fora

A solução proposta é baseada no desenho fora dos limites passou:

if (e.ColumnIndex == 3) //last column index
{
    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);
}

A propriedade ClipBounds do exemplo gráficos disponíveis indica uma área não ligado (a partir de grandes números negativos para grande positivo). Mas nada é desenhado fora da área de columnheader da última coluna.

Alguém tem uma solução para isso?

Foi útil?

Solução

Eu estou surpreso com a resposta de Jeffery Tan nesse post. Sua solução não pode trabalhar, desde os tentativas de código para desenhar fora da área de cliente do controle de cabeçalho. O hDC usado dentro desenho personalizado (e, portanto, desenho proprietário) é para a área de cliente do controle, e assim não pode ser usado para pintar na área de não-cliente. A área à direita da coluna mais à direita em um cabeçalho de controlo é na área não-cliente. Então você precisa de uma solução diferente.

Possíveis soluções

  1. Hi tecnologia e parcialmente eficaz

Você pode ativar o desenho fora da área de cliente usando a chamada GetDC() WinAPI:

[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);
}

Em seu manipulador de eventos empate coluna, você vai precisar de algo como isto:

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);
}

Mas o problema com isto é que, desde o seu desenho está fora da área do cliente, o Windows nem sempre sabe quando ele deve ser desenhado. Então ele vai desaparecer, por vezes, em seguida, ser redesenhado quando o Windows acha que as necessidades de cabeçalho repintura.

  1. Baixa tecnologia, mas feio

Adicione uma coluna extra vazio para seu controle, proprietário desenhá-lo fazer olhar como quiser, torná-lo muito ampla, e desligue a rolagem horizontal (opcional).

Eu sei que isto é horrível, mas você está procurando sugestões:)

  1. Mais eficaz, mas ainda não é perfeito

Use ObjectListView . Este invólucro em torno de um .NET ListView permite que você adicione sobreposições à sua lista - uma sobreposição pode desenhar em qualquer lugar dentro do ListView, incluindo o cabeçalho. [Declaração: Eu sou o autor de ObjectListView, mas eu ainda acho que é a melhor solução]

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);
    }
}

Isto dá a seguinte: text alt

[leitura sobre esta resposta, penso que este é um exemplo de tentar muito difícil :) Espero que você encontrar algo útil.]

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top