domenica 24 luglio 2011

How to animate an image in MVVM

I want to design a "tableau de bord" with some indicators blinking or animating as soon as a boolean condition is true.
The indicators are simple images, the blinking is obtained changing the image opacity in a Storyboard.

<Storyboard x:Key="BlinkingAnimation">
  <DoubleAnimation Storyboard.TargetProperty="(Image.Opacity)"    
    BeginTime="0:0:0" Duration="0:0:0.5"    
    From="1.0" To="0.0" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>

The animaton will start on a DataTrigger bound to a Property defined in the ViewModel


First recipe: just edit the style of the Image in the XAML

<Image Source="/MvvmBlinkingImage;component/Images/favorite.png" >
  <Image.Style>
     <Style>
      <Style.Triggers>
        <DataTrigger Binding="{Binding Property1}" Value="true">
          <DataTrigger.EnterActions>
            <BeginStoryboard Storyboard="{StaticResource BlinkingAnimation}" x:Name="blink"/>
          </DataTrigger.EnterActions>
          <DataTrigger.ExitActions>
            <StopStoryboard BeginStoryboardName="blink" />
          </DataTrigger.ExitActions>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Image.Style>
 
</Image> 

Second recipe: Create a custom control inherited from Image. The control registers a dependency property to bind to the DataTrigger


public class AnimatedImage : Image
{
        public static DependencyProperty IsBlinkingProperty =
            DependencyProperty.Register("IsBlinking", typeof(bool), typeof(AnimatedImage));
 
        public bool IsBlinking
        {
            get { return (bool)base.GetValue(IsBlinkingProperty); }
            set { base.SetValue(IsBlinkingProperty, value); }
        }
}

Now add a new style to a DictionaryResource for the new AnimatedImage control:


<
Style x:Key="AnimatedImageStyle" TargetType="{x:Type uc:AnimatedImage}">
  <Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsBlinking}" Value="true">
      <DataTrigger.EnterActions>
        <BeginStoryboard Storyboard="{StaticResource BlinkingAnimation}" x:Name="blink"/>
      </DataTrigger.EnterActions>
      <DataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="blink" />
      </DataTrigger.ExitActions>
    </DataTrigger>
  </Style.Triggers>
</Style>   

Please note that IsBlinking is a property of AnimateImage and not of the ViewModel, so it is Necessary override the DefaultContext with RelativeSource Self.Here an useful link on WPF binding: http://www.nbdtech.com/Free/WpfBinding.pdf

Eventually use the AnimateImage control and AnimatedImageStyle in the XAML:

<uc:AnimatedImage IsBlinking="{Binding Property1}" Style="{StaticResource AnimatedImageStyle}" Source="/MvvmBlinkingImage;component/Images/favorite.png" />



giovedì 21 luglio 2011

Detecting USB microphone insertion/removal in C# .Net 4.0 WPF

I'm working on a C# .Net 4.0 WPF project that must detect the insertion or removal of an USB microphone.
The code should be implemented in a C# class library.
Since .Net 4.0 doesn't have classes able to detect the insertion or removal of an USB device, the solution is hooking the message WM_DEVICECHANGE, then find out which device changed in order to be sure that the device is the one desired and not some other device.
The first issue to solve is that we don't have any hWnd handle in a class library, so we need to create a fake window in order to hook his window procedure:


HwndSource hwndSource = new HwndSource(0, 0, 0, 0, 0, "fake", IntPtr.Zero);
if (hwndSource != null)  //Attaching to window procedure
    hwndSource.AddHook(new HwndSourceHook(this.hwndSourceHook));

//the window procedure
IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
{
    if (msg == WM_DEVICECHANGE)   
   {
      if ((int)wParam == DBT_DEVICEARRIVAL)
     {   
        DEV_BROADCAST_DEVICEINTERFACE info = (DEV_BROADCAST_DEVICEINTERFACE)   
Marshal.PtrToStructure(lParam, typeof(DEV_BROADCAST_DEVICEINTERFACE));   
      }   
      else if ((int)wParam == DBT_DEVICEREMOVECOMPLETE)
     {
      }
      else if ((int)wParam == DBT_DEVNODES_CHANGED)
     {
     }
  }  
  return IntPtr.Zero;
}


The second problem is to identify the device by the GUID class.
Several microphones by Philips, Olympus or Dictaphone are multicomposite devices.
It means that when you plugin the microphone you get 5 or 6 WM_DEVICECHANGE messages.
So it is preferable to filter the device class using the RegisterDeviceNotification API.

DEV_BROADCAST_DEVICEINTERFACE notificationFilter = new DEV_BROADCAST_DEVICEINTERFACE();
int size = Marshal.SizeOf(notificationFilter);
notificationFilter.dbcc_size = size;
notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notificationFilter.dbcc_reserved = 0;
notificationFilter.dbcc_classguid = new Guid(MediaClassID).ToByteArray();
IntPtr buffer = IntPtr.Zero;
buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(notificationFilter, buffer, true);
IntPtr result = RegisterDeviceNotification(this._hwndSource.Handle, buffer, (Int32)(DEVICE_NOTIFY.DEVICE_NOTIFY_WINDOW_HANDLE));

The class guid are stored in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses
If you want find out the class guid of your device, use the parameter DEVICE_NOTIFY_ALL_INTERFACE_CLASSES in RegisterDeviceNotification API, plug in the device into the USB port and read the guid in the DEV_BROADCAST_DEVICEINTERFACE structure.

I found out the following classes used by USB microphones:
KSCATEGORY_CAPTURE = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
KSCATEGORY_AUDIO = "{6994AD04-93EF-11D0-A3CC-00A0C9223196}"

Here attached a MVVM project using the USBDetector class

WPF

Non sono un serio sviluppatore ma nella mia attività mi tocca creare scripts e applicazioni per automatizzare l'attività di ufficio. Negli ultimi 20 anni ho utilizzato principalmente come strumenti di programmazione C++ e MFC. Quando l'anno scorso ho visto in azione .Net 4.0 e WPF, mi è uscito spontaneamante un Sokka!
Ho intrapreso un percorso autoformativo per uscire dalla caverna trovando particolarmente utili i webcast di Corrado Cavalli, senza dubbio il migliore nella sua categoria.
Molto interessanti i tutorial di channel9 e gli eventi tecnici di TechEd.
Aggiungendo un pizzico di patterns e toolkits (Model View ViewModel, Dependendy Injection, Inversion of Control) come MVVM LightUnity conto di disporre di un framework che rimarrà attuale per i prossimi 20 anni.

mercoledì 20 luglio 2011

Sokka!

Sokka! è una esclamazione legata a stupore e meraviglia, unita a un po' di soddisfazione, e che sta ad indicare "finalmente ho capito", "ho trovato", l'equivalente di eureka! pronunciato da Archimede, ma molto più liberatorio.
Potete pronunciare Sokka! davanti a un bolognese o a un giapponese, che senza dubbio capirà e si immedesimerà nel vostro stato d'animo. Sokka! è indicata soprattutto dopo essersi conto di aver commesso una grossa cappella.....
In questo blog vorrei postare la soluzione ai miei problemi di tipo informatico che mi hanno fatto esclamare Sokka! con l'auspicio che anche qualcun altro possa esclamare Sokka! leggendo il contenuto di un post.