<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Erik-Klimczak/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Erik-Klimczak/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Erik-Klimczak/Posts</link>
    <language>en</language>
    <pubDate>Tue, 21 May 2013 05:34:47 GMT</pubDate>
    <lastBuildDate>Tue, 21 May 2013 05:34:47 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>1</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>WPF Custom Screen Saver Art</title>
      <description><![CDATA[
<h3>Summary</h3>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/thum.png"><img title="thum" border="0" alt="thum" align="left" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/thum_thumb.png" width="71" height="63"></a>Creating custom
 wallpaper is easy. But what about custom screen savers? This post will detail how to build a custom saver using Windows Presentation Framework (WPF). The posted code also provides some insight on how to create interesting particle effects using WPF's animation
 engine, and how to implement multiple monitor support in .Net.</p>
<p>Erik Klimczak - <a href="http://www.claritycon.com/">Clarity Consulting</a></p>
<h5>Download</h5>
<ul>
<li><span><a href="http://wpfscreensaverart.codeplex.com/">http://wpfscreensaverart.codeplex.com/</a>&nbsp;</span>&nbsp;</li></ul>
<h4></h4>
<h4>Introduction</h4>
<p><a href="http://www.microsoft.com/uc/default.mspx">Microsoft Unified Communications</a> (UC) is a new technology that has been getting a lot of hype in the past couple of months. UC is essentially the integration of messaging, voice, and video across the
 applications and devices that people use every day. More information about UC can be found
<a href="http://www.microsoft.com/uc/default.mspx">here</a>. One of the coolest things about UC is the concept of “presence” (see below). The Presence indicator effectively allows the user to reflect his/her status in other Office Communicator Server friendly
 applications (i.e. Outlook, Office communicator, Live Meeting, etc.)</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image002.jpg"><img title="clip_image002" border="0" alt="clip_image002" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image002_thumb.jpg" width="240" height="151"></a></p>
<p>While building out some communicator functionality on another project I found myself recreating the presence “bubbles” in xaml so that they could scale without losing quality (see below). I used Expression Design to re-create the presence bubbles and export
 then to xaml.</p>
<p>In doing so it occurred to me that the presence “bubbles” would make for some excellent art sprites.
</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image004.jpg"><img title="clip_image004" border="0" alt="clip_image004" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image004_thumb.jpg" width="470" height="342"></a>&nbsp;</p>
<p>So after a hop-skip-and a jump to Photoshop I found myself with a shiny new “presence art” wallpaper.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image006.jpg"><img title="clip_image006" border="0" alt="clip_image006" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image006_thumb.jpg" width="496" height="312"></a></p>
<p>Immediately after creating the wallpaper I thought to myself, “this would also make a great screen saver”. This article will attempt to show how to build a custom WPF screen saver that implements a simple physics particle effect using the WPF animation engine.</p>
<h4>Particle Animation</h4>
<p>With my graphic designer hat on I knew that I wanted to create a floating particle effect. Particle effects can be used to simulate anything from rain, snow, fire to bubbles and clouds. Then by varying the presence “bubbles” in size and opacity the illusion
 of depth and space can be created. After some research I found the CompositionTarget.Rendering event handler in WPF. Essentially, this event is a timer that ticks all the time and fires once each time WPF decides to render a frame. Inside the event handler
 you have complete freedom to do whatever you want to any object.&nbsp; In other words, hooking CompositionTarget.Rendering is very much a &quot;do it yourself&quot; animation system. This event is especially good for physics-based animations and is very similar to the way
 Flash's rendering engine works. The MSDN entry for this event handler can be found
<a href="http://msdn.microsoft.com/en-us/library/system.windows.media.compositiontarget.rendering.aspx">
here</a>.</p>
<p>Once I had found the appropriate animation hook I created the particle user control. This control holds the various particle attributes that will be animated. The code below shows the various properties that can be used to create very interesting physics-based
 effects. These properties can be used to calculate collision detection, gravitational pull and other kinetics-related effects.</p>
<p>C#</p>
<div>
<div>
<pre><span>   1:</span> <span>public</span> <span>partial</span> <span>class</span> Particle : UserControl</pre>
<pre><span>   2:</span>    {</pre>
<pre><span>   3:</span>&nbsp; </pre>
<pre><span>   4:</span>        <span>public</span> Particle()</pre>
<pre><span>   5:</span>        {</pre>
<pre><span>   6:</span>&nbsp; </pre>
<pre><span>   7:</span>            InitializeComponent();</pre>
<pre><span>   8:</span>        }</pre>
<pre><span>   9:</span>&nbsp; </pre>
<pre><span>  10:</span>        <span>public</span> <span>static</span> <span>readonly</span> DependencyProperty StatusProperty = DependencyProperty.Register(<span>&quot;Status&quot;</span>, <span>typeof</span>(Status), <span>typeof</span>(Particle), <span>new</span> UIPropertyMetadata(Particle.StatusValueChanged));</pre>
<pre><span>  11:</span>        <span>public</span> Status Status</pre>
<pre><span>  12:</span>        {</pre>
<pre><span>  13:</span>            get { <span>return</span> (Status)GetValue(StatusProperty); }</pre>
<pre><span>  14:</span>            set { SetValue(StatusProperty, <span>value</span>); }</pre>
<pre><span>  15:</span>        }</pre>
<pre><span>  16:</span>&nbsp; </pre>
<pre><span>  17:</span>        <span>private</span> <span>static</span> <span>void</span> StatusValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)</pre>
<pre><span>  18:</span>        {</pre>
<pre><span>  19:</span>            Particle myclass = (Particle)d;</pre>
<pre><span>  20:</span>            myclass.imgStatus.Source = Application.Current.FindResource(((Status)e.NewValue).ToString() &#43; <span>&quot;Png&quot;</span>) <span>as</span> BitmapImage;</pre>
<pre><span>  21:</span>        }</pre>
<pre><span>  22:</span>&nbsp; </pre>
<pre><span>  23:</span>        <span>public</span> <span>double</span> Radius</pre>
<pre><span>  24:</span>        {</pre>
<pre><span>  25:</span>            get { <span>return</span> <span>this</span>.imgStatus.Height / 2; }</pre>
<pre><span>  26:</span>            set { <span>this</span>.imgStatus.Height = <span>this</span>.imgStatus.Width = <span>value</span> * 2; }</pre>
<pre><span>  27:</span>        }</pre>
<pre><span>  28:</span>&nbsp; </pre>
<pre><span>  29:</span>        <span>private</span> <span>double</span> vy;</pre>
<pre><span>  30:</span>        <span>public</span> <span>double</span> VY</pre>
<pre><span>  31:</span>        {</pre>
<pre><span>  32:</span>            get { <span>return</span> <span>this</span>.vy; }</pre>
<pre><span>  33:</span>            set { <span>this</span>.vy = <span>value</span>; }</pre>
<pre><span>  34:</span>        }</pre>
<pre><span>  35:</span>&nbsp; </pre>
<pre><span>  36:</span>        <span>private</span> <span>double</span> vx;</pre>
<pre><span>  37:</span>        <span>public</span> <span>double</span> VX</pre>
<pre><span>  38:</span>        {</pre>
<pre><span>  39:</span>            get { <span>return</span> <span>this</span>.vx; }</pre>
<pre><span>  40:</span>            set { <span>this</span>.vx = <span>value</span>; }</pre>
<pre><span>  41:</span>        }</pre>
<pre><span>  42:</span>&nbsp; </pre>
<pre><span>  43:</span>        <span>private</span> <span>double</span> mass;</pre>
<pre><span>  44:</span>        <span>public</span> <span>double</span> Mass</pre>
<pre><span>  45:</span>        {</pre>
<pre><span>  46:</span>            get { <span>return</span> <span>this</span>.mass; }</pre>
<pre><span>  47:</span>            set { <span>this</span>.mass = <span>value</span>; }</pre>
<pre><span>  48:</span>        }</pre>
<pre><span>  49:</span>        <span>private</span> <span>double</span> x;</pre>
<pre><span>  50:</span>        <span>public</span> <span>double</span> X</pre>
<pre><span>  51:</span>        {</pre>
<pre><span>  52:</span>            get { <span>return</span> <span>this</span>.x; }</pre>
<pre><span>  53:</span>            set { <span>this</span>.x = <span>value</span>; }</pre>
<pre><span>  54:</span>        }</pre>
<pre><span>  55:</span>&nbsp; </pre>
<pre><span>  56:</span>        <span>private</span> <span>double</span> y;</pre>
<pre><span>  57:</span>        <span>public</span> <span>double</span> Y</pre>
<pre><span>  58:</span>        {</pre>
<pre><span>  59:</span>            get { <span>return</span> <span>this</span>.y; }</pre>
<pre><span>  60:</span>            set { <span>this</span>.y = <span>value</span>; }</pre>
<pre><span>  61:</span>        }</pre>
<pre><span>  62:</span>    }</pre>
</div>
</div>
<pre class="csharpcode">VB</pre>
<div>
<div>
<pre><span>   1:</span> Partial <span>Public</span> <span>Class</span> Particle</pre>
<pre><span>   2:</span>     <span>Inherits</span> UserControl</pre>
<pre><span>   3:</span>&nbsp; </pre>
<pre><span>   4:</span>&nbsp; </pre>
<pre><span>   5:</span>     <span>Public</span> <span>Sub</span> <span>New</span>()</pre>
<pre><span>   6:</span>         InitializeComponent()</pre>
<pre><span>   7:</span>     <span>End</span> <span>Sub</span></pre>
<pre><span>   8:</span>&nbsp; </pre>
<pre><span>   9:</span>     <span>Public</span> <span>Shared</span> <span>ReadOnly</span> StatusProperty <span>As</span> DependencyProperty = DependencyProperty.Register(<span>&quot;Status&quot;</span>, <span>GetType</span>(Status), <span>GetType</span>(Particle), <span>New</span> PropertyMetadata(<span>AddressOf</span> Particle.StatusValueChanged))</pre>
<pre><span>  10:</span>     <span>Public</span> <span>Property</span> Status() <span>As</span> Status</pre>
<pre><span>  11:</span>         <span>Get</span></pre>
<pre><span>  12:</span>             <span>Return</span> <span>CType</span>(GetValue(StatusProperty), Status)</pre>
<pre><span>  13:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  14:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> Status)</pre>
<pre><span>  15:</span>             SetValue(StatusProperty, value)</pre>
<pre><span>  16:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  17:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  18:</span>&nbsp; </pre>
<pre><span>  19:</span>     <span>Private</span> <span>Shared</span> <span>Sub</span> StatusValueChanged(<span>ByVal</span> d <span>As</span> DependencyObject, <span>ByVal</span> e <span>As</span> DependencyPropertyChangedEventArgs)</pre>
<pre><span>  20:</span>         <span>Dim</span> [<span>myclass</span>] <span>As</span> Particle = <span>CType</span>(d, Particle)</pre>
<pre><span>  21:</span>         [<span>myclass</span>].imgStatus.Source = <span>TryCast</span>(Application.Current.FindResource((<span>CType</span>(e.NewValue, Status)).ToString() &amp; <span>&quot;Png&quot;</span>), BitmapImage)</pre>
<pre><span>  22:</span>     <span>End</span> <span>Sub</span></pre>
<pre><span>  23:</span>&nbsp; </pre>
<pre><span>  24:</span>     <span>Public</span> <span>Property</span> Radius() <span>As</span> <span>Double</span></pre>
<pre><span>  25:</span>         <span>Get</span></pre>
<pre><span>  26:</span>             <span>Return</span> <span>Me</span>.imgStatus.Height / 2</pre>
<pre><span>  27:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  28:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  29:</span>             <span>Me</span>.imgStatus.Width = value * 2</pre>
<pre><span>  30:</span>             <span>Me</span>.imgStatus.Height = <span>Me</span>.imgStatus.Width</pre>
<pre><span>  31:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  32:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  33:</span>&nbsp; </pre>
<pre><span>  34:</span>     <span>Private</span> _vy <span>As</span> <span>Double</span></pre>
<pre><span>  35:</span>     <span>Public</span> <span>Property</span> VY() <span>As</span> <span>Double</span></pre>
<pre><span>  36:</span>         <span>Get</span></pre>
<pre><span>  37:</span>             <span>Return</span> <span>Me</span>._vy</pre>
<pre><span>  38:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  39:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  40:</span>             <span>Me</span>._vy = value</pre>
<pre><span>  41:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  42:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  43:</span>&nbsp; </pre>
<pre><span>  44:</span>     <span>Private</span> _vx <span>As</span> <span>Double</span></pre>
<pre><span>  45:</span>     <span>Public</span> <span>Property</span> VX() <span>As</span> <span>Double</span></pre>
<pre><span>  46:</span>         <span>Get</span></pre>
<pre><span>  47:</span>             <span>Return</span> <span>Me</span>._vx</pre>
<pre><span>  48:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  49:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  50:</span>             <span>Me</span>._vx = value</pre>
<pre><span>  51:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  52:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  53:</span>&nbsp; </pre>
<pre><span>  54:</span>     <span>Private</span> _mass <span>As</span> <span>Double</span></pre>
<pre><span>  55:</span>     <span>Public</span> <span>Property</span> Mass() <span>As</span> <span>Double</span></pre>
<pre><span>  56:</span>         <span>Get</span></pre>
<pre><span>  57:</span>             <span>Return</span> <span>Me</span>._mass</pre>
<pre><span>  58:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  59:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  60:</span>             <span>Me</span>._mass = value</pre>
<pre><span>  61:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  62:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  63:</span>&nbsp; </pre>
<pre><span>  64:</span>     <span>Private</span> _x <span>As</span> <span>Double</span></pre>
<pre><span>  65:</span>     <span>Public</span> <span>Property</span> X() <span>As</span> <span>Double</span></pre>
<pre><span>  66:</span>         <span>Get</span></pre>
<pre><span>  67:</span>             <span>Return</span> <span>Me</span>._x</pre>
<pre><span>  68:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  69:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  70:</span>             <span>Me</span>._x = value</pre>
<pre><span>  71:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  72:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  73:</span>&nbsp; </pre>
<pre><span>  74:</span>     <span>Private</span> _y <span>As</span> <span>Double</span></pre>
<pre><span>  75:</span>     <span>Public</span> <span>Property</span> Y() <span>As</span> <span>Double</span></pre>
<pre><span>  76:</span>         <span>Get</span></pre>
<pre><span>  77:</span>             <span>Return</span> <span>Me</span>._y</pre>
<pre><span>  78:</span>         <span>End</span> <span>Get</span></pre>
<pre><span>  79:</span>         <span>Set</span>(<span>ByVal</span> value <span>As</span> <span>Double</span>)</pre>
<pre><span>  80:</span>             <span>Me</span>._y = value</pre>
<pre><span>  81:</span>         <span>End</span> <span>Set</span></pre>
<pre><span>  82:</span>     <span>End</span> <span>Property</span></pre>
<pre><span>  83:</span>&nbsp; </pre>
<pre><span>  84:</span> <span>End</span> <span>Class</span></pre>
<pre><span>  85:</span>&nbsp; </pre>
<pre><span>  86:</span>&nbsp; </pre>
</div>
</div>
<p>Once I had the particle class created, I decided to use a variation of a spring physics equation to get the desired float animation. The spring equation forces the particles toward each other and then springs them past each other similar to how a ball on
 the end of a rubber band would act when pulling it and letting it spring back and forth. Then by tweaking the force and velocity applied to each particle I successfully simulated a floating effect (I am by no means a physicist and I am sure there is a better
 way of implementing this equation). By combining the CompositionTarget.Rendering event and the positioning logic we can effectively scatter and animate the particles on our Canvas. The math involved looks something like this:</p>
<h6></h6>
C#
<div>
<div>
<pre><span>   1:</span> <span>void</span> Spring(Particle a, Particle b)</pre>
<pre><span>   2:</span>         {</pre>
<pre><span>   3:</span> <span>double</span> dx = b.X - a.X;</pre>
<pre><span>   4:</span> <span>double</span> dy = b.Y - a.Y;</pre>
<pre><span>   5:</span>&nbsp; </pre>
<pre><span>   6:</span> <span>double</span> dist = Math.Sqrt(dx * dx &#43; dy * dy);</pre>
<pre><span>   7:</span> <span>if</span> (dist &lt; _minDist)</pre>
<pre><span>   8:</span>             {</pre>
<pre><span>   9:</span> <span>double</span> ax = dx * _spring;</pre>
<pre><span>  10:</span> <span>double</span> ay = dy * _spring;</pre>
<pre><span>  11:</span>&nbsp; </pre>
<pre><span>  12:</span>                 a.VX &#43;= ax;</pre>
<pre><span>  13:</span>                 a.VY &#43;= ay;</pre>
<pre><span>  14:</span>&nbsp; </pre>
<pre><span>  15:</span>                 b.VX -= ax;</pre>
<pre><span>  16:</span>                 b.VY -= ay;</pre>
<pre><span>  17:</span>&nbsp; </pre>
<pre><span>  18:</span> Canvas.SetLeft(a, a.X);</pre>
<pre><span>  19:</span> Canvas.SetTop(a, a.Y);</pre>
<pre><span>  20:</span>&nbsp; </pre>
<pre><span>  21:</span> Canvas.SetLeft(b, b.X);</pre>
<pre><span>  22:</span> Canvas.SetTop(b, b.Y);</pre>
<pre><span>  23:</span>&nbsp; </pre>
<pre><span>  24:</span>&nbsp; </pre>
<pre><span>  25:</span>             }</pre>
<pre><span>  26:</span>&nbsp; </pre>
<pre><span>  27:</span> Canvas.SetLeft(a, a.X);</pre>
<pre><span>  28:</span> Canvas.SetTop(a, a.Y);</pre>
<pre><span>  29:</span>&nbsp; </pre>
<pre><span>  30:</span> Canvas.SetLeft(b, b.X);</pre>
<pre><span>  31:</span> Canvas.SetTop(b, b.Y);</pre>
<pre><span>  32:</span>&nbsp; </pre>
<pre><span>  33:</span>&nbsp; </pre>
<pre><span>  34:</span>         }</pre>
<pre><span>  35:</span>&nbsp; </pre>
<pre><span>  36:</span> VB:</pre>
<pre><span>  37:</span> PrivateSub Spring(ByVal a As Particle, ByVal b As Particle)</pre>
<pre><span>  38:</span> Dim dx AsDouble = b.X - a.X</pre>
<pre><span>  39:</span> Dim dy AsDouble = b.Y - a.Y</pre>
<pre><span>  40:</span>&nbsp; </pre>
<pre><span>  41:</span> Dim dist AsDouble = Math.Sqrt(dx * dx &#43; dy * dy)</pre>
<pre><span>  42:</span> If dist &lt; _minDist Then</pre>
<pre><span>  43:</span> Dim ax AsDouble = dx * _spring</pre>
<pre><span>  44:</span> Dim ay AsDouble = dy * _spring</pre>
<pre><span>  45:</span>&nbsp; </pre>
<pre><span>  46:</span>             a.VX &#43;= ax</pre>
<pre><span>  47:</span>             a.VY &#43;= ay</pre>
<pre><span>  48:</span>&nbsp; </pre>
<pre><span>  49:</span>             b.VX -= ax</pre>
<pre><span>  50:</span>             b.VY -= ay</pre>
<pre><span>  51:</span>&nbsp; </pre>
<pre><span>  52:</span>             Canvas.SetLeft(a, a.X)</pre>
<pre><span>  53:</span>             Canvas.SetTop(a, a.Y)</pre>
<pre><span>  54:</span>&nbsp; </pre>
<pre><span>  55:</span>             Canvas.SetLeft(b, b.X)</pre>
<pre><span>  56:</span>             Canvas.SetTop(b, b.Y)</pre>
<pre><span>  57:</span>&nbsp; </pre>
<pre><span>  58:</span>&nbsp; </pre>
<pre><span>  59:</span> EndIf</pre>
<pre><span>  60:</span>&nbsp; </pre>
<pre><span>  61:</span>         Canvas.SetLeft(a, a.X)</pre>
<pre><span>  62:</span>         Canvas.SetTop(a, a.Y)</pre>
<pre><span>  63:</span>&nbsp; </pre>
<pre><span>  64:</span>         Canvas.SetLeft(b, b.X)</pre>
<pre><span>  65:</span>         Canvas.SetTop(b, b.Y)</pre>
<pre><span>  66:</span>&nbsp; </pre>
<pre><span>  67:</span>&nbsp; </pre>
<pre><span>  68:</span> EndSub</pre>
<pre><span>  69:</span>&nbsp; </pre>
<pre><span>  70:</span> And the main animation loop looks like <span>this</span>:</pre>
<pre><span>  71:</span>&nbsp; </pre>
<pre><span>  72:</span> C#:</pre>
<pre><span>  73:</span> <span>void</span> CompositionTarget_Rendering(<span>object</span> sender, EventArgs e)</pre>
<pre><span>  74:</span>         {</pre>
<pre><span>  75:</span> <span>for</span> (<span>int</span> i = 0; i &lt; _numParticles; i&#43;&#43;)</pre>
<pre><span>  76:</span>             {</pre>
<pre><span>  77:</span>                 _particles[i].X &#43;= _particles[i].VX;</pre>
<pre><span>  78:</span>                 _particles[i].Y &#43;= _particles[i].VY;</pre>
<pre><span>  79:</span>&nbsp; </pre>
<pre><span>  80:</span> Particle p = _particles[i];</pre>
<pre><span>  81:</span>&nbsp; </pre>
<pre><span>  82:</span> <span>if</span> (p.X &gt;<span>this</span>.Width)</pre>
<pre><span>  83:</span>                 {</pre>
<pre><span>  84:</span>                     p.X = 0;</pre>
<pre><span>  85:</span>                 }</pre>
<pre><span>  86:</span>&nbsp; </pre>
<pre><span>  87:</span> elseif (p.X &lt; 0)</pre>
<pre><span>  88:</span>                 {</pre>
<pre><span>  89:</span>                     p.X = <span>this</span>.Width;</pre>
<pre><span>  90:</span>                 }</pre>
<pre><span>  91:</span>&nbsp; </pre>
<pre><span>  92:</span> <span>if</span> (p.Y &gt;<span>this</span>.Height)</pre>
<pre><span>  93:</span>                 {</pre>
<pre><span>  94:</span>                     p.Y = 0;</pre>
<pre><span>  95:</span>                 }</pre>
<pre><span>  96:</span> elseif (p.Y &lt; 0)</pre>
<pre><span>  97:</span>                 {</pre>
<pre><span>  98:</span>                     p.Y = <span>this</span>.Height;</pre>
<pre><span>  99:</span>                 }</pre>
<pre><span> 100:</span>             }</pre>
<pre><span> 101:</span>&nbsp; </pre>
<pre><span> 102:</span>&nbsp; </pre>
<pre><span> 103:</span> <span>for</span> (<span>int</span> i = 0; i &lt; _numParticles - 1; i&#43;&#43;)</pre>
<pre><span> 104:</span>             {</pre>
<pre><span> 105:</span> var partA = _particles[i];</pre>
<pre><span> 106:</span> <span>for</span> (<span>int</span> j = i &#43; 1; j &lt; _numParticles; j&#43;&#43;)</pre>
<pre><span> 107:</span>                 {</pre>
<pre><span> 108:</span> var partB = _particles[j];</pre>
<pre><span> 109:</span>                     Spring(partA, partB);</pre>
<pre><span> 110:</span>&nbsp; </pre>
<pre><span> 111:</span>                 }</pre>
<pre><span> 112:</span>             }</pre>
<pre><span> 113:</span>         }</pre>
</div>
</div>
<p>VB</p>
<div>
<div>
<pre><span>   1:</span> Sub CompositionTarget_Rendering(ByVal sender As System.Object, ByVal e As System.EventArgs)</pre>
<pre><span>   2:</span> For i AsInteger = 0 To _numParticles - 1</pre>
<pre><span>   3:</span>             _particles(i).X &#43;= _particles(i).VX</pre>
<pre><span>   4:</span>             _particles(i).Y &#43;= _particles(i).VY</pre>
<pre><span>   5:</span>&nbsp; </pre>
<pre><span>   6:</span> Dim p As Particle = _particles(i)</pre>
<pre><span>   7:</span>&nbsp; </pre>
<pre><span>   8:</span> If p.X &gt;Me.Width Then</pre>
<pre><span>   9:</span>                 p.X = 0</pre>
<pre><span>  10:</span>&nbsp; </pre>
<pre><span>  11:</span> ElseIf p.X &lt; 0 Then</pre>
<pre><span>  12:</span>                 p.X = Me.Width</pre>
<pre><span>  13:</span> EndIf</pre>
<pre><span>  14:</span>&nbsp; </pre>
<pre><span>  15:</span> If p.Y &gt;Me.Height Then</pre>
<pre><span>  16:</span>                 p.Y = 0</pre>
<pre><span>  17:</span> ElseIf p.Y &lt; 0 Then</pre>
<pre><span>  18:</span>                 p.Y = Me.Height</pre>
<pre><span>  19:</span> EndIf</pre>
<pre><span>  20:</span> Next i</pre>
<pre><span>  21:</span>&nbsp; </pre>
<pre><span>  22:</span>&nbsp; </pre>
<pre><span>  23:</span> For i AsInteger = 0 To _numParticles - 2</pre>
<pre><span>  24:</span> Dim partA = _particles(i)</pre>
<pre><span>  25:</span> For j AsInteger = i &#43; 1 To _numParticles - 1</pre>
<pre><span>  26:</span> Dim partB = _particles(j)</pre>
<pre><span>  27:</span>                 Spring(partA, partB)</pre>
<pre><span>  28:</span>&nbsp; </pre>
<pre><span>  29:</span> Next j</pre>
<pre><span>  30:</span> Next</pre>
<pre><span>  31:</span>&nbsp; </pre>
<pre><span>  32:</span> EndSub</pre>
<pre><span>  33:</span>&nbsp; </pre>
</div>
</div>
<h4>&nbsp;</h4>
<h4>Supporting Multiple Monitors</h4>
<p>After the animation was rendering correctly the next step was getting it to run on multiple monitors. To make this happen I wrote some code in the application entry point to get a handle to the active screens. The System.Windows.Forms namespace has a Screen
 class which contains a collection of screens and their attributes including working area, width, and height. By looping through the screen collection I measure the screen boundaries and set the window size dynamically based on the available screen real estate.</p>
<p>C#</p>
<div>
<div>
<pre><span>   1:</span> <span>private</span> <span>void</span> Application_Startup(<span>object</span> sender, StartupEventArgs e)</pre>
<pre><span>   2:</span>         {</pre>
<pre><span>   3:</span>&nbsp; </pre>
<pre><span>   4:</span> Window1 _window = <span>null</span>;</pre>
<pre><span>   5:</span>&nbsp; </pre>
<pre><span>   6:</span>             System.Windows.Forms.Cursor.Hide();</pre>
<pre><span>   7:</span>&nbsp; </pre>
<pre><span>   8:</span> <span>foreach</span> (Screen screen inScreen.AllScreens)</pre>
<pre><span>   9:</span>             {</pre>
<pre><span>  10:</span> <span>if</span> (screen.Primary)</pre>
<pre><span>  11:</span>                 {</pre>
<pre><span>  12:</span> Rectangle location = screen.Bounds;</pre>
<pre><span>  13:</span>                     _window = newWindow1(location.Height, location.Width);</pre>
<pre><span>  14:</span>                     _window.Width = location.Width;</pre>
<pre><span>  15:</span>                     _window.Height = location.Height;</pre>
<pre><span>  16:</span>                     _window.Left = 0;</pre>
<pre><span>  17:</span>                     _window.Top = 0;</pre>
<pre><span>  18:</span>                     _window.WindowState = WindowState.Maximized;</pre>
<pre><span>  19:</span>                     _window.Show();</pre>
<pre><span>  20:</span>                 }</pre>
<pre><span>  21:</span>&nbsp; </pre>
<pre><span>  22:</span> elseif (!screen.Primary)</pre>
<pre><span>  23:</span>                 {</pre>
<pre><span>  24:</span>&nbsp; </pre>
<pre><span>  25:</span> Rectangle location = screen.Bounds;</pre>
<pre><span>  26:</span>                     _window = newWindow1(location.Height, location.Width);</pre>
<pre><span>  27:</span>                     _window.Left = screen.WorkingArea.Left;</pre>
<pre><span>  28:</span>                     _window.Top = screen.WorkingArea.Top;</pre>
<pre><span>  29:</span>                     _window.Width = location.Width;</pre>
<pre><span>  30:</span>                     _window.Height = location.Height;</pre>
<pre><span>  31:</span>                     _window.Show();</pre>
<pre><span>  32:</span>                 }</pre>
<pre><span>  33:</span>&nbsp; </pre>
<pre><span>  34:</span>             }</pre>
<pre><span>  35:</span>&nbsp; </pre>
<pre><span>  36:</span>         }</pre>
</div>
</div>
<p>VB</p>
<div>
<div>
<pre><span>   1:</span> <span>private</span> void Application_Startup(<span>object</span> sender, StartupEventArgs e)</pre>
<pre><span>   2:</span>         {</pre>
<pre><span>   3:</span>&nbsp; </pre>
<pre><span>   4:</span> Window1 _window = null;</pre>
<pre><span>   5:</span>&nbsp; </pre>
<pre><span>   6:</span>             System.Windows.Forms.Cursor.Hide();</pre>
<pre><span>   7:</span>&nbsp; </pre>
<pre><span>   8:</span> foreach (Screen screen inScreen.AllScreens)</pre>
<pre><span>   9:</span>             {</pre>
<pre><span>  10:</span> <span>if</span> (screen.Primary)</pre>
<pre><span>  11:</span>                 {</pre>
<pre><span>  12:</span> Rectangle location = screen.Bounds;</pre>
<pre><span>  13:</span>                     _window = newWindow1(location.Height, location.Width);</pre>
<pre><span>  14:</span>                     _window.Width = location.Width;</pre>
<pre><span>  15:</span>                     _window.Height = location.Height;</pre>
<pre><span>  16:</span>                     _window.Left = 0;</pre>
<pre><span>  17:</span>                     _window.Top = 0;</pre>
<pre><span>  18:</span>                     _window.WindowState = WindowState.Maximized;</pre>
<pre><span>  19:</span>                     _window.Show();</pre>
<pre><span>  20:</span>                 }</pre>
<pre><span>  21:</span>&nbsp; </pre>
<pre><span>  22:</span> <span>elseif</span> (!screen.Primary)</pre>
<pre><span>  23:</span>                 {</pre>
<pre><span>  24:</span>&nbsp; </pre>
<pre><span>  25:</span> Rectangle location = screen.Bounds;</pre>
<pre><span>  26:</span>                     _window = newWindow1(location.Height, location.Width);</pre>
<pre><span>  27:</span>                     _window.Left = screen.WorkingArea.Left;</pre>
<pre><span>  28:</span>                     _window.Top = screen.WorkingArea.Top;</pre>
<pre><span>  29:</span>                     _window.Width = location.Width;</pre>
<pre><span>  30:</span>                     _window.Height = location.Height;</pre>
<pre><span>  31:</span>                     _window.Show();</pre>
<pre><span>  32:</span>                 }</pre>
<pre><span>  33:</span>&nbsp; </pre>
<pre><span>  34:</span>             }</pre>
<pre><span>  35:</span>&nbsp; </pre>
<pre><span>  36:</span>         }</pre>
</div>
</div>
<h4></h4>
<h4></h4>
<h4>Making it a Screen Saver</h4>
<p>The last step to this application is making it a screen saver. By implementing mouse and keyboard event handlers to shut down the application we essentially can mimic the interaction of a screen saver.
</p>
<p>C#</p>
<div>
<div>
<pre><span>   1:</span> MouseMove &#43;= newMouseEventHandler(Window2_MouseMove);</pre>
<pre><span>   2:</span>   MouseDown &#43;= newMouseButtonEventHandler(Window2_MouseDown);</pre>
<pre><span>   3:</span>   KeyDown &#43;= newKeyEventHandler(Window2_KeyDown);</pre>
<pre><span>   4:</span> <span>void</span> Window2_KeyDown(<span>object</span> sender, KeyEventArgs e)</pre>
<pre><span>   5:</span>         {</pre>
<pre><span>   6:</span> Application.Current.Shutdown();</pre>
<pre><span>   7:</span>         }</pre>
<pre><span>   8:</span>&nbsp; </pre>
<pre><span>   9:</span> <span>void</span> Window2_MouseDown(<span>object</span> sender, MouseButtonEventArgs e)</pre>
<pre><span>  10:</span>         {</pre>
<pre><span>  11:</span> Application.Current.Shutdown();</pre>
<pre><span>  12:</span>         }</pre>
<pre><span>  13:</span>&nbsp; </pre>
<pre><span>  14:</span> <span>void</span> Window2_MouseMove(<span>object</span> sender, MouseEventArgs e)</pre>
<pre><span>  15:</span>         {</pre>
<pre><span>  16:</span> Point currentPosition = e.MouseDevice.GetPosition(<span>this</span>);</pre>
<pre><span>  17:</span>&nbsp; </pre>
<pre><span>  18:</span> <span>if</span> (!isActive)</pre>
<pre><span>  19:</span>             {</pre>
<pre><span>  20:</span>                 mousePosition = currentPosition;</pre>
<pre><span>  21:</span>                 isActive = <span>true</span>;</pre>
<pre><span>  22:</span>             }</pre>
<pre><span>  23:</span> <span>else</span></pre>
<pre><span>  24:</span>             {</pre>
<pre><span>  25:</span>&nbsp; </pre>
<pre><span>  26:</span> <span>if</span> ((Math.Abs(mousePosition.X - currentPosition.X) &gt; 10) ||</pre>
<pre><span>  27:</span>                     (Math.Abs(mousePosition.Y - currentPosition.Y) &gt; 10))</pre>
<pre><span>  28:</span>                 {</pre>
<pre><span>  29:</span> Application.Current.Shutdown();</pre>
<pre><span>  30:</span>                 }</pre>
<pre><span>  31:</span>             }</pre>
<pre><span>  32:</span>         }</pre>
</div>
</div>
<p>VB</p>
<div>
<div>
<pre><span>   1:</span> AddHandlerMe.MouseMove, <span>AddressOf</span> Window_MouseMove</pre>
<pre><span>   2:</span> AddHandlerMe.MouseDown, <span>AddressOf</span> Window_MouseDown</pre>
<pre><span>   3:</span> AddHandlerMe.KeyDown, <span>AddressOf</span> Window_KeyDown</pre>
<pre><span>   4:</span>&nbsp; </pre>
<pre><span>   5:</span> PrivateSub Window_KeyDown(<span>ByVal</span> sender AsObject, <span>ByVal</span> e <span>As</span> KeyEventArgs)</pre>
<pre><span>   6:</span>         Application.Current.Shutdown()</pre>
<pre><span>   7:</span> EndSub</pre>
<pre><span>   8:</span>&nbsp; </pre>
<pre><span>   9:</span> PrivateSub Window_MouseDown(<span>ByVal</span> sender AsObject, <span>ByVal</span> e <span>As</span> MouseButtonEventArgs)</pre>
<pre><span>  10:</span>         Application.Current.Shutdown()</pre>
<pre><span>  11:</span> EndSub</pre>
<pre><span>  12:</span>&nbsp; </pre>
<pre><span>  13:</span> PrivateSub Window_MouseMove(<span>ByVal</span> sender AsObject, <span>ByVal</span> e <span>As</span> MouseEventArgs)</pre>
<pre><span>  14:</span> <span>Dim</span> currentPosition <span>As</span> Point = e.MouseDevice.GetPosition(<span>Me</span>)</pre>
<pre><span>  15:</span> <span>If</span> (<span>Not</span> isActive) <span>Then</span></pre>
<pre><span>  16:</span>             mousePosition = currentPosition</pre>
<pre><span>  17:</span>             isActive = <span>True</span></pre>
<pre><span>  18:</span> <span>Else</span></pre>
<pre><span>  19:</span> <span>If</span> (Math.Abs(mousePosition.X - currentPosition.X) &gt; 10) <span>OrElse</span> (Math.Abs(mousePosition.Y - currentPosition.Y) &gt; 10) <span>Then</span></pre>
<pre><span>  20:</span>                 Application.Current.Shutdown()</pre>
<pre><span>  21:</span> <span>EndIf</span></pre>
<pre><span>  22:</span> <span>EndIf</span></pre>
<pre><span>  23:</span> EndSub</pre>
<pre><span>  24:</span>&nbsp; </pre>
</div>
</div>
<p>Lastly, simply set the build configuration to Release mode and build it. In the output bin-&gt;Release directory find the built executable. Rename the file extension from .exe to .scr then right click and choose
<b>Install</b> from the context menu.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image008.jpg"><img title="clip_image008" border="0" alt="clip_image008" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image008_thumb.jpg" width="423" height="319"></a></p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image010.jpg"><img title="clip_image010" border="0" alt="clip_image010" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/8626294/clip_image010_thumb.jpg" width="413" height="217"></a></p>
<p>That's it! </p>
<h4>Challenges to You</h4>
<p>One of the interesting things about Office Communicator Server is that it comes with an SDK to build your own custom Unified Communications applications.</p>
<ul>
<li>I would love to see the presence bubbles actually hooked up to real users' status, and maybe a cool animation to indicate when a users' status is changed.
</li><li>Create a config file to let the user specify his/her own images and tweak other settings like speed and velocity.&nbsp;
</li></ul>
<h4>Conclusion</h4>
<p>This was a great opportunity to brush up on my physics skills and play with some of the animation possibilities in WPF. This application is also a great example of alternative data visualization. Sometimes I get tired of seeing everything in tabular form
 and I think that “presence art” is a great example of Art &#43; Code (aesthetically pleasing and functional). I hope you enjoy it.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Erik-Klimczak/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:19ddc2e88de5497fb0669e7600cf331e">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/WPF-Custom-Screen-Saver-Art</comments>
      <itunes:summary>
Summary
Creating custom
 wallpaper is easy. But what about custom screen savers? This post will detail how to build a custom saver using Windows Presentation Framework (WPF). The posted code also provides some insight on how to create interesting particle effects using WPF&#39;s animation
 engine, and how to implement multiple monitor support in .Net. 
Erik Klimczak - Clarity Consulting 
Download

http://wpfscreensaverart.codeplex.com/&amp;nbsp;&amp;nbsp;

Introduction
Microsoft Unified Communications (UC) is a new technology that has been getting a lot of hype in the past couple of months. UC is essentially the integration of messaging, voice, and video across the
 applications and devices that people use every day. More information about UC can be found
here. One of the coolest things about UC is the concept of “presence” (see below). The Presence indicator effectively allows the user to reflect his/her status in other Office Communicator Server friendly
 applications (i.e. Outlook, Office communicator, Live Meeting, etc.) 
 
While building out some communicator functionality on another project I found myself recreating the presence “bubbles” in xaml so that they could scale without losing quality (see below). I used Expression Design to re-create the presence bubbles and export
 then to xaml. 
In doing so it occurred to me that the presence “bubbles” would make for some excellent art sprites.
 
&amp;nbsp; 
So after a hop-skip-and a jump to Photoshop I found myself with a shiny new “presence art” wallpaper. 
 
Immediately after creating the wallpaper I thought to myself, “this would also make a great screen saver”. This article will attempt to show how to build a custom WPF screen saver that implements a simple physics particle effect using the WPF animation engine. 
Particle Animation
With my graphic designer hat on I knew that I wanted to create a floating particle effect. Particle effects can be used to simulate anything from rain, snow, fire to bubbles and clouds. Then by va</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/WPF-Custom-Screen-Saver-Art</link>
      <pubDate>Fri, 20 Jun 2008 15:24:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/WPF-Custom-Screen-Saver-Art</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/8626294_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/8626294_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Erik Klimczak </dc:creator>
      <itunes:author>Erik Klimczak </itunes:author>
      <slash:comments>12</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/WPF-Custom-Screen-Saver-Art/RSS</wfw:commentRss>
      <category>Windows</category>
      <category>windows miscellaneous</category>
    </item>    
</channel>
</rss>