Domanda

È possibile ritirare il proprietario dell'intera sezione dell'intestazione di colonna di una visualizzazione elenco? (compresa la regione a destra delle intestazioni di colonna)? ListView è in Visualizzazione dettagli.

Una risposta qui indica che lo spazio rimanente può essere disegnato insieme all'ultima intestazione di colonna: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

Ma sembra non funzionare affatto - non viene disegnato nulla al di fuori dell'area dell'intestazione.

La soluzione proposta si basa sul disegno al di fuori dei limiti passati:

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

La proprietà ClipBounds dell'istanza grafica disponibile indica un'area non associata (da grandi numeri negativi a grandi positivi). Ma nulla viene disegnato al di fuori dell'area dell'intestazione dell'ultima colonna.

Qualcuno ha una soluzione per questo?

È stato utile?

Soluzione

Sono sorpreso dalla risposta di Jeffery Tan in quel post. La sua soluzione non può funzionare, poiché il codice tenta di disegnare all'esterno dell'area client di controllo dell'intestazione. Il hDC utilizzato nel disegno personalizzato (e quindi nel disegno del proprietario) è destinato all'area client del controllo, quindi non può essere utilizzato per disegnare nell'area non client. L'area a destra della colonna più a destra in un controllo di intestazione si trova nell'area non client. Quindi hai bisogno di una soluzione diversa.

Soluzioni possibili

  1. Alta tecnologia e parzialmente efficace

Puoi abilitare il disegno al di fuori dell'area client usando la chiamata WinAPI GetDC () :

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

Nel gestore dell'evento di disegno della colonna, avrai bisogno di qualcosa del genere:

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

Ma il problema è che, poiché il disegno è al di fuori dell'area client, Windows non sa sempre quando dovrebbe essere disegnato. Quindi a volte scompare e quindi viene ridisegnato quando Windows pensa che l'intestazione debba essere ridipinta.

  1. Bassa tecnologia ma brutta

Aggiungi una colonna vuota in più al tuo controllo, il proprietario la disegna in modo che appaia come desideri, rendila molto ampia e disattiva lo scorrimento orizzontale (opzionale).

So che è orribile, ma stai cercando suggerimenti :)

  1. Più efficace, ma ancora non perfetto

Usa ObjectListView . Questo wrapper attorno a .NET ListView consente di aggiungere overlay all'elenco: un overlay può essere disegnato ovunque all'interno di ListView, inclusa l'intestazione. [Dichiarazione: sono l'autore di ObjectListView, ma penso ancora che sia la soluzione migliore]

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

Questo dà questo: alt text

[Leggendo questa risposta, penso che questo sia un esempio di tentativi troppo duri :) Spero che trovi qualcosa di utile qui.]

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top