2012-04-11 9 views
10

He creado una nueva aplicación Windows Forms (C#) con un formulario simple que contiene ListView. Entonces he cambiado el View Property a Detalles y aumentado el tamaño de la fuente utilizada en este ListView y aquí está el resultado:Tema de Windows que afecta al encabezado ListView

Esto es como se ve en Windows XP con Windows clásico tema:
enter image description here

y aquí está el resultado con tema de Windows XP:
enter image description here

puedo evitar la aparición de mi solicitud a verse afectada por los estilos visuales, ya sea mediante la eliminación de Application.EnableVisualStyles() llamada o cambiando el Application.VisualStyleState: enter image description here
Aunque este cambio hace que el ListView tenga la apariencia deseada, también afecta la apariencia de otros controles. Me gustaría que mi ListView sea el único control que no se ve afectado por los Estilos visuales.

También he encontrado preguntas similares que intentan tratar con él:
Can you turn off visual styles/theming for just a single windows control?
How do I disable visual styles for just one control, and not its children?

Por desgracia, ninguna de las soluciones mencionadas obras. Parece que el encabezado en sí mismo estaría formado por algunos controles que se ven afectados por los estilos visuales, incluso cuando los estilos visuales para el control ListView están deshabilitados.

Cualquier solución C# que impida que los estilos visuales afecten a la apariencia del encabezado ListView sería apreciada.

Respuesta

2

Después de agotar la investigación, lo descubrí. Lo que pasa es que cuando se llama a

SetWindowTheme(this.Handle, "", ""); 

dentro de clase personalizada ListView, evita que los estilos visuales de afectar a la apariencia del control ListView pero no el ListView de control del cabezal (SysHeader32 ventana), que es ventana secundaria de ListView. Así cuando se llama a la función SetWindowTheme, necesitamos proveer el identificador de la ventana encabezado en lugar del mango de la ListView:

[DllImportAttribute("uxtheme.dll")] 
private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); 

[DllImport("user32")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); 

// Callback method to be used when enumerating windows: 
private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
{ 
    GCHandle gch = GCHandle.FromIntPtr(pointer); 
    List<IntPtr> list = gch.Target as List<IntPtr>; 
    if (list == null) 
     throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 
    list.Add(handle); 
    return true; 
} 

// delegate for the EnumChildWindows method: 
private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); 

// get first child: 
private static void DisableVisualStylesForFirstChild(IntPtr parent) 
{ 
    List<IntPtr> children = new List<IntPtr>(); 
    GCHandle listHandle = GCHandle.Alloc(children); 
    try 
    { 
     EnumWindowProc childProc = new EnumWindowProc(EnumWindow); 
     EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); 
     if (children.Count > 0) 
      SetWindowTheme(children[0], "", ""); 
    } 
    finally 
    { 
     if (listHandle.IsAllocated) 
      listHandle.Free(); 
    } 
} 

protected override void OnHandleCreated(EventArgs e) 
{ 
    DisableVisualStylesForFirstChild(this.Handle); 
    base.OnHandleCreated(e); 
} 
+0

Dado que se basa en la solución sugerida por Kamil Lach, estoy otorgando su respuesta con la recompensa que ofrecí. – LihO

2

¿Qué tal deshabilitar los estilos visuales?

con este código se podría desactivar el estilo de un control (sólo tiene que utilizar ListViewConstrol en lugar de Lista):

using System; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

public class ListViewControl : ListView { 
    [DllImportAttribute("uxtheme.dll")] 
    private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); 

    protected override void OnHandleCreated(EventArgs e) { 
    SetWindowTheme(this.Handle, "", ""); 
    base.OnHandleCreated(e); 
    } 
} 
+0

+1 por señalar que los estilos visuales causan este cambio, aunque esta solución no lo hace trabajo en absoluto. – LihO

+0

Descubrí por qué SetWindowTheme no funcionaba antes. Funciona ahora, mira mi respuesta;) – LihO

+0

Felicidades Kamil por la generosidad :) – ABH

3

Parece que este es un known bug para el que no hay ninguna solución fácil. De acuerdo con la respuesta allí:

Después de hacer un gran trabajo de investigación con este tema, nos encontramos con que se trata de un error del SO ventanas, que los olvida de control de cabecera ComCtl6.0 para aplicar la información de fuente al dibujo CORRIENTE CONTINUA.

Sin embargo, podría dibujar el encabezado de columna usted mismo. Consulte this article on MSDN para obtener detalles sobre cómo hacerlo y también consulte listView1_DrawColumnHeader.

+0

+1 por dibujarlo tú mismo –

+0

Dibujarlo por mí mismo no servirá para nada ya que solo puedes cambiar el contenido eso está siendo dibujado, no el tamaño del encabezado. – LihO

0

Como Botz3000 mencionó en su respuesta que es un problema bien conocido con ListView en Windows XP. Otra solución es registrar el evento ListView.DrawColumnHeader y restablecer la fuente del encabezado en él. Debe establecer la propiedad ListView.OwnerDraw en true. El código MSDN es el siguiente;

// Draws column headers. 
private void listView1_DrawColumnHeader(object sender, 
    DrawListViewColumnHeaderEventArgs e) 
{ 
    using (StringFormat sf = new StringFormat()) 
    { 
     // Store the column text alignment, letting it default 
     // to Left if it has not been set to Center or Right. 
     switch (e.Header.TextAlign) 
     { 
      case HorizontalAlignment.Center: 
       sf.Alignment = StringAlignment.Center; 
       break; 
      case HorizontalAlignment.Right: 
       sf.Alignment = StringAlignment.Far; 
       break; 
     } 

     // Draw the standard header background. 
     e.DrawBackground(); 

     // Draw the header text. 
     using (Font headerFont = 
        new Font("Helvetica", 10, FontStyle.Bold)) 
     { 
      e.Graphics.DrawString(e.Header.Text, headerFont, 
       Brushes.Black, e.Bounds, sf); 
     } 
    } 
    return; 
} 

En este caso la fuente de cabecera siempre habrá "Helvetica", 10, FontStyle.Bold y no serán afectadas por la fuente de lista. Check MSDN para más detalles.

+0

No, OwnerDraw no es el camino, no es posible afectar la altura del encabezado ListView con él. – LihO

+0

@LihO No está haciendo nada con la altura del encabezado, ya que no es posible en XP. Por favor, lea mi respuesta cuidadosamente, la idea es mantener el texto del encabezado más pequeño para que quepa dentro del encabezado. – ABH

+0

Pero mi pregunta es cómo "hacer que el encabezado ListView tenga la altura correcta", no cómo hacer que el texto del encabezado sea más pequeño ... – LihO

Cuestiones relacionadas