integración_escritorio

ListView – Aspecto Nativo

Un problema que tuve con el control ListView es que carece del aspecto nativo presentado en el explorador de Windows, la selección del control es pobre y sin transparencia.

Investigando como poder obtener el aspecto nativo en un control ListView, encontré la primera respuesta en el sitio de StackOverflow. En esta publicación, exponen que para lograrlo, se debe de utilizar la función SetWindowTheme de la librería uxtheme.dll.

Al implementar el código, en efecto se puede obtener el aspecto nativo. Sin embargo, este presenta un problema de parpadeo al actualizar algún elemento, ya que el control completo se refresca, en lugar de un sólo elemento.

La respuesta al problema del parpadeo la encontré en el sitio de C Pound, en donde explican que para evitar el parpadeo, se debe de utilizar el Double Buffer y filtrar el mensaje WM_ERASEBKGND.

Al implementar ambos códigos en una clase, se obtiene un ListView que utiliza el aspecto nativo del sistema operativo y que no produce parpadeo. Sin embargo presenta un borde punteado de color negro al momento de recibir foco y también cuando se cambia la selección de algún elemento

Nuevamente en el sitio de StackOverflow. Se debe de enviar el mensaje WM_CHANGEUISTATE con el parámetro UISF_HIDEFOCUS para evitar que se dibuje el borde punteado de selección.

El código resultado es el siguiente:


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

namespace LV_AspectoNativo
{
 class NativeListView:ListView
 {
  [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
  private extern static int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);

  [DllImport("user32.dll")]
  public extern static int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

  protected override void CreateHandle()
  {
   base.CreateHandle();
   // Aplicar el tema nativo del control ListView
   SetWindowTheme(this.Handle, "explorer", null);
  }

  public NativeListView()
  {
   // Activar double buffering
   this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

   // Habilitar el evento OnNotifyMessage para luego poder filtrar
   // el mensaje WM_ERASEBKGND antes de que sea procesado
   this.SetStyle(ControlStyles.EnableNotifyMessage, true);

   // Remover el rectangulo de selección de borde punteado
   SendMessage(Handle, 0x127, 0x10001, 0);
  }

  protected override void OnNotifyMessage(Message m)
  {
   // Filtrar el mensaje WM_ERASEBKGND
   if (m.Msg != 0x14)
   {
    base.OnNotifyMessage(m);
   }
  }

  protected override void OnSelectedIndexChanged(EventArgs e)
  {
   base.OnSelectedIndexChanged(e);
   // Remover el rectangulo de selección de borde punteado
   SendMessage(Handle, 0x127, 0x10001, 0);
  }

  protected override void OnEnter(EventArgs e)
  {
   base.OnEnter(e);
   // Remover el rectangulo de selección de borde punteado
   SendMessage(Handle, 0x127, 0x10001, 0);
  }
 }
}

Ejemplo

El resultado es un control parecido al ListView el cual puede ubicarse en la barra de componentes del proyecto. El control se utiliza de la misma manera que un ListView de WindowsForms.

listview con aspecto nativo

Ejemplo – Listview Aspecto Nativo

El proyecto utiliza el parte de los iconos creados por Martz90 – Clircle Icons Pack, enlaces al sitio de los iconos y licencia correspondiente dentro de la carpeta de iconos del proyecto ejemplo.

2 comentarios sobre “ListView – Aspecto Nativo”

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s