Dado que apenas quedan unos meses para que Windows 7 “se encuentre definitivamente entre nosotros”, vamos a ir viendo algunas características interesantes que presenta este nuevo sistema operativo. Estas características o funcionalidades no son sólo atractivas desde el punto de vista de desarrollo sino también para el propio usuario, ya que tienen como objetivo facilitar y simplificar el trabajo diario.
El ejemplo que vamos a ver a continuación se trata de mostrar una serie de iconos sobre nuestra aplicación minimizada. Y la pregunta es ¿Para que nos sirve esto? Podemos utilizar los iconos para indicar el estado en que se encuentra una aplicación o un archivo, para marcar el tipo de contenido de una carpeta…
A través del listbox que aparece en la imagen, podemos seleccionar los distintos iconos que se muestran de manera que si activamos el checkbox “Show selected icon as overlay”, el icono que se encuentre seleccionado, aparecerá sobre el icono de nuestra aplicación, cuando esta se encuentra minimizada. A continuación podemos ver alguno de los ejemplos:
Una vez visto esto vamos a entrar en el código de la aplicación. Creamos nuestro proyecto de tipo Windows Forms, y añadimos las referencias al Windows API Code Pack, previamente instalado en nuestro equipo. A continuación añadimos un control de tipo WPF, y los recursos que vayamos a utilizar, y pasamos a programar dicho control.
- <UserControl x:Class="TaskBarIcons.OverlayIcons"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d"
- xmlns:local="clr-namespace:TaskBarIcons">
- <UserControl.Resources>
- <local:IconToBitmapSourceConverter x:Key="IconToBitmapSourceConverter" />
- <DataTemplate x:Key="ImageTemplate">
- <Grid>
- <Image Source="{Binding Converter={StaticResource IconToBitmapSourceConverter}, Mode=Default}"/>
- </Grid>
- </DataTemplate>
- <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
- <VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal"/>
- </ItemsPanelTemplate>
- <SolidColorBrush x:Key="ListBoxItemUnselected" Color="#002685E2" />
- <SolidColorBrush x:Key="ListBoxItemSelected" Color="#FF2685E2" />
- <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
- <Setter Property="Background" Value="Transparent"/>
- <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
- <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
- <Setter Property="Padding" Value="2,0,0,0"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type ListBoxItem}">
- <Border x:Name="Bd" SnapsToDevicePixels="true"
- Background="{TemplateBinding Background}"
- Padding="{TemplateBinding Padding}" HorizontalAlignment="Center"
- VerticalAlignment="Center"
- BorderBrush="{DynamicResource ListBoxItemUnselected}" BorderThickness="2">
- <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
- </Border>
- <ControlTemplate.Triggers>
- <Trigger Property="IsSelected" Value="true">
- <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource ListBoxItemSelected}"/>
- </Trigger>
- <Trigger Property="IsEnabled" Value="false">
- <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </UserControl.Resources>
- <Grid>
- <Grid Margin="2" Width="200" VerticalAlignment="Top">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="*" MinHeight="50"/>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- </Grid.RowDefinitions>
- <Rectangle Style="{DynamicResource BorderStyle}" Grid.RowSpan="4" />
- <TextBlock Text="Overlay Icons"
- Margin="{DynamicResource BoxedContentMargin}"
- Style="{DynamicResource SectionTitle}" />
- <ListBox x:Name="iconsList"
- Margin="{DynamicResource BoxedContentMargin}"
- Grid.Row="1" ItemTemplate="{DynamicResource ImageTemplate}"
- ItemsPanel="{DynamicResource ItemsPanelTemplate1}"
- ItemContainerStyle="{DynamicResource ListBoxItemStyle1}"
- SelectionChanged="iconsList_SelectionChanged" />
- <CheckBox x:Name="ShowOverlay" Click="ShowOverlay_Click" Grid.Row="2"
- Margin="{DynamicResource BoxedContentMargin}">
- <TextBlock Text="Show selected icon as overlay" TextWrapping="Wrap" />
- </CheckBox>
- </Grid>
- </Grid>
- </UserControl>
- </form>
Por otro lado el archivo .cs, donde definiremos la lógica de funcionamiento del mismo y cuyo código será:
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Globalization;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Media.Imaging;
- using Microsoft.WindowsAPICodePack.Taskbar;
- namespace TaskBarIcons
- {
- /// <summary>
- /// Interaction logic for UserControl1.xaml
- /// </summary>
- public partial class OverlayIcons : UserControl
- {
- public OverlayIcons()
- {
- InitializeComponent();
- this.Loaded += Overlays_Loaded;
- this.Unloaded += Overlays_Unloaded;
- }
- private void Overlays_Unloaded(object sender, RoutedEventArgs e)
- {
- TaskbarManager.Instance.SetOverlayIcon(null, null);
- }
- private void Overlays_Loaded(object sender, RoutedEventArgs e)
- {
- if (this.iconsList.ItemsSource == null)
- {
- this.iconsList.ItemsSource = OverlayIcons.Icons;
- }
- else
- {
- ShowOrHideOverlayIcon();
- }
- }
- static List<Icon> _icons;
- public static List<Icon> Icons
- {
- get
- {
- if (_icons == null)
- {
- _icons = new List<Icon>()
- {
- TaskBarIcons.Resources.Discussion,
- TaskBarIcons.Resources.Mail,
- TaskBarIcons.Resources.Add_Appointment,
- TaskBarIcons.Resources.Add_To_Favorite,
- TaskBarIcons.Resources.Desktop,
- TaskBarIcons.Resources.Movie_CD,
- TaskBarIcons.Resources.Mr__Bomb,
- TaskBarIcons.Resources.Smiley_Star_Pink
- };
- }
- return _icons;
- }
- }
- private void ShowOverlay_Click(object sender, RoutedEventArgs e)
- {
- ShowOrHideOverlayIcon();
- }
- private void iconsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- ShowOrHideOverlayIcon();
- }
- //The following method is part of the lab. If we are asked to show an
- //overlay icon, use the TaskbarManager.SetOverlayIcon method to set it.
- //Use the same method with a null icon to reset it, so that no icon is
- //displayed.
- private void ShowOrHideOverlayIcon()
- {
- if (ShowOverlay.IsChecked.Value)
- {
- Icon icon = iconsList.SelectedItem as Icon;
- if (icon != null)
- TaskbarManager.Instance.SetOverlayIcon(icon, "icon" + iconsList.SelectedIndex.ToString());
- }
- else
- {
- TaskbarManager.Instance.SetOverlayIcon(null, null);
- }
- }
- }
- public class IconToBitmapSourceConverter : IValueConverter
- {
- #region IValueConverter Members
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- Icon icon = value as Icon;
- if (icon != null)
- {
- BitmapSource bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
- icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
- return bitmap;
- }
- return value;
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- #endregion
- }
- }
Si queremos aprovechar otras de las características que presenta Windows 7, existe un kit de entrenamiento que podemos descargar aquí, y en el cual encontramos numerosos tutoriales para crear distintas aplicaciones.