Integración avanzada Taksbar

La nueva barra de tareas de Windows 7 nos ofrece nuevas posibilidades para cambiar la relación con el usuario. Aumenta la interactividad aplicación-usuario mejorando los mecanismos de comunicación hacia el usuario (overlay icon, taskbar progress, thumbnail preview...) y del usuario hacia el sistema (thumbnail icons, Jump List...).

En este apartado veremos algunas de estas características con un enfoque que se sale de los conocimientos básicos.

Introducción a Jump List

La Jump List o lista de destinos cambia la forma de organizar y encontrar archivos. En lugar de buscar los archivos por su localización física y organización en carpetas, Jump List permite que tengamos los archivos más utilizados o los más recientes en un menú particular de cada aplicación.  Por ejemplo la siguiente imagen muestra la Jump List de mi Visual Studio, donde podemos encontrar accesos directos a las últimas soluciones en las que he estado trabajando.

Controlar los accesos directos que se incluyen en la Jump List es sencillo. Basta con agregar una referencia a las dll del Windows API Code Pack para acceder al espacio de nombres TaskBar. Por ejemplo, el siguiente método agrega accesos directos al bloc de notas, a la calculadora y a la ventana de comandos:

private void SetJumpList()
{
    JumpListLink lnk;
            
    //Creamos una sección personalizada
    JumpListCustomCategory aplicaciones =
        new JumpListCustomCategory("Aplicaciones");
    //Añadimos referencias a calculadora, cmd y notepad
    lnk = new JumpListLink("notepad.exe", "Bloc de notas");
    lnk.IconReference = new IconReference("notepad.exe", 0);
    aplicaciones.AddJumpListItems(lnk);
    lnk = new JumpListLink("Calc.exe", "Calculadora");
    lnk.IconReference = new IconReference("calc.exe", 0);
    aplicaciones.AddJumpListItems(lnk);
    lnk = new JumpListLink("cmd.exe", "Ventana comandos");
    lnk.IconReference = new IconReference("cmd.exe", 0);
    aplicaciones.AddJumpListItems(lnk);
            
    //Por último hay que añadir a la JumpList esta categoría
    JumpList JList = JumpList.CreateJumpList();
    JList.AddCustomCategories(aplicaciones);
    JList.Refresh();
}

Al igual que otras operaciones con la barra de tareas, hay que recordar que pertenecen al dominio de la ventana activa. Por tanto si llamamos al método que acabamos de crear en el Load() del formulario obtendremos una excepción "A valid Window is needed to update the TaskBar". Por tanto llamaremos a SetJumpList cuando se cree la ventana, por ejemplo en el evento Show(). De esta forma conseguiremos nuestra nueva Jump List con este aspecto:

En este caso no se muestran la lista de elementos más utilizados ni los más recientes porque hemos sobre escrito la lista. Para añadir esta sección bastaría con escribir el siguiente código

Comandos de aplicación en Jump List

Puesto que el cometido original de la Jump List es servir como lista de accesos directos, bien sea a listas de documentos o a aplicaciones relacionadas, la funcionalidad de incluir botones de la propia aplicación no está contemplada. A pesar de eso podemos recurrir a un truco para conseguir el efecto deseado: podemos incluir accesos directos a nuestra propia aplicación pasándole parámetros, de forma que en el método Main(string[] args) podamos detectar que se trata de uno de nuestros propios botones y que lo que hay que hacer no es instanciar una nueva ejecución de la aplicación, sino ejecutar un código distinto. Esto sería esquemáticamente lo que tendríamos que hacer en el método Main() para reaccionar correctamente ante inicios de la aplicación "normal", es decir, sin parámetros y desde la Jump List que sería con parámetros adecuados.

Lanzamiento "Normal" Lanzamiento desde Jump List
Creamos un nuevo contexto de aplicación Vemos si el parámetro es de comando
Application.Run(nuevo contexto) Recuperamos la aplicación en curso:
Process.GetProcess
 

Enviamos un mensaje a la aplicación principal:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]

privatestaticexternIntPtrSendMessage(IntPtr hwnd, uint Msg,IntPtrwParam, IntPtr lParam);

Por supuesto con esto no es suficiente, faltaría que la aplicación principal pudiese interceptar ese mensaje y actuar en consecuencia. Para ello tenemos que sobre escribir el método WndProc, previsualizando el mensaje recibido y comprobando si se corresponde con alguno de los que tenemos definidos como mensajes de Jump List. En el siguiente código vemos una posible implementación de este código, donde hemos unificado los mensajes que utilizaremos en una enumeración Contexto.Mesagges y estamos respondiendo ante dos de ellos que abren dos formularios en la aplicación:

protected override void WndProc(ref Message message)
{
    //Filtramos el mensaje
    if (message.Msg == (int)Contexto.Messages.OPEN_FRM2)
    {
        new Form2().Show();
    }
    else if (message.Msg == (int)Contexto.Messages.OPEN_FRM3)
    {
        new Form3().Show();
    }
    //Dejamos que los mensajes sigan su curso
    base.WndProc(ref message);
}