<?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 - Entries tagged with Holiday</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Tags/holiday/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 - Entries tagged with Holiday</title>
      <link>http://channel9.msdn.com/Tags/holiday</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/Tags/holiday</link>
    <language>en</language>
    <pubDate>Tue, 18 Jun 2013 22:54:05 GMT</pubDate>
    <lastBuildDate>Tue, 18 Jun 2013 22:54:05 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>21</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Fed Up With Snow Already? Warm Up Your Desktop With Holiday Lights</title>
      <description><![CDATA[ <p>I’m not sure what the weather’s like in your neighbourhood, but for the first time I can remember in many years, here in the UK we’ve just had a deluge of November snow, and apparently there’s more to come!</p><p>So, what better time to warm up your desktop with the new <a href="http://windows.microsoft.com/en-us/windows/downloads/holiday-lights">Windows 7 Holiday Lights</a> desktop theme? 17 new desktop wallpapers each featuring a wintry theme are on offer, with “sparkling images of holiday celebration and winter wonder” according to the website.</p><p>My personal favourite is the snowy river scene, shot deep in a forest. It looks like the coldest place on earth, apart from the glow from a sole fir tree, fully illuminated and bathing the adjacent river with light. </p><p>I don’t know who had the impossible job of wiring that tree up, but next weekend, when I’m nailing up our own lights in the garden, I won’t feel so bad!</p><p>&nbsp;</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:63fb32534b8047a1a1a39e3e013d3160">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/Fed-Up-With-Snow-Already-Warm-Up-Your-Desktop-With-Holiday-Lights</comments>
      <itunes:summary> I’m not sure what the weather’s like in your neighbourhood, but for the first time I can remember in many years, here in the UK we’ve just had a deluge of November snow, and apparently there’s more to come! So, what better time to warm up your desktop with the new Windows 7 Holiday Lights desktop theme? 17 new desktop wallpapers each featuring a wintry theme are on offer, with “sparkling images of holiday celebration and winter wonder” according to the website. My personal favourite is the snowy river scene, shot deep in a forest. It looks like the coldest place on earth, apart from the glow from a sole fir tree, fully illuminated and bathing the adjacent river with light.  I don’t know who had the impossible job of wiring that tree up, but next weekend, when I’m nailing up our own lights in the garden, I won’t feel so bad! &amp;nbsp; </itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/Fed-Up-With-Snow-Already-Warm-Up-Your-Desktop-With-Holiday-Lights</link>
      <pubDate>Tue, 30 Nov 2010 19:18:15 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/Fed-Up-With-Snow-Already-Warm-Up-Your-Desktop-With-Holiday-Lights</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/a69e3b84-9c16-4b4f-8ad3-d27e9e127024.png" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/9016ec70-ff2b-4448-b3eb-6a552b116794.png" height="165" width="220"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/4feeaea1-3985-42a9-92ad-4994342a61eb.png" height="240" width="320"></media:thumbnail>      
      <dc:creator>Terry Walsh</dc:creator>
      <itunes:author>Terry Walsh</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/Fed-Up-With-Snow-Already-Warm-Up-Your-Desktop-With-Holiday-Lights/RSS</wfw:commentRss>
      <category>Personalization</category>
      <category>Wallpaper</category>
      <category>wallpapers</category>
      <category>Windows 7</category>
      <category>Holiday</category>
      <category>christmas</category>
    </item>
  <item>
      <title>Ensure You’re No Longer Fingers and Thumbs in the Cold</title>
      <description><![CDATA[ <p>Tricky situations in modern life #237: Using smartphones and other portable devices outdoors in the winter. Despite the best efforts of UI designers and engineers, it’s nigh on impossible to operate a handheld device with gloves on. In years gone by, that was probably okay – if it was a call on our mobile phone, we can call them back when we’re indoors. But nowadays, your phone is a heck of a lot more useful in the moment than, well, a phone used to be.</p><p>Let’s say you get lost in a blizzard - &nbsp;GPS to the rescue! Ah, that’s going to require at least 1 minute of gloveless typing in the middle of a deep freeze. Not good. Okay, pull off a glove, find the app, get a position, try to type in your desired destination – hand freezes up, impossible to type any more. </p><p>The answer to this seasonal quandary is most definitely <a href="http://www.freehands.com/categories/Collections/">Freehands</a>. Filed under “ideas so bad they’re actually quite good” Freehands offer a wide range of gloves with removeable thumb and index finger. Fleece? Cashmere? Wool? Soft Shell? They have the lot. </p><p>Now your Winter portable electronics emergency is easily resolved. Terrible track comes on the headphones requiring a shuffle? Must-have photo of snowball fight required? Mobile video opportunity of the kids sledging? Just pop off a finger and thumb, and you’re all set with only minor cooling impact.</p><p>They’re sure to be seen in a Sky Mall catalogue soon, so check them out before they go mainstream!</p><p>&nbsp;</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:8f18522548d94034a01c9e2c014107a6">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/Ensure-Youre-No-Longer-Fingers-and-Thumbs-in-the-Cold</comments>
      <itunes:summary> Tricky situations in modern life #237: Using smartphones and other portable devices outdoors in the winter. Despite the best efforts of UI designers and engineers, it’s nigh on impossible to operate a handheld device with gloves on. In years gone by, that was probably okay – if it was a call on our mobile phone, we can call them back when we’re indoors. But nowadays, your phone is a heck of a lot more useful in the moment than, well, a phone used to be. Let’s say you get lost in a blizzard - &amp;nbsp;GPS to the rescue! Ah, that’s going to require at least 1 minute of gloveless typing in the middle of a deep freeze. Not good. Okay, pull off a glove, find the app, get a position, try to type in your desired destination – hand freezes up, impossible to type any more.  The answer to this seasonal quandary is most definitely Freehands. Filed under “ideas so bad they’re actually quite good” Freehands offer a wide range of gloves with removeable thumb and index finger. Fleece? Cashmere? Wool? Soft Shell? They have the lot.  Now your Winter portable electronics emergency is easily resolved. Terrible track comes on the headphones requiring a shuffle? Must-have photo of snowball fight required? Mobile video opportunity of the kids sledging? Just pop off a finger and thumb, and you’re all set with only minor cooling impact. They’re sure to be seen in a Sky Mall catalogue soon, so check them out before they go mainstream! &amp;nbsp; </itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/Ensure-Youre-No-Longer-Fingers-and-Thumbs-in-the-Cold</link>
      <pubDate>Fri, 12 Nov 2010 19:30:17 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/Ensure-Youre-No-Longer-Fingers-and-Thumbs-in-the-Cold</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/a83ef774-c04a-48ed-bec9-4b765694fd92.png" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/36cbb778-a59b-4041-8f99-44e13b2c0438.png" height="165" width="220"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/e77dfdbc-6414-4e12-a8e1-abbae8fa515a.png" height="240" width="320"></media:thumbnail>      
      <dc:creator>Terry Walsh</dc:creator>
      <itunes:author>Terry Walsh</itunes:author>
      <slash:comments>1</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/Ensure-Youre-No-Longer-Fingers-and-Thumbs-in-the-Cold/RSS</wfw:commentRss>
      <category>Portable</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Halloween Gremlins</title>
      <description><![CDATA[
<p>This article describes a quick and easy application to play Halloween tricks on the PC.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_2.jpg"><img title="clip_image001" border="0" alt="clip_image001" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_thumb.jpg" width="282" height="135"></a></p>
<h3>Introduction</h3>
<p>This article describes “Gremlin”, a quick and easy application that lets you play Halloween tricks. When your victim's computer is idle, Gremlin moves windows around on the screen, changes the focus window, moves your mouse, scrolls windows, and types nonsensical
 stuff. When there is background noise – like someone talking – it will shake the screen, even as your victim is typing away.</p>
<h3>Deployment</h3>
<p><b>Run it right away</b>. You can download, copy theGremlin.exe executable and NAudio.dll to the victim's computer (say in c:\ directory), and then double click on the executable to run it.</p>
<p><b>Run it later.</b> The other option is to copy the executable and dll files (or a shortcut to it) to the Startup folder on the victim's machine and watch the fun begin when they start up their machine in the morning!</p>
<p>If the computer you're using runs on Windows XP the path is: </p>
<blockquote>
<p>C:\Documents and Settings\All Users\Start Menu\Programs\Startup</p>
</blockquote>
<p>With Vista and Windows 7 the path looks like: </p>
<blockquote>
<p>C:\Users\<i>USERNAME</i>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup</p>
</blockquote>
<p>Just remember to change <i>USERNAME</i> to the name of the user on your machine.</p>
<p></p>
<h4>Commandline</h4>
<p>Gremlin is compiled as a windows application, so it won't popup a terminal window if you double click on it, etc. But you can run it from the command line with flags:</p>
<blockquote>
<p><b>-aggressive</b> will make the gremlin's actions more obvious</p>
<p><b>-help</b> will display the command line options</p>
<p><b>-name</b> <i>NAME</i> is useful for testing. Gremlin will only use windows with this specific title or from this specific application. (Remember to drop the &quot;.exe&quot; from the application filename)</p>
</blockquote>
<p>To stop the program, press CTRL&#43;F2.</p>
<h3>And now … the dodgy bits</h3>
<p>The overall structure of the program is broken down into three kinds of functionality – actions, triggers and some interstitial glue:</p>
<p>Actions</p>
<ul>
<li>The screen-shaker is a window that makes the monitor look like it is shaking. Sort of like a loose cable on the back of the monitor.
</li><li>A random event might kick the windows around—either friction will slow them down, or...
</li><li>Gremlin will type nonsensical messages from the keyboard. These messages are then sent from a virtual keyboard, or they:
</li><li>Move the mouse around, or </li><li>Press the mouse buttons, or </li><li>Randomly switch the focus to another window </li></ul>
<p>Triggers</p>
<ul>
<li>An audio module listens for sounds that trigger the module that shakes your screen.
</li><li>Otherwise, the software uses a p/invoke to <strong>GetLastInputInfo()</strong> and waits for the user to be idle for a minute or two. When it detects that the user is inactive, it randomly selects and carries out actions.
</li></ul>
<p>Other</p>
<ul>
<li>A hidden window receives key press events. I tend to reuse this module a lot, as a way to
<i>stop</i> experimental programs that may have made my machine unusable. </li></ul>
<p>For fun, I'll describe a couple of these modules below.</p>
<p></p>
<h4>Screen shaker</h4>
<p>My favorite bit is the screen shaker. It grabs a picture of the screens, creates a window that spreads across them, and then moves that image back and forth a few pixels every 30ms or so, with a little bit of random rotation. (Faster computers, of course,
 get a better effect).</p>
<p>The screen shaker is special in four ways:</p>
<ul>
<li>It is a top-level window – no other windows are allowed to go over it. </li><li>This top-level window never becomes the focus window (the window that gets the keyboard events).
</li><li>Mouse button events (e.g. clicks and double-clicks) are passed through to the windows and desktop underneath. This gives the illusion that this is the &quot;real&quot; desktop shaking, by allowing a person to click on a button or text that passes the click thru to
 the <i>real</i> button or text. </li><li>It shakes each of the monitor's screens independently </li></ul>
<p>Some background: to create a window that looks like the shaking screen, I used two classes. The first is ScrShake (in ScreenShake.cs), which derives from the second class UnfocusableForm.&nbsp; I'll describe ScrShake first.</p>
<p>The screen shaking process requires five instance variables:</p>
<ul>
<li><i>animTimer</i> is a System.Windows.Forms.Timer used to force painting of a new frame on the screen.
</li><li><i>bx</i>, and <i>by </i>are how far the screen has shaken up or down, left or right.
</li><li><i>angle </i>is how much the screen has twisted during shaking. </li><li><i>screenBitmap</i> is an array of bitmaps, one for each of the monitors. </li></ul>
<p>This creates a window without a border or other trappings, then makes it the topmost window and sets a flag in the method variable ExStyle to ignore mouse clicks. More on this flag in a little while.</p>
<p></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> ScrShake : UnfocusableForm
{
   <span class="kwrd">public</span> ScrShake(<span class="kwrd">double</span> ShakeCoef, <span class="kwrd">double</span> AngleCoef) : <span class="kwrd">base</span>(<span class="kwrd">true</span>)
   {
      <span class="kwrd">this</span>.SuspendLayout();
      … other setup code …
      <span class="rem">// This is needed since we're over the whole display, and we don't</span>
      <span class="rem">// want the other areas to be blurry</span>
      TransparencyKey =  BackColor = ForeColor = System.Drawing.Color.Fuchsia;
      DoubleBuffered = <span class="kwrd">true</span>;
      TopMost = <span class="kwrd">true</span>;
      FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

      ClientSize = <span class="kwrd">new</span> System.Drawing.Size(300, 300);
      Name = <span class="str">&quot;topimage&quot;</span>;
      ResumeLayout(<span class="kwrd">false</span>);

      <span class="rem">// This is need to pass mouse clicks thru to lower layers</span>
      ExStyle |= (<span class="kwrd">int</span>) WS . EX_TRANSPARENT;

      … More code that will be described later…
   }
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b><br>
</b></p>
<p>When the timer has done a given number of animations, it will call the Stop() method. This will stop the animation, clean it up, and hide the window:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">void</span> Stop()
{
   animTimer . Stop();
   Hide();
   screenBitmap = <span class="kwrd">null</span>;
}</pre>
<p>When the main loops that start the animated screen shaking process, it calls the Screens() method. This grabs an image of the screens, determines the shape of each monitor, and starts the animation for 10 frames.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">void</span> Screens()
{
   <span class="kwrd">if</span> (Visible)
   {
      Stop();
      <span class="kwrd">return</span> ;
   }
   <span class="rem">// Grab the screens</span>
   screenBitmap = Program.GrabScreens();
   CountDown = 10;

   animTimer.Start();
   angle = 0.0f;
   … code to display the window and get shape of monitors (see below)…
}</pre>
<p><b><br>
</b></p>
<p>The screen capture portion is in ScreenCapture.cs. The method GrabScreens() creates an individual bitmap for each monitor and returns them as an array.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">void</span> Screens()
{
   <span class="kwrd">if</span> (Visible)
   {
      Stop();
      <span class="kwrd">return</span> ;
   }
   <span class="rem">// Grab the screens</span>
   screenBitmap = Program.GrabScreens();
   CountDown = 10;

   animTimer.Start();
   angle = 0.0f;
   … code to display the window and get shape of monitors (see below)…
}</pre>
<p><b><br>
</b></p>
<p>The code below determines the bounds of each screen and builds up a size of all of the screens put together. The window will be set to be this size.
</p>
<p><b>C# </b></p>
<pre class="csharpcode">Screen[] AllScreens = Screen.AllScreens;

<span class="rem">// full width/height of all monitors combined</span>
Rectangle fullSize = AllScreens[0].Bounds;

<span class="rem">// find a rectangle that will encompass all monitors on the system</span>
<span class="rem">// (assuming the primary monitor is on the left/top!)</span>
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i &lt; AllScreens.Length &amp;&amp; i &lt; screenBitmap.Length; i&#43;&#43;)
{
    Rectangle Bounds = AllScreens[i].Bounds;

    <span class="kwrd">if</span> (Bounds.Left &lt; fullSize.Left)
        fullSize.X = Bounds.X;

    <span class="kwrd">if</span> (Bounds.Right &gt; fullSize.Right)
        fullSize.Width = Bounds.Right - fullSize.X;

    <span class="kwrd">if</span> (Bounds.Top &lt; fullSize.Top)
        fullSize.Y = Bounds.Y;

    <span class="kwrd">if</span> (Bounds.Bottom &gt; fullSize.Bottom)
        fullSize.Height = Bounds.Bottom - fullSize.Y;
}</pre>
<p>The code to show the window, fill the whole screen, and move it to the top looks like:</p>
<p><b>C# </b></p>
<pre class="csharpcode">Show();
WindowState = FormWindowState.Normal;
<span class="rem">// cover all monitors with one gigantic window</span>
Location = <span class="kwrd">new</span> Point(fullSize.Left, fullSize.Top);
Size = <span class="kwrd">new</span> Size(fullSize.Width, fullSize.Height);

<span class="rem">// bring it to the top</span>
BringToFront();</pre>
<p>The constructor also created a timer that drives the screen shaking effect. The timer has a delegate that randomly selects the angle of rotation and the offset of the image, and triggers a repaint of the window. (The amount of shaking is controlled by two
 external variables called <i>AngleCoef</i> and <i>ShakeCoef</i>).</p>
<p><b>C# </b></p>
<pre class="csharpcode">animTimer = <span class="kwrd">new</span> System.Windows.Forms.Timer();
animTimer.Tick &#43;= <span class="kwrd">delegate</span>(<span class="kwrd">object</span> A, EventArgs E)
{
    <span class="kwrd">if</span> (--CountDown &lt; 1)
        Stop();

    angle &#43;= (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * AngleCoef);
    bx = (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * ShakeCoef);
    by = (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * ShakeCoef);
    Invalidate();
};

<span class="rem">// Sets the timer interval to 30 milliseconds.</span>
animTimer.Interval = 30;</pre>
<p>Although each monitor shifts up &amp; down, left &amp; right by the same amount, and rotates by the same angle, they are painted independently. This gives the illusion that each monitor has a shaky image. Paint the window is using the following code.
</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPaint(PaintEventArgs e)
{
    <span class="kwrd">base</span>.OnPaint(e);
    Graphics g = e.Graphics;
    g.CompositingQuality = CompositingQuality.HighQuality;

    <span class="rem">// for each monitor, draw the effect</span>
    Screen[] AllScreens = Screen.AllScreens;
    <span class="kwrd">for</span>(<span class="kwrd">int</span> i = 0; i &lt; screenBitmap.Length; i&#43;&#43;)
    {
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == screenBitmap[i])&nbsp;&nbsp; <span class="kwrd">continue</span>;
        g.SmoothingMode = SmoothingMode.HighQuality;

        <span class="rem">// grab the size of the current monitor</span>
        Rectangle region = AllScreens[i].Bounds;

        <span class="kwrd">double</span> ImWidth = screenBitmap[i].Width  * <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Graphics.DpiX / screenBitmap[i].HorizontalResolution;
        <span class="kwrd">double</span> ImHeight= screenBitmap[i].Height * <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Graphics.DpiY / screenBitmap[i].VerticalResolution;
        Matrix m = <span class="kwrd">new</span> Matrix();
        m.Translate( (<span class="kwrd">float</span>)(- ImWidth  /2), 
                  (<span class="kwrd">float</span>)(- ImHeight /2), MatrixOrder.Append);

        <span class="rem">// rotate the bitmap about the center</span>
        m.RotateAt(angle, <span class="kwrd">new</span> Point(0,0), MatrixOrder.Append);

        <span class="rem">// center the image no matter what its size is</span>
        m.Translate( region.Width /2 - bx, 
                  region.Height/2 - by, MatrixOrder.Append);

        <span class="rem">// assign our transformation matrix</span>
        g.Transform = m;

        <span class="rem">// draw it</span>
        g.DrawImage(screenBitmap[i], region.Left, region.Top);
    }</pre>
<h4>The Form that does nothing!</h4>
<p>The ScrShaker class uses a help class called UnfocusableForm (in UnfocusableForm.cs) to create a window that never becomes the focus window – it never receives key presses, etc.</p>
<p>This window has no trappings – no border, no resize gripper, no icon, no minimize / maximize buttons, no title bar.</p>
<p></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> UnfocusableForm : Form
{
   <span class="kwrd">public</span> UnfocusableForm(<span class="kwrd">bool</span> X) : <span class="kwrd">base</span>()
   {
      <span class="kwrd">if</span> (X)
        {
           ControlBox = <span class="kwrd">false</span>;
           FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
           ShowInTaskbar = <span class="kwrd">false</span>;
           ShowIcon = <span class="kwrd">false</span>;
           MinimizeBox = <span class="kwrd">false</span>;
           SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
           StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        }
   }</pre>
<p>Then it overrides the ShowWithoutActivation method so that the window will <i>
not</i> become the active when it is shown.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> ShowWithoutActivation
{ get {  <span class="kwrd">return</span> <span class="kwrd">true</span>; } }</pre>
<p>The UnfocusableForm class also overrides the CreateParams() method to set extra styles when creating the window. I haven't found a way to set these styles flexibly. Instead, the UnfocusableForm uses a method variable called ExStyle that allows derived classes
 to specify what flags they desire. In this case, The ScrShake class used the method variable to set a flag that ignore mouse clicks:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> CreateParams CreateParams
{
  get
  {
     CreateParams cp=<span class="kwrd">base</span>.CreateParams;
     cp . ExStyle |= ExStyle;
     <span class="kwrd">return</span> cp;
  }
}</pre>
<p><b><br>
</b>Finally, it captures a couple of events that ask a window if it would like to become the active window. (These usually happen when the user clicks on an inactive window):</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">const</span> <span class="kwrd">int</span> MA_NOACTIVATE = 0x0003;
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> WndProc(<span class="kwrd">ref</span> Message m)
{
  <span class="kwrd">if</span> (m.Msg == (<span class="kwrd">int</span>) WM.MOUSEACTIVATE)
  {
     m.Result = (IntPtr) MA_NOACTIVATE;
     <span class="kwrd">return</span>;
  }
  <span class="kwrd">if</span> (m.Msg == (<span class="kwrd">int</span>) WM.FOCUS)
  {
     m.Result = (IntPtr)1;
     <span class="kwrd">return</span>;
  }
  <span class="kwrd">base</span>.WndProc(<span class="kwrd">ref</span> m);
}</pre>
<h4>Sending Mouse Events</h4>
<p>Sending Mouse Events is simple, but not trivial. The wiki at Pinvoke.net provides the signature to the procedures and structures we need to pass to it. (Note: these structures are a bit different, based on
<a href="http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx">a blog posting by Raymond Chen</a>)</p>
<p><b>C# </b></p>
<pre class="csharpcode">[DllImport(<span class="str">&quot;user32.dll&quot;</span>, EntryPoint = <span class="str">&quot;SendInput&quot;</span>, SetLastError = <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">uint</span> SendInput(<span class="kwrd">uint</span> nInputs, INPUT[] Inputs, <span class="kwrd">int</span> cbSize);
[DllImport(<span class="str">&quot;user32.dll&quot;</span>, EntryPoint = <span class="str">&quot;GetMessageExtraInfo&quot;</span>, SetLastError = <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr GetMessageExtraInfo();

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> INPUT
{
   <span class="kwrd">internal</span> INPUTTYPE   type;
   <span class="kwrd">internal</span> INPUT_UNION i;
}

 <span class="rem">// This generates the anonymous union</span>
[StructLayout(LayoutKind.Explicit)]
<span class="kwrd">struct</span> INPUT_UNION
{
   [FieldOffset(0)]
   <span class="kwrd">public</span> MOUSEINPUT mi;
   [FieldOffset(0)]
   <span class="kwrd">public</span> KEYBDINPUT ki;
   [FieldOffset(0)]
   <span class="kwrd">public</span> HARDWAREINPUT hi;
};

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> MOUSEINPUT
{
   <span class="kwrd">public</span> <span class="kwrd">int</span>    dx;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    dy;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    mouseData;
   <span class="kwrd">public</span> MOUSEEVENTF dwFlags;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    time;
   <span class="kwrd">public</span> IntPtr dwExtraInfo;
}

[Flags]
<span class="kwrd">enum</span> MOUSEEVENTF : <span class="kwrd">int</span>
{
   MOVE       = 0x01,
   LEFTDOWN   = 0x02,
   LEFTUP     = 0x04,
   RIGHTDOWN  = 0x08,
   RIGHTUP    = 0x10,
   MIDDLEDOWN = 0x20,
   MIDDLEUP   = 0x40,
   ABSOLUTE   = 0x8000
}</pre>
<p><b><br>
</b></p>
<p>Each of these pieces go together in a specific way. To do a mouse movement, a mouse event structure needs to be created. This involves setting dwFlags to the kind of mouse event (a relative movement in this case), dx and dy to the number of pixels moved.
 It is also important to set dwExtraInfo to whatever GetMessageExtraInfo() is set to.</p>
<p><b>C# </b></p>
<pre class="csharpcode">MOUSEINPUT MEvent = <span class="kwrd">new</span> MOUSEINPUT();
MEvent.dwFlags = MOUSEEVENTF.MOVE;
MEvent.dx = Rnd . Next(-8, 8) ;
MEvent.dy = Rnd . Next(-8, 8);
MEvent.dwExtraInfo = GetMessageExtraInfo();
Send(MEvent);</pre>
<p>Sending the event takes a few more steps that are all wrapped in a helper methdo called Send(). Send these
<i>human interface device</i> events via the SendInput() procedure (earlier). The procedure takes an array of events, for different kinds of devices. We have to create the array, set the event type, copy the event data, and then make the call:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">bool</span> Send(MOUSEINPUT Event)
{
  INPUT[] Events = <span class="kwrd">new</span> INPUT[1];
  Events[0] . type = INPUTTYPE . MOUSE;
  Events[0] . i.mi = MEvent;
  <span class="kwrd">return</span> SendInput((<span class="kwrd">uint</span>)Events.Length, Events, Marshal.SizeOf(Events[0])) &gt; 0; 
}</pre>
<p><b><br>
</b></p>
<p>From here, sending a mouse button click is pretty straight forward. A mouse click is really a mouse button press event, followed by a mouse button release event. To make things interesting the mouse button is choosen at random. The “ugly” part is that each
 of the mouse buttons is assigned a bit, so a binary shift is used to convert a button number to its bit. And the button release is yet another bit, so the second message shifts the flags, to move the bit from the “button pressed” state to the “button released
 state”.</p>
<p><b>C# </b></p>
<pre class="csharpcode">MOUSEINPUT MEvent = <span class="kwrd">new</span> MOUSEINPUT();
MEvent.dwFlags = (MOUSEEVENTF) (1 &lt;&lt; (2*Rnd.Next(0, 3)&#43;1)) ;
MEvent.dwExtraInfo = GetMessageExtraInfo ();
Send(MEvent);

MEvent.dwFlags = (MOUSEEVENTF)((<span class="kwrd">int</span>) MEvent.dwFlags &lt;&lt; 1);
MEvent.dwExtraInfo = GetMessageExtraInfo ();
Send(MEvent);</pre>
<p><b><br>
</b></p>
<h4>Generating deranged text</h4>
<p>The gremlin can also type deranged sentences that will appear in editors, if the user left one open. The SendWait() method in the SendKeys class does the typing itself:</p>
<p><b>C#</b>&nbsp;</p>
<pre class="csharpcode">SendKeys . SendWait(GenerateSentence());
SendKeys . SendWait(<span class="str">&quot;{ENTER}&quot;</span>);</pre>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_5B6_5D.jpg"><img title="clip_image001[6]" border="0" alt="clip_image001[6]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_5B6_5D_thumb.jpg" width="282" height="135"></a></p>
<p>Generating the sentences is not difficult; I used a simplistic Markov generator. This generator starts by randomly selecting a word that can start a sentence. The
<i>Starts</i> variable is array which holds just these words. Then, in the Transition method, this word is used to find the
<i>next</i> word that can be included in the sentence. It does this by using a dictionary, called
<i>NonStart</i>, which given the word as a key, will return a list of all the words that can come after it. This process then repeats, appending the words onto the end of a string. It stops if it finds a word that can end a sentence.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">string</span>,<span class="kwrd">string</span>[]&gt; NonStart ;
<span class="kwrd">static</span> <span class="kwrd">string</span>[] Starts;
<span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">string</span>,<span class="kwrd">string</span>&gt; Terminal ;

<span class="kwrd">static</span> <span class="kwrd">string</span> GenerateSentence()
{
  StringBuilder SB = <span class="kwrd">new</span> StringBuilder();
  <span class="kwrd">string</span> Word = Starts[ Rnd.Next(0, Starts.Length) ];

  Transition(SB, Word);
  <span class="kwrd">return</span> SB.ToString();
}

<span class="kwrd">static</span> <span class="kwrd">void</span> Transition(StringBuilder SB, <span class="kwrd">string</span> Word)
{
  <span class="kwrd">while</span> (<span class="kwrd">true</span>)
  {
     SB.Append(Word);
     SB.Append(<span class="str">' '</span>);

     <span class="rem">// Look up word after this</span>
     <span class="kwrd">string</span>[] Nexts;
     <span class="kwrd">if</span> (!NonStart.TryGetValue(Word, <span class="kwrd">out</span> Nexts))
       <span class="kwrd">break</span>;
     <span class="kwrd">int</span> Idx = Rnd.Next(Terminal . ContainsKey(Word) ? -1 :0, Nexts.Length);
     <span class="kwrd">if</span> (Idx &lt; 0)
       <span class="kwrd">break</span>;
     Word = Nexts[Idx];
  }
}</pre>
<p><b><br>
</b></p>
<p>Building these two dictionaries and array is a pretty simple process. The BuildSuffixTree() method takes a string and splits it up into sentences. Then it splits each sentence into (lower case) words. The first word of the sentence goes onto the end of the
<i>Starts</i> array. Otherwise, the previous word is used to look up a list in a dictionary, and the current word is appended on to the list. This dictionary will become the
<i>NonStarts</i> dictionary. The last word of the sentence is also placed into the
<i>Terminal</i> dictionary, to indicate that this might be the end of a sentence.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">void</span> BuildSuffixTree()
{
  <span class="rem">// First, build up a list of words that start sentence, and transitions</span>
  List&lt;<span class="kwrd">string</span>&gt; Starts1 = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();
  Dictionary&lt;<span class="kwrd">string</span>,List&lt;<span class="kwrd">string</span>&gt;&gt; Trans = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">string</span>,List&lt;<span class="kwrd">string</span>&gt;&gt;();
  <span class="kwrd">foreach</span>(<span class="kwrd">string</span> S1 <span class="kwrd">in</span> S.Split(<span class="kwrd">new</span> <span class="kwrd">char</span>[]{<span class="str">'.'</span>,<span class="str">'?'</span>,<span class="str">'!'</span>}))
  {
     <span class="kwrd">string</span> Prev=<span class="kwrd">null</span>;
     <span class="kwrd">foreach</span>(<span class="kwrd">string</span> S2 <span class="kwrd">in</span> S1.Split(<span class="kwrd">new</span> <span class="kwrd">char</span>[]{<span class="str">' '</span>,<span class="str">'\n'</span>,<span class="str">'\r'</span>,<span class="str">'\t'</span>,<span class="str">','</span>,<span class="str">';'</span>}))
     {
        <span class="kwrd">if</span> (S2 . Length &lt; 1)
          <span class="kwrd">continue</span>;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == Prev)
          {
             Starts1.Add(<span class="kwrd">string</span>.Intern(S2.ToLower()));
             Prev = <span class="kwrd">string</span>.Intern(S2.ToLower());
             <span class="kwrd">continue</span>;
          }
        List&lt;<span class="kwrd">string</span>&gt; Nextsa;
        <span class="kwrd">if</span> (! Trans.TryGetValue(Prev, <span class="kwrd">out</span> Nextsa))
          Trans[Prev] = Nextsa = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();
        Prev = <span class="kwrd">string</span>.Intern(S2.ToLower());
        Nextsa.Add(Prev);
     }
     <span class="kwrd">if</span> (<span class="kwrd">null</span> != Prev)
       Terminal[Prev] = Prev;
 }

 <span class="rem">// Next, flatten the list of words that start a sentence</span>
 Starts = Starts1.ToArray();

 <span class="rem">// Flatten the transition table</span>
 <span class="kwrd">foreach</span> (<span class="kwrd">string</span> S3 <span class="kwrd">in</span> Trans.Keys)
  NonStart[S3] = Trans [S3].ToArray();
}</pre>
<p><b><br>
</b></p>
<h3>The things that trigger action</h3>
<h4>The audio trigger</h4>
<p>The audio module (in file AudioTrigger.cs) listens in on all of the microphones. It uses NAudio, with a basic setup and delegate structure swiped from Mark Heath's article “.NET Audio Recording”. The first difference is that it registers
<i>all</i> audio input devices:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> WaveIn[] StartMics()
{
  <span class="kwrd">int</span> NumDevices = WaveIn.DeviceCount;
  WaveIn[] AudIns = <span class="kwrd">new</span> WaveIn[NumDevices];
  <span class="kwrd">for</span> (<span class="kwrd">int</span> waveInDevice = 0; waveInDevice &lt; NumDevices ; waveInDevice&#43;&#43;)
  {
     AudIns[waveInDevice] = <span class="kwrd">new</span> WaveIn();
     AudIns[waveInDevice].DeviceNumber = waveInDevice;
     AudIns[waveInDevice].DataAvailable &#43;= waveIn_DataAvailable;
     AudIns[waveInDevice].WaveFormat = <span class="kwrd">new</span> WaveFormat(8000, 1);
     AudIns[waveInDevice].StartRecording();
  }
  <span class="kwrd">return</span> AudIns;
}</pre>
<p>The real magic in the trigger is a modified version of the waveIn_DataAvailable delegate. Instead of saving the audio, it checks for any sound activity. It starts by checking to see if any of the sound amplitudes are greater than a pre-defined, very high
 threshold. Then the samples are squared and summed up, and the result is compared with a threshold. If it exceeds the threshold, the trigger is set. These two are good at catching the kind of sound made when a person is talking, futzing on the desk, or typing.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image002_2.jpg"><img title="clip_image002" border="0" alt="clip_image002" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image002_thumb.jpg" width="372" height="210"></a></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">double</span> AudioThresh  = 0.8;
<span class="kwrd">static</span> <span class="kwrd">double</span> AudioThresh2 = 0.09;

<span class="kwrd">static</span> <span class="kwrd">void</span> waveIn_DataAvailable(<span class="kwrd">object</span> sender, WaveInEventArgs e)
{
  <span class="kwrd">bool</span> Tr = <span class="kwrd">false</span>;
  <span class="kwrd">double</span> Sum2  = 0;
  <span class="kwrd">int</span> Count = e.BytesRecorded / 2;
  <span class="kwrd">for</span> (<span class="kwrd">int</span> index = 0; index &lt; e.BytesRecorded; index &#43;= 2)
  {
     <span class="kwrd">double</span> Tmp = (<span class="kwrd">short</span>)((e.Buffer[index &#43; 1] &lt;&lt; 8) | e.Buffer[index &#43; 0]);
     Tmp /= 32768.0;
     Sum2 &#43;= Tmp*Tmp;
     <span class="kwrd">if</span> (Tmp &gt; AudioThresh)
       Tr = <span class="kwrd">true</span>;
  }
  Sum2 /= Count;

  <span class="rem">// If the Mean-Square is greater than a threshold, set a flag to indicate that noise has happened</span>
  <span class="kwrd">if</span> (Tr || Sum2 &gt; AudioThresh2)
    Interlocked.Exchange(<span class="kwrd">ref</span> AudioTrigger, 1);
}</pre>
<p><b><br>
</b></p>
<p>This sets a flag – AudioTrigger – which will be seen (and reset) in the main loop, with a bit of code that looks like:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">while</span> (0 == Shutdown)
{
    <span class="rem">// Do some lovely events</span>
    Application . DoEvents();
    Thread . Sleep (20);

    <span class="rem">//… do some other stuff ..</span>

    <span class="rem">// Check for a kick from the sound system</span>
    <span class="kwrd">if</span> (0 != AudioTrigger)
    {
        Interlocked . Exchange(<span class="kwrd">ref</span> AudioTrigger, 0);
        …
        ScreenShaker . Screens();
        <span class="kwrd">continue</span>;
    }
    <span class="rem">//… more checks for the user idle trigger…</span>
}<b><br></b></pre>
<h4>Waiting for the user to be idle</h4>
<p>The check to see if the user is not doing anything, the main loop uses a helper method called LastInputTime(), which returns the number of milliseconds the user did any input activity. The loop ensures that the user has been idle for long enough, and then
 calls the method that selects random gremlin actions:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">uint</span> LastTime = Win32.LastInputTime();
<span class="kwrd">if</span> ((<span class="kwrd">uint</span>) Environment.TickCount &lt; IdleTimeTrigger &#43; LastTime)
    <span class="kwrd">continue</span>;</pre>
<p>The LastInputTime() helper method uses a p/invoke call to the GetLastInputInfo() API call. The wiki at Pinvoke.net provides the signature to the procedure, and a suitable structure that we need to pass to it:</p>
<p><b>C# </b></p>
<pre class="csharpcode">[DllImport(<span class="str">&quot;User32.dll&quot;</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> GetLastInputInfo(<span class="kwrd">ref</span> LASTINPUTINFO LastInfo);

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> LASTINPUTINFO
{
  <span class="kwrd">public</span> <span class="kwrd">uint</span> cbSize;

  <span class="rem">/// &lt;summary&gt;</span>
  <span class="rem">/// Number of system tickes</span>
  <span class="rem">/// &lt;/summary&gt;</span>
  <span class="kwrd">public</span> <span class="kwrd">uint</span> dwTime;
}</pre>
<p>Then, these two structures are wrapped up into the LastInputTime() helper procedure, which does the dirty work of allocating and initializing a structure.
</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> LastInputTime()
{
  LASTINPUTINFO lastInput=<span class="kwrd">new</span> LASTINPUTINFO();
  lastInput.cbSize = (<span class="kwrd">uint</span>)Marshal.SizeOf(lastInput);
  GetLastInputInfo(<span class="kwrd">ref</span> lastInput);
  <span class="kwrd">return</span> lastInput . dwTime;
}<b><br></b></pre>
<h3>Conclusion</h3>
<p>The tricks gremlin plays are intended to be somewhat subtle. There is an aggressive option to make it react more, and move windows around more visibly.
</p>
<p>If you want to try this out, the download link for the <a href="http://gremlin.codeplex.com/Release/ProjectReleases.aspx">
executable</a> and <a href="http://gremlin.codeplex.com/SourceControl/ListDownloadableCommits.aspx">
source code</a> are at the top of the article!</p>
<h4>Resources and References</h4>
<p>This article is a blatant grab bag of experimental and reused code from earlier experiments and other demo programs. Below are some of the projects I lifted code examples from:</p>
<ul>
<li><a href="http://pinvoke.net/">Pinvoke.net</a> – a wiki-style site with many useful bits of example code related to calling the Windows API from within .NET.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2009/10/08/9905168.aspx">“.NET Audio Recorder”</a> by Mark Heath, from which I stole code to make the audio trigger.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2007/10/29/5773776.aspx">“Possessed PC Pranks for Halloween”</a> by Brian Peek, from which I stole the basic code for sending keystrokes.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2007/03/29/1991785.aspx">“April Fools' Day Application”</a> by Brian Peek, from which I stole code to grab the screen and rotate it.
</li></ul>
<h3>About The Author</h3>
<p>Randall Maas writes firmware for medical devices, and consults in embedded software. Before that he did a lot of other things… like everyone else in the software industry. You can contact him at
<a href="mailto:randym@acm.org">randym@acm.org</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:144c71c45bb4497091de9e7600caf138">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</comments>
      <itunes:summary>
This article describes a quick and easy application to play Halloween tricks on the PC. 
 
Introduction
This article describes “Gremlin”, a quick and easy application that lets you play Halloween tricks. When your victim&#39;s computer is idle, Gremlin moves windows around on the screen, changes the focus window, moves your mouse, scrolls windows, and types nonsensical
 stuff. When there is background noise – like someone talking – it will shake the screen, even as your victim is typing away. 
Deployment
Run it right away. You can download, copy theGremlin.exe executable and NAudio.dll to the victim&#39;s computer (say in c:\ directory), and then double click on the executable to run it. 
Run it later. The other option is to copy the executable and dll files (or a shortcut to it) to the Startup folder on the victim&#39;s machine and watch the fun begin when they start up their machine in the morning! 
If the computer you&#39;re using runs on Windows XP the path is:  

C:\Documents and Settings\All Users\Start Menu\Programs\Startup 

With Vista and Windows 7 the path looks like:  

C:\Users\USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 

Just remember to change USERNAME to the name of the user on your machine. 
 
Commandline
Gremlin is compiled as a windows application, so it won&#39;t popup a terminal window if you double click on it, etc. But you can run it from the command line with flags: 

-aggressive will make the gremlin&#39;s actions more obvious 
-help will display the command line options 
-name NAME is useful for testing. Gremlin will only use windows with this specific title or from this specific application. (Remember to drop the &amp;quot;.exe&amp;quot; from the application filename) 

To stop the program, press CTRL&amp;#43;F2. 
And now … the dodgy bits
The overall structure of the program is broken down into three kinds of functionality – actions, triggers and some interstitial glue: 
Actions 

The screen-shaker is a window that makes the monitor look like it i</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</link>
      <pubDate>Sat, 31 Oct 2009 22:37:42 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9915768_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9915768_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Randall Maas</dc:creator>
      <itunes:author>Randall Maas</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins/RSS</wfw:commentRss>
      <category>Audio</category>
      <category>Halloween</category>
      <category>Pranks</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>TwitterDrive – Author Interview</title>
      <description><![CDATA[<p><img title="tDrive" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/tDrive_3.jpg" alt="tDrive" width="79" height="45" align="left" border="0"> In case you haven't heard, <a href="http://www.brianpeek.com/media/p/3413.aspx">TwitterDrive</a> is going to revolutionize the way files are stored and shared on the Internet.&nbsp; Today, we had the rare privilege of sitting down and talking with <a href="http://www.brianpeek.com/">Brian Peek</a>, creator of this cutting edge product.</p><p><strong>Q: Thanks for taking the time to speak with us today.&nbsp; Why don't you tell us a little bit about yourself?</strong></p><p>A: I'm surprised I even considered this.&nbsp; I'm so above you people now.&nbsp; But anyway, my name is Brian Peek, and until I developed this app, I was working, like you people, at a job that was pointless.&nbsp; Now, I'm on the cusp of owning people like you.&nbsp; Once this takes off, I can finally pursue my life's other passion:&nbsp; hip-hop music.</p><p><strong><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/30872-480-360_2.png"><img title="30872-480-360" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/30872-480-360_thumb.png" alt="30872-480-360" width="364" height="274" align="left" border="0"></a> Q: I don't doubt it.&nbsp; So why don't you tell us a little bit about TwitterDrive and how you came up with the idea?</strong></p><p>A: TwitterDrive is the next “big thing” in cloud storage.&nbsp; There are a ton of cloud storage providers out there now, most of which cost money or have limited disk space available.&nbsp; But why should we live with limitations like these?&nbsp; Twitter provides their users with unlimited storage for sending and saving their “tweets”.&nbsp; My amazingly brilliant idea was to take this service to the next level:&nbsp; using it to store and share files.&nbsp; That is, free cloud storage.&nbsp; Bet you wish you thought of that.</p><p><strong><strong><img title="shatner" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/shatner_3.png" alt="shatner" width="185" height="250" align="left" border="0"></strong>Q: I sure do.&nbsp; So how does TwitterDrive work? </strong></p><p>A: It works perfectly.&nbsp; Simply run the TwitterDrive application, provide your Twitter user credentials, and then start uploading and downloading files.&nbsp; Files are compressed, base64 encoded, and then uploaded to Twitter 140 bytes at a time, fully maximizing the amount of space allowed per tweet.</p><p>Imagine…uploading 14 thousand bytes of data per hour!&nbsp; Or downloading two megabytes per hour!&nbsp; Match that, SkyDrive.</p><p><strong>Q: That sounds amazing.&nbsp; Unlimited storage for free.</strong></p><p>It is amazing.&nbsp; Which is why I thought of it and you didn't.&nbsp; Welcome to the future.</p><p><strong>Q: So are there any limitations?</strong></p><p>Only if you consider uploading 14 thousand <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/mp_main_wide_EarlyComputerMarketing_2.png"><img title="mp_main_wide_EarlyComputerMarketing" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525555/mp_main_wide_EarlyComputerMarketing_thumb.png" alt="mp_main_wide_EarlyComputerMarketing" width="364" height="282" align="right" border="0"></a>bytes per hour a limitation.&nbsp; But really, who has that much data?&nbsp; 14k should be enough for everybody.</p><p><strong>Q: What about data protection?&nbsp; Is the file data protected in any way?</strong></p><p>The data is compressed, encoded and chunked up into bits.&nbsp; Who needs more security than that?&nbsp; Besides, users would need to know your TwitterDrive account username to get at the data.&nbsp; Security through obscurity is a win for everyone!</p><p><strong>Q: Do you have any new features planned for TwitterDrive?</strong></p><p>New features?&nbsp; No.&nbsp; It's already the most complete, useful and bug free application ever developed.&nbsp; It doesn't require any additional features.</p><p>Now if you'll excuse me, I have to start planning which jet I want to buy.</p><p><strong>Well there you have it, folks.&nbsp; We are at the cusp of a revolution.&nbsp; Are you ready?</strong></p><p><a href="http://www.brianpeek.com/media/p/3413.aspx">Download TwitterDrive here</a>.&nbsp; Want to learn more?&nbsp; Learn <a href="http://blogs.msdn.com/coding4fun/archive/2009/04/01/9525376.aspx">how it was made</a>!</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:e52421f86d2e4408974b9e7600ccd94c">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/TwitterDrive--Author-Interview</comments>
      <itunes:summary> In case you haven&#39;t heard, TwitterDrive is going to revolutionize the way files are stored and shared on the Internet.&amp;nbsp; Today, we had the rare privilege of sitting down and talking with Brian Peek, creator of this cutting edge product. Q: Thanks for taking the time to speak with us today.&amp;nbsp; Why don&#39;t you tell us a little bit about yourself? A: I&#39;m surprised I even considered this.&amp;nbsp; I&#39;m so above you people now.&amp;nbsp; But anyway, my name is Brian Peek, and until I developed this app, I was working, like you people, at a job that was pointless.&amp;nbsp; Now, I&#39;m on the cusp of owning people like you.&amp;nbsp; Once this takes off, I can finally pursue my life&#39;s other passion:&amp;nbsp; hip-hop music.  Q: I don&#39;t doubt it.&amp;nbsp; So why don&#39;t you tell us a little bit about TwitterDrive and how you came up with the idea? A: TwitterDrive is the next “big thing” in cloud storage.&amp;nbsp; There are a ton of cloud storage providers out there now, most of which cost money or have limited disk space available.&amp;nbsp; But why should we live with limitations like these?&amp;nbsp; Twitter provides their users with unlimited storage for sending and saving their “tweets”.&amp;nbsp; My amazingly brilliant idea was to take this service to the next level:&amp;nbsp; using it to store and share files.&amp;nbsp; That is, free cloud storage.&amp;nbsp; Bet you wish you thought of that. Q: I sure do.&amp;nbsp; So how does TwitterDrive work?  A: It works perfectly.&amp;nbsp; Simply run the TwitterDrive application, provide your Twitter user credentials, and then start uploading and downloading files.&amp;nbsp; Files are compressed, base64 encoded, and then uploaded to Twitter 140 bytes at a time, fully maximizing the amount of space allowed per tweet. Imagine…uploading 14 thousand bytes of data per hour!&amp;nbsp; Or downloading two megabytes per hour!&amp;nbsp; Match that, SkyDrive. Q: That sounds amazing.&amp;nbsp; Unlimited storage for free. It is amazing.&amp;nbsp; Which is why I thought of it and you didn&#39;t.&amp;nbsp; Welcome to the futu</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/TwitterDrive--Author-Interview</link>
      <pubDate>Wed, 01 Apr 2009 04:10:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/TwitterDrive--Author-Interview</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9525555_100.jpg" height="76" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9525555_220.jpg" height="166" width="220"></media:thumbnail>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>9</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/blog/TwitterDrive--Author-Interview/RSS</wfw:commentRss>
      <category>Productivity</category>
      <category>utility</category>
      <category>Web</category>
      <category>Windows</category>
      <category>Holiday</category>
      <category>april fools day</category>
    </item>
  <item>
      <title>TwitterDrive – The Revolution in Cloud Storage</title>
      <description><![CDATA[
<table border="0" cellspacing="0" cellpadding="1" width="100%">
<tbody>
<tr class="entry_overview">
<td width="50">&nbsp;<img title="tDrive" border="0" alt="tDrive" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525376/tDrive_3.jpg" width="75" height="41">
</td>
<td><span class="entry_description">In this article, Brian Peek will provide a technical overview of TwitterDrive, an application used to store and retrieve files via the Twitter messaging service.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author"><a href="http://www.brianpeek.com/" target="_blank">Brian Peek</a></div>
<div class="entry_company"><a href="http://www.aspsoft.com/">ASPSOFT, Inc.</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> 2<span class="entry_details_input">-3 hours</span></div>
<div class="entry_details"><b>Cost: </b>Free</div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual C# Express 2008 SP1, Visual Basic Express 2008 SP1, or Visual Studio 2008 SP1, .NET Framework 3.5 SP1</a></span></div>
<div class="entry_details"><b>Hardware: </b>None</div>
<div class="entry_details"><b>Download: </b><a href="http://www.brianpeek.com/media/p/3413.aspx" target="_blank">Application</a>,
<a href="http://www.brianpeek.com/media/p/3414.aspx" target="_blank">Source Code</a></div>
<div class="entry_details"><b>Discussion Forum: </b><a href="http://www.brianpeek.com/forums/44.aspx" target="_blank">Forum</a></div>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<h3>Introduction</h3>
<p>As you've probably guessed by now, <b>TwitterDrive</b> is my April Fool's Day application for Coding4Fun this year.&nbsp; While the application does actually work, the limitations of Twitter make it functionally useless.&nbsp; That said, I'll still take you through
 the important parts as there is some value in the code with regard to the Twitter API, LINQ to XML, threading, and a couple other things.</p>
<h4>How It Works</h4>
<p>Not very well, actually.&nbsp; The concept is we take a file, compress it, uuencode/base64 encode it (that is, make a text representation of the binary contents), and then upload it 140 characters at a time to Twitter as status messages.&nbsp; When the file upload
 is complete, an index is written of every file that is currently stored on Twitter with some information that can be used to later retrieve the file.</p>
<h4>Twitter</h4>
<p>Let's start with the Twitter API.&nbsp; Full documentation on this API can be found at:</p>
<p><a title="http://apiwiki.twitter.com/" href="http://apiwiki.twitter.com/">http://apiwiki.twitter.com/</a></p>
<p>TwitterDrive only requires a very small subset of this functionality to work.&nbsp; We need the ability to post a new status message, download a user timeline, destroy a status, and verify the user's credentials.&nbsp; All of these things are handled in the
<b>TwitterService</b> class.</p>
<p>The heart of this class consists of two methods:&nbsp; <b>GetTwitter </b>and <b>PostTwitter</b>.&nbsp;
<b>GetTwitter</b> will make a GET request to Twitter of the specified URL, and <b>
PostTwitter</b> will make a POST request to Twitter of the specified URL with the supplied data.</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>private</span> XDocument GetTwitter(<span>string</span> url)<br>{<br>    WebClient wc = <span>new</span> WebClient();<br><br>    <span>// only authenticate if we have a password</span><br>    <span>if</span>(!<span>string</span>.IsNullOrEmpty(Password))<br>        wc.Credentials = <span>new</span> NetworkCredential(Username, Password);<br><br>    Stream s = wc.OpenRead(url);<br><br>    <span>// return an XDocument for LINQ</span><br>    XmlTextReader xmlReader = <span>new</span> XmlTextReader(s);<br>    XDocument xdoc = XDocument.Load(xmlReader);<br>    xmlReader.Close();<br>    <span>return</span> xdoc;<br>}<br><br><span>private</span> XDocument PostTwitter(<span>string</span> url, <span>string</span> data)<br>{<br>    <span>byte</span>[] bytes = Encoding.ASCII.GetBytes(data);<br><br>    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);<br>    request.Method = <span>&quot;POST&quot;</span>;<br><br>    <span>// if we're writing, we need to authenticate</span><br>    request.Credentials = <span>new</span> NetworkCredential(Username, Password);<br><br>    <span>// if this is 'true', Twitter breaks</span><br>    request.ServicePoint.Expect100Continue = <span>false</span>;<br>    request.ContentType = <span>&quot;application/x-www-form-urlencoded&quot;</span>;<br>    request.ContentLength = bytes.Length;<br><br>    Stream reqStream = request.GetRequestStream();<br>    reqStream.Write(bytes, 0, bytes.Length);<br><br>    <span>// turn the response into an XDocument for use with LINQ</span><br>    HttpWebResponse resp = (HttpWebResponse)request.GetResponse();<br>    XmlReader xmlReader = XmlReader.Create(resp.GetResponseStream());<br>    XDocument xdoc = XDocument.Load(xmlReader);<br>    xmlReader.Close();<br>    <span>return</span> xdoc;<br>}<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Private</span> <span>Function</span> GetTwitter(<span>ByVal</span> url <span>As</span> <span>String</span>) <span>As</span> XDocument<br>    <span>Dim</span> wc <span>As</span> <span>New</span> WebClient()<br><br>    <span>' only authenticate if we have a password</span><br>    <span>If</span> (<span>Not</span> <span>String</span>.IsNullOrEmpty(Password)) <span>Then</span><br>        wc.Credentials = <span>New</span> NetworkCredential(Username, Password)<br>    <span>End</span> <span>If</span><br><br>    <span>Dim</span> s <span>As</span> Stream = wc.OpenRead(url)<br><br>    <span>' return an XDocument for LINQ</span><br>    <span>Dim</span> xmlReader <span>As</span> <span>New</span> XmlTextReader(s)<br>    <span>Dim</span> xdoc <span>As</span> XDocument = XDocument.Load(xmlReader)<br>    xmlReader.Close()<br>    <span>Return</span> xdoc<br><span>End</span> <span>Function</span><br><br><span>Private</span> <span>Function</span> PostTwitter(<span>ByVal</span> url <span>As</span> <span>String</span>, <span>ByVal</span> data <span>As</span> <span>String</span>) <span>As</span> XDocument<br>    <span>Dim</span> bytes() <span>As</span> <span>Byte</span> = Encoding.ASCII.GetBytes(data)<br><br>    <span>Dim</span> request <span>As</span> HttpWebRequest = <span>CType</span>(WebRequest.Create(url), HttpWebRequest)<br>    request.Method = <span>&quot;POST&quot;</span><br><br>    <span>' if we're writing, we need to authenticate</span><br>    request.Credentials = <span>New</span> NetworkCredential(Username, Password)<br><br>    <span>' if this is 'true', Twitter breaks</span><br>    request.ServicePoint.Expect100Continue = <span>False</span><br>    request.ContentType = <span>&quot;application/x-www-form-urlencoded&quot;</span><br>    request.ContentLength = bytes.Length<br><br>    <span>Dim</span> reqStream <span>As</span> Stream = request.GetRequestStream()<br>    reqStream.Write(bytes, 0, bytes.Length)<br><br>    <span>' turn the response into an XDocument for use with LINQ</span><br>    <span>Dim</span> resp <span>As</span> HttpWebResponse = <span>CType</span>(request.GetResponse(), HttpWebResponse)<br>    <span>Dim</span> xmlReader <span>As</span> XmlReader = XmlReader.Create(resp.GetResponseStream())<br>    <span>Dim</span> xdoc <span>As</span> XDocument = XDocument.Load(xmlReader)<br>    xmlReader.Close()<br>    <span>Return</span> xdoc<br><span>End</span> Function</pre>
<br>
</div>
<p>Each of these methods will use the <b>NetworkCredentials</b> object to authenticate to Twitter for reading or writing, as required.&nbsp; Twitter API methods return simple XML objects.&nbsp; Both
<b>GetTwitter</b> and <b>PostTwitter</b> take these XML documents and turn them into
<b>XDocument</b> objects that can be easily queried with LINQ to XML later.</p>
<p>We only need to call two Twitter “get” methods: <b>user_timeline </b>and <b>verify_credentials</b>.&nbsp; There are two overloaded methods which call the
<b>user_timeline</b> API:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> IList&lt;Status&gt; GetUserTimeline(<span>int</span> page, <span>int</span> count)<br>{<br>    XDocument xdoc = GetTwitter(<span>string</span>.Format(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/user_timeline.xml?count=" href="http://twitter.com/statuses/user_timeline.xml?count=">http://twitter.com/statuses/user_timeline.xml?count=</a>{0}&amp;page={1}&amp;id={2}&quot;</span>, count, page, Username));<br>    IList&lt;Status&gt; statuses = ParseStatuses(xdoc);<br>    <span>return</span> statuses;<br>}<br><br><span>public</span> IList&lt;Status&gt; GetUserTimeline(<span>int</span> since_id, <span>int</span> max_id, <span>int</span> page, <span>int</span> count)<br>{<br>    XDocument xdoc = GetTwitter(<span>string</span>.Format(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/user_timeline.xml?since_id=" href="http://twitter.com/statuses/user_timeline.xml?since_id=">http://twitter.com/statuses/user_timeline.xml?since_id=</a>{0}&amp;max_id={1}&amp;count={2}&amp;page={3}&amp;id={4}&quot;</span>, since_id, max_id, count, page, Username));<br>    IList&lt;Status&gt; statuses = ParseStatuses(xdoc);<br>    <span>return</span> statuses;<br>}</pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> GetUserTimeline(<span>ByVal</span> page <span>As</span> <span>Integer</span>, <span>ByVal</span> count <span>As</span> <span>Integer</span>) <span>As</span> IList(Of Status)<br>    <span>Dim</span> xdoc <span>As</span> XDocument = GetTwitter(<span>String</span>.Format(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/user_timeline.xml?count=" href="http://twitter.com/statuses/user_timeline.xml?count=">http://twitter.com/statuses/user_timeline.xml?count=</a>{0}&amp;page={1}&amp;id={2}&quot;</span>, count, page, Username))<br>    <span>Dim</span> statuses <span>As</span> IList(Of Status) = ParseStatuses(xdoc)<br>    <span>Return</span> statuses<br><span>End</span> <span>Function</span><br><br><span>Public</span> <span>Function</span> GetUserTimeline(<span>ByVal</span> since_id <span>As</span> <span>Integer</span>, <span>ByVal</span> max_id <span>As</span> <span>Integer</span>, <span>ByVal</span> page <span>As</span> <span>Integer</span>, <span>ByVal</span> count <span>As</span> <span>Integer</span>) <span>As</span> IList(Of Status)<br>    <span>Dim</span> xdoc <span>As</span> XDocument = GetTwitter(<span>String</span>.Format(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/user_timeline.xml?since_id=" href="http://twitter.com/statuses/user_timeline.xml?since_id=">http://twitter.com/statuses/user_timeline.xml?since_id=</a>{0}&amp;max_id={1}&amp;count={2}&amp;page={3}&amp;id={4}&quot;</span>, since_id, max_id, count, page, Username))<br>    <span>Dim</span> statuses <span>As</span> IList(Of Status) = ParseStatuses(xdoc)<br>    <span>Return</span> statuses<br><span>End</span> Function</pre>
<br>
</div>
<p>Each of these methods creates a URL with the appropriate query string arguments (see the Twitter API docs for the full list) and then calls our ParseStatuses method with the returned XDocument, which will give us a List of Status objects. The Twitter-returned
 status contains a variety of data, such as:</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>&lt;</span><span>status</span><span>&gt;</span><br><span>&lt;</span><span>created_at</span><span>&gt;</span>Mon Mar 30 07:20:57 &#43;0000 2009<span>&lt;/</span><span>created_at</span><span>&gt;</span><br><span>&lt;</span><span>id</span><span>&gt;</span>1234567123<span>&lt;/</span><span>id</span><span>&gt;</span><br><span>&lt;</span><span>text</span><span>&gt;</span>Status text<span>&lt;/</span><span>text</span><span>&gt;</span><br><span>&lt;</span><span>source</span><span>&gt;</span>web<span>&lt;/</span><span>source</span><span>&gt;</span><br><span>&lt;</span><span>truncated</span><span>&gt;</span>false<span>&lt;/</span><span>truncated</span><span>&gt;</span><br><span>&lt;</span><span>in_reply_to_status_id</span><span>/&gt;</span><br><span>&lt;</span><span>in_reply_to_user_id</span><span>/&gt;</span><br><span>&lt;</span><span>favorited</span><span>&gt;</span>false<span>&lt;/</span><span>favorited</span><span>&gt;</span><br><br><span>&lt;</span><span>user</span><span>&gt;</span><br><span>&lt;</span><span>id</span><span>&gt;</span>12345678<span>&lt;/</span><span>id</span><span>&gt;</span><br><span>&lt;</span><span>name</span><span>&gt;</span>Some Person<span>&lt;/</span><span>name</span><span>&gt;</span><br><span>&lt;</span><span>screen_name</span><span>&gt;</span>myscreenname<span>&lt;/</span><span>screen_name</span><span>&gt;</span><br><span>&lt;</span><span>description</span><span>/&gt;</span><br><span>&lt;</span><span>location</span><span>/&gt;</span><br><br><span>&lt;</span><span>profile_image_url</span><span>&gt;</span><br><a class="linkification-ext" title="Linkification: http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525376/default_profile_normal.png" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525376/default_profile_normal.png">http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525376/default_profile_normal.png</a><br><span>&lt;/</span><span>profile_image_url</span><span>&gt;</span><br><span>&lt;</span><span>url</span><span>/&gt;</span><br><span>&lt;</span><span>protected</span><span>&gt;</span>false<span>&lt;/</span><span>protected</span><span>&gt;</span><br><span>&lt;</span><span>followers_count</span><span>&gt;</span>1<span>&lt;/</span><span>followers_count</span><span>&gt;</span><br><span>&lt;/</span><span>user</span><span>&gt;</span><br><span>&lt;/</span><span>status</span><span>&gt;</span></pre>
<br>
</div>
<p>We only care about a few elements and only parse those, namely id, text, user (which is in itself an XML chunk), and created_at.</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>private</span> IList&lt;Status&gt; ParseStatuses(XContainer container)<br>{<br>    <span>// return a list of Status objects</span><br>    var query = from status <span>in</span> container.Descendants(<span>&quot;statuses&quot;</span>).Descendants(<span>&quot;status&quot;</span>)<br>                select ParseStatus(status);<br>    <span>return</span> query.ToList();<br>}<br><br><span>private</span> Status ParseStatus(XDocument xdoc)<br>{<br>    <span>// create a Status object from the returned XML</span><br>    var query = from status <span>in</span> xdoc.Descendants(<span>&quot;status&quot;</span>)<br>                select ParseStatus(status);<br><br>    <span>return</span> query.SingleOrDefault();<br>}<br><br><span>private</span> Status ParseStatus(XElement xelement)<br>{<br>    Status s = <span>new</span> Status()<br>                {<br>                    ID = (<span>int</span>)xelement.Element(<span>&quot;id&quot;</span>),<br>                    Text = (<span>string</span>)xelement.Element(<span>&quot;text&quot;</span>),<br>                    UserInformation = ParseUserInformation(xelement.Element(<span>&quot;user&quot;</span>)),<br>                    <span>// HTTP-formatted date</span><br>                    CreatedAt = DateTime.ParseExact(xelement.Element(<span>&quot;created_at&quot;</span>).Value,<br>                            <span>&quot;ddd MMM dd HH:mm:ss zzzz yyyy&quot;</span>,<br>                            CultureInfo.GetCultureInfoByIetfLanguageTag(<span>&quot;en-us&quot;</span>),<br>                            DateTimeStyles.AllowWhiteSpaces)<br>                };<br><br>    <span>return</span> s;<br>}<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Private</span> <span>Function</span> ParseStatuses(<span>ByVal</span> container <span>As</span> XContainer) <span>As</span> IList(Of Status)<br>    <span>' return a list of Status objects</span><br>    <span>Dim</span> query = _<br>        From status <span>In</span> container.Descendants(<span>&quot;statuses&quot;</span>).Descendants(<span>&quot;status&quot;</span>) _<br>        <span>Select</span> ParseStatus(status)<br>    <span>Return</span> query.ToList()<br><span>End</span> <span>Function</span><br><br><span>Private</span> <span>Function</span> ParseStatus(<span>ByVal</span> xdoc <span>As</span> XDocument) <span>As</span> Status<br>    <span>' create a Status object from the returned XML</span><br>    <span>Dim</span> query = _<br>        From status <span>In</span> xdoc.Descendants(<span>&quot;status&quot;</span>) _<br>        <span>Select</span> ParseStatus(status)<br><br>    <span>Return</span> query.SingleOrDefault()<br><span>End</span> <span>Function</span><br><br><span>Private</span> <span>Function</span> ParseStatus(<span>ByVal</span> xelement <span>As</span> XElement) <span>As</span> Status<br>    <span>Dim</span> s <span>As</span> <span>New</span> Status() <span>With</span> { _<br>        .ID = <span>CInt</span>(xelement.Element(<span>&quot;id&quot;</span>)), _<br>        .Text = <span>CStr</span>(xelement.Element(<span>&quot;text&quot;</span>)), _<br>        .UserInformation = ParseUserInformation(xelement.Element(<span>&quot;user&quot;</span>)), _<br>        .CreatedAt = DateTime.ParseExact(xelement.Element(<span>&quot;created_at&quot;</span>).Value, _<br>                    <span>&quot;ddd MMM dd HH:mm:ss zzzz yyyy&quot;</span>, CultureInfo.GetCultureInfoByIetfLanguageTag(<span>&quot;en-us&quot;</span>), DateTimeStyles.AllowWhiteSpaces) }<br>    <span>Return</span> s<br><span>End</span> Function</pre>
<br>
</div>
<p>These methods use LINQ to XML to drill down into the XML document to parse out individual status objects and return them as a list.&nbsp; You will notice the user element contains a
<strong>user_information</strong> XML chunk, and the <b>ParseUserInformation</b> method parses that data</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>private</span> UserInformation ParseUserInformation(XContainer container)<br>{<br>    <span>// parse and return a UserInformation object</span><br>    <span>return</span> <span>new</span> UserInformation<br>    {<br>        ID = (<span>int</span>)container.Element(<span>&quot;id&quot;</span>),<br>        Name = (<span>string</span>)container.Element(<span>&quot;name&quot;</span>),<br>        ScreenName = (<span>string</span>)container.Element(<span>&quot;screen_name&quot;</span>)<br>    };<br>}<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Private</span> <span>Function</span> ParseUserInformation(<span>ByVal</span> container <span>As</span> XContainer) <span>As</span> UserInformation<br>    <span>' parse and return a UserInformation object</span><br>    <span>Dim</span> ui <span>As</span> <span>New</span> UserInformation() <span>With</span> { _<br>        .ID = <span>CInt</span>(container.Element(<span>&quot;id&quot;</span>)), _<br>        .Name = <span>CStr</span>(container.Element(<span>&quot;name&quot;</span>)), _<br>        .ScreenName = <span>CStr</span>(container.Element(<span>&quot;screen_name&quot;</span>)) }<br><br>    <span>Return</span> ui<br><span>End</span> Function</pre>
<br>
</div>
<p>The <b>verify_credentials</b> API is called in a similar manner, but in this case we will “listen” for a 401 (Unauthorized) exception and return true or false appropriately:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> <span>bool</span> VerifyTwitterCredentials(<span>string</span> username, <span>string</span> password)<br>{<br>    <span>try</span><br>    {<br>        WebClient wc = <span>new</span> WebClient();<br>        wc.Credentials = <span>new</span> NetworkCredential(username, password);<br>        Stream s = wc.OpenRead(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/account/verify_credentials.xml" href="http://twitter.com/account/verify_credentials.xml">http://twitter.com/account/verify_credentials.xml</a>&quot;</span>);<br>        s.Close();<br>    }<br>    <span>catch</span>(WebException we)<br>    {<br>        <span>if</span>((we.Response <span>as</span> HttpWebResponse).StatusCode == HttpStatusCode.Unauthorized)<br>            <span>return</span> <span>false</span>;<br>        <span>throw</span>;<br>    }<br><br>    <span>return</span> <span>true</span>;<br>}</pre>
<br>
</div>
<p>With the “get” methods out of the way, we can write our “post” methods.&nbsp; We only need two methods here as well:&nbsp;
<b>update</b> and <b>destroy</b>.&nbsp; Update is used to write a new tweet to Twitter, and destroy is used to remove an existing tweet.</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> Status UpdateStatus(<span>string</span> status)<br>{<br>    XDocument doc = PostTwitter(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/update.xml" href="http://twitter.com/statuses/update.xml">http://twitter.com/statuses/update.xml</a>&quot;</span>, <span>&quot;status=&quot;</span> &#43; status);<br>    Status s =  ParseStatus(doc);<br><br>    <span>// if we don't get the text we sent, we hit the rate limit...</span><br>    <span>if</span>(s.Text != HttpUtility.UrlDecode(status))<br>        <span>throw</span> <span>new</span> TwitterRateLimitException(<span>&quot;Twitter upload limit reached.&quot;</span>);<br>    <span>return</span> s;<br>}<br><br><span>public</span> Status Destroy(<span>int</span> status)<br>{<br>    XDocument doc = PostTwitter(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/statuses/destroy/" href="http://twitter.com/statuses/destroy/">http://twitter.com/statuses/destroy/</a>&quot;</span> &#43; status &#43; <span>&quot;.xml&quot;</span>, <span>&quot;id=&quot;</span> &#43; status);<br>    <span>return</span> ParseStatus(doc);<br>}</pre>
<br>
</div>
<p>&nbsp;</p>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> VerifyTwitterCredentials(<span>ByVal</span> username <span>As</span> <span>String</span>, <span>ByVal</span> password <span>As</span> <span>String</span>) <span>As</span> <span>Boolean</span><br>    <span>Try</span><br>        <span>Dim</span> wc <span>As</span> <span>New</span> WebClient()<br>        wc.Credentials = <span>New</span> NetworkCredential(username, password)<br>        <span>Dim</span> s <span>As</span> Stream = wc.OpenRead(<span>&quot;<a class="linkification-ext" title="Linkification: http://twitter.com/account/verify_credentials.xml" href="http://twitter.com/account/verify_credentials.xml">http://twitter.com/account/verify_credentials.xml</a>&quot;</span>)<br>        s.Close()<br>    <span>Catch</span> we <span>As</span> WebException<br>        <span>If</span> (<span>TryCast</span>(we.Response, HttpWebResponse)).StatusCode = HttpStatusCode.Unauthorized <span>Then</span><br>            <span>Return</span> <span>False</span><br>        <span>End</span> <span>If</span><br>        <span>Throw</span><br>    <span>End</span> <span>Try</span><br><br>    <span>Return</span> <span>True</span><br><span>End</span> Function</pre>
<br>
</div>
<p>The <b>UpdateStatus</b> method has a bit of code to determine whether we hit Twitter's upload rate limit.&nbsp; Twitter will limit you to about 100 tweets per hour.&nbsp; The only way to determine if you've hit the upload limit (that I found at least) is to compare
 the text from <b>status</b> element returned from the update to the text that was sent.&nbsp; If the upload limit is hit, the last valid
<b>status</b> element will be returned, and therefore the text blocks will not match.&nbsp; If this happens, we throw our own custom
<b>TwitterRateLimitException</b> up the stack for the UI to handle.</p>
<h4>TwitterDrive</h4>
<p>Now that we can talk to Twitter, the next step is to write the code that uses these methods to store and retrieve our file data.&nbsp; This code is located in the
<b>TwitterDrive</b> class.</p>
<p>One of the goals I had was to make this application thread-happy to provide a responsive UI while files are uploaded and downloaded.&nbsp; Therefore, this class sets up three events which can be hooked by the UI to receive periodic status information:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> <span>class</span> ChunkEventArgs : EventArgs<br>{<br>    <span>public</span> Status Status;<br>    <span>public</span> <span>int</span> ChunkLength;<br>    <span>public</span> <span>int</span> Total;<br><br>    <span>public</span> ChunkEventArgs(Status status, <span>int</span> length, <span>int</span> total)<br>    {<br>        Status = status;<br>        ChunkLength = length;<br>        Total = total;<br>    }<br>}<br><br>...<br><br><span>// event handlers for async file transfer</span><br><span>public</span> <span>event</span> EventHandler&lt;ChunkEventArgs&gt; ChunkUpload;<br><span>public</span> <span>event</span> EventHandler&lt;ChunkEventArgs&gt; ChunkDownload;<br><span>public</span> <span>event</span> EventHandler&lt;EventArgs&gt; TransferComplete;<br></pre>
<br>
</div>
<p>&nbsp;</p>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Class</span> ChunkEventArgs<br>    <span>Inherits</span> EventArgs<br>    <span>Public</span> Status <span>As</span> Status<br>    <span>Public</span> ChunkLength <span>As</span> <span>Integer</span><br>    <span>Public</span> Total <span>As</span> <span>Integer</span><br><br>    <span>Public</span> <span>Sub</span> <span>New</span>(<span>ByVal</span> status <span>As</span> Status, <span>ByVal</span> length <span>As</span> <span>Integer</span>, <span>ByVal</span> total <span>As</span> <span>Integer</span>)<br>        Status = status<br>        ChunkLength = length<br>        <span>Me</span>.Total = total<br>    <span>End</span> <span>Sub</span><br><span>End</span> Class</pre>
<br>
</div>
<p>These events will be called at the appropriate times and provide information to allow the UI to draw a progress bar and other status information.</p>
<p>The <b>UploadFile</b> method does exactly what you think: it uploads the file specified.&nbsp; The file contents are loaded into memory, compressed, base64 encoded, and finally URL encoded.&nbsp; Then, this large string is cut into 140 character chunks and sent to
 Twitter, one chunk at a time.&nbsp; After each chunk is uploaded, the <b>ChunkUpload</b> event is called.&nbsp; Finally, when all chunks are uploaded, a new
<b>FileEntry</b> object is created, added to the in-memory file index, and that index is finally written to the top of the Twitter status list.</p>
<p><b>C#</b>&nbsp;<b> </b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> <span>void</span> UploadFile(<span>string</span> path)<br>{<br>    Status s = <span>null</span>;<br>    <span>int</span> startID = 0;<br>    <span>int</span> length = 0;<br>    <span>int</span> chunkLength = 140;<br><br>    <span>// encode the file</span><br>    <span>string</span> file = EncodeFile(path);<br><br>    <span>// upload the chunks</span><br>    <span>for</span>(<span>int</span> i = 0; i &lt; file.Length; i&#43;= chunkLength)<br>    {<br>        <span>// get the proper length (i.e. don't get full 140 if we're at the end)</span><br>        <span>string</span> chunk = file.Substring(i, Math.Min(chunkLength, file.Length-i));<br><br>        <span>// handle the case where we chopped a chunk in the middle of an encoded character</span><br>        <span>// in this case, chop off the encoded data and reset the counter</span><br>        <span>if</span>(chunk.EndsWith(<span>&quot;%2&quot;</span>))<br>        {<br>            chunk = chunk.Substring(0, chunk.Length-2);<br>            i -= 2;<br>        }<br><br>        <span>if</span>(chunk.EndsWith(<span>&quot;%&quot;</span>))<br>        {<br>            chunk = chunk.Substring(0, chunk.Length-1);<br>            i -= 1;<br>        }<br><br>        <span>try</span><br>        {<br>            <span>// upload the chunk</span><br>            s = _twitter.UpdateStatus(chunk);<br><br>            <span>// notify listeners that we uploaded</span><br>            <span>if</span>(ChunkUpload != <span>null</span>)<br>                ChunkUpload(<span>this</span>, <span>new</span> ChunkEventArgs(s, chunk.Length, file.Length));<br>        }<br>        <span>catch</span>(TwitterRateLimitException)<br>        {<br>            <span>throw</span> <span>new</span> TwitterDriveException(<span>&quot;Twitter upload limit reached.  Please try again later.&quot;</span>);<br>        }<br><br>        <span>if</span>(i == 0)<br>            startID = s.ID;<br><br>        length&#43;&#43;;<br>    }<br><br>    <span>// create a new FileEntry for this file</span><br>    FileEntry fe = <span>new</span> FileEntry()<br>    {<br>        Filename = Path.GetFileName(path),<br>        StartStatus = startID,<br>        EndStatus = s.ID,<br>        Length = length,<br>        FileIndex = GetNextIndex()<br>    };<br><br>    <span>// update the index</span><br>    UpdateFileIndex(fe);<br><br>    <span>// notify we're done</span><br>    <span>if</span>(TransferComplete != <span>null</span>)<br>        TransferComplete(<span>this</span>, <span>null</span>);<br>}<br></pre>
<br>
</div>
<p></p>
<p></p>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> UploadFile(<span>ByVal</span> filepath <span>As</span> <span>String</span>)<br>    <span>Dim</span> s <span>As</span> Status = <span>Nothing</span><br>    <span>Dim</span> startID <span>As</span> <span>Integer</span> = 0<br>    <span>Dim</span> length <span>As</span> <span>Integer</span> = 0<br>    <span>Dim</span> chunkLength <span>As</span> <span>Integer</span> = 140<br><br>    <span>' encode the file</span><br>    <span>Dim</span> file <span>As</span> <span>String</span> = EncodeFile(filepath)<br><br>    <span>' upload the chunks</span><br>    <span>For</span> i <span>As</span> <span>Integer</span> = 0 <span>To</span> file.Length - 1 <span>Step</span> chunkLength<br>        <span>' get the proper length (i.e. don't get full 140 if we're at the end)</span><br>        <span>Dim</span> chunk <span>As</span> <span>String</span> = file.Substring(i, Math.Min(chunkLength, file.Length-i))<br><br>        <span>' handle the case where we chopped a chunk in the middle of an encoded character</span><br>        <span>' in this case, chop off the encoded data and reset the counter</span><br>        <span>If</span> chunk.EndsWith(<span>&quot;%2&quot;</span>) <span>Then</span><br>            chunk = chunk.Substring(0, chunk.Length-2)<br>            i -= 2<br>        <span>End</span> <span>If</span><br><br>        <span>If</span> chunk.EndsWith(<span>&quot;%&quot;</span>) <span>Then</span><br>            chunk = chunk.Substring(0, chunk.Length-1)<br>            i -= 1<br>        <span>End</span> <span>If</span><br><br>        <span>Try</span><br>            <span>' upload the chunk</span><br>            s = _twitter.UpdateStatus(chunk)<br><br>            <span>' notify listeners that we uploaded</span><br>            <span>RaiseEvent</span> ChunkUpload(<span>Me</span>, <span>New</span> ChunkEventArgs(s, chunk.Length, file.Length))<br>        <span>Catch</span> e1 <span>As</span> TwitterRateLimitException<br>            <span>Throw</span> <span>New</span> TwitterDriveException(<span>&quot;Twitter upload limit reached.  Please try again later.&quot;</span>)<br>        <span>End</span> <span>Try</span><br><br>        <span>If</span> i = 0 <span>Then</span><br>            startID = s.ID<br>        <span>End</span> <span>If</span><br><br>        length &#43;= 1<br>    <span>Next</span> i<br><br>    <span>' create a new FileEntry for this file</span><br>    <span>Dim</span> fe <span>As</span> <span>New</span> FileEntry() <span>With</span> {.Filename = Path.GetFileName(filepath), .StartStatus = startID, .EndStatus = s.ID, .Length = length, .FileIndex = GetNextIndex()}<br><br>    <span>' update the index</span><br>    UpdateFileIndex(fe)<br><br>    <span>' notify we're done</span><br>    <span>RaiseEvent</span> TransferComplete(<span>Me</span>, <span>Nothing</span>)<br><span>End</span> Function</pre>
<br>
</div>
<p>Let's take a closer look at the <b>EncodeFile</b> method:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>private</span> <span>string</span> EncodeFile(<span>string</span> path)<br>{<br>    <span>// load the file</span><br>    <span>byte</span>[] buff = File.ReadAllBytes(path);<br><br>    <span>// compress</span><br>    MemoryStream ms = <span>new</span> MemoryStream();<br>    GZipStream gs = <span>new</span> GZipStream(ms, CompressionMode.Compress);<br>    gs.Write(buff, 0, buff.Length);<br>    gs.Close();<br><br>    <span>byte</span>[] buffCompressed = ms.ToArray();<br><br>    <span>// base64, urlencode</span><br>    <span>return</span> HttpUtility.UrlEncode(Convert.ToBase64String(buffCompressed));<br>}</pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Private</span> <span>Function</span> EncodeFile(<span>ByVal</span> path <span>As</span> <span>String</span>) <span>As</span> <span>String</span><br>    <span>' load the file</span><br>    <span>Dim</span> buff() <span>As</span> <span>Byte</span> = File.ReadAllBytes(path)<br><br>    <span>' compress</span><br>    <span>Dim</span> ms <span>As</span> <span>New</span> MemoryStream()<br>    <span>Dim</span> gs <span>As</span> <span>New</span> GZipStream(ms, CompressionMode.Compress)<br>    gs.Write(buff, 0, buff.Length)<br>    gs.Close()<br><br>    <span>Dim</span> buffCompressed() <span>As</span> <span>Byte</span> = ms.ToArray()<br><br>    <span>' base64, urlencode</span><br>    <span>Return</span> HttpUtility.UrlEncode(Convert.ToBase64String(buffCompressed))<br><span>End</span> Function</pre>
<br>
</div>
<p>The code here reads the bytes of a file into a byte array.&nbsp; Then, a <b>MemoryStream</b> object is created and tied to a
<b>GZipStream</b> (compression) object.&nbsp; Next, the byte array is written to the stream which will compress the data on the fly.&nbsp; Once the stream is closed, calling
<b>ToArray</b> on the <b>MemoryStream</b> will return a byte array of the compressed data.&nbsp; The byte array is base64 encoded (turned into text) and finally URL encoded so it can be sent to Twitter.</p>
<p>The file index is written at the end of each file upload.&nbsp; The index is comprised of a delimited string which contains the data in the
<b>FileEntry</b> object.&nbsp; Each file is uploaded as one tweet, with an end marker to denote where the file index ends.</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>private</span> <span>void</span> WriteFileEntries()<br>{<br>    <span>// write an end marker (write this first since they come out in reverse order later)</span><br>    _twitter.UpdateStatus(FileEntryEnd);<br><br>    <span>for</span>(<span>int</span> i = 0; i &lt; _fileEntries.Count; i&#43;&#43;)<br>        WriteFileEntry(_fileEntries[i]);<br>}<br><br><span>private</span> <span>void</span> WriteFileEntry(FileEntry fe)<br>{<br>    <span>// simple delimited list of data</span><br>    <span>string</span> entry = <span>string</span>.Format(FileEntryHeader &#43;<br>                                <span>&quot;{0}&quot;</span> &#43; FileEntrySeparator &#43; <br>                                <span>&quot;{1}&quot;</span> &#43; FileEntrySeparator &#43;<br>                                <span>&quot;{2}&quot;</span> &#43; FileEntrySeparator &#43;<br>                                <span>&quot;{3}&quot;</span> &#43; FileEntrySeparator &#43;<br>                                <span>&quot;{4}&quot;</span>, <br>                                fe.Filename, fe.StartStatus, fe.EndStatus, fe.Length, fe.FileIndex);<br>    _twitter.UpdateStatus(entry);<br>}<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Private</span> <span>Sub</span> WriteFileEntries()<br>    <span>' write an end marker (write this first since they come out in reverse order later)</span><br>    _twitter.UpdateStatus(FileEntryEnd)<br><br>    <span>Dim</span> i <span>As</span> <span>Integer</span> = 0<br>    <span>Do</span> <span>While</span> i &lt; _fileEntries.Count<br>        WriteFileEntry(_fileEntries(i))<br>        i &#43;= 1<br>    <span>Loop</span><br><span>End</span> <span>Sub</span><br><br><span>Private</span> <span>Sub</span> WriteFileEntry(<span>ByVal</span> fe <span>As</span> FileEntry)<br>    <span>' simple delimited list of data</span><br>    <span>Dim</span> entry <span>As</span> <span>String</span> = <span>String</span>.Format(FileEntryHeader &amp; <span>&quot;{0}&quot;</span> &amp; FileEntrySeparator &amp; <span>&quot;{1}&quot;</span> &amp; FileEntrySeparator &amp; <span>&quot;{2}&quot;</span> &amp; FileEntrySeparator &amp; <span>&quot;{3}&quot;</span> &amp; FileEntrySeparator &amp; <span>&quot;{4}&quot;</span>, fe.Filename, fe.StartStatus, fe.EndStatus, fe.Length, fe.FileIndex)<br>    _twitter.UpdateStatus(entry)<br><span>End</span> Sub</pre>
<br>
</div>
<p>A file list can be retrieved and parsed out with the following code:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> IList&lt;FileEntry&gt; GetFileIndex()<br>{<br>    <span>bool</span> end = <span>false</span>;<br>    <span>int</span> page = 1;<br><br>    <span>// the index should be the last things tweeted, but if we have a failed upload, it may not be</span><br>    <span>while</span>(!end &amp;&amp; page &lt; 5)<br>    {<br>        IList&lt;Status&gt; indexes = _twitter.GetUserTimeline(page, 200);<br><br>        _fileEntries.Clear();<br><br>        <span>// parase out the file entries</span><br>        <span>foreach</span>(Status index <span>in</span> indexes)<br>        {<br>            FileEntry fe = ParseFileIndexString(index.Text);<br>            <span>if</span>(fe != <span>null</span>)<br>            {<br>                fe.IndexStatusId = index.ID;<br>                _fileEntries.Add(fe);<br>            }<br><br>            <span>if</span>(index.Text.StartsWith(FileEntryEnd))<br>            {<br>                end = <span>true</span>;<br>                <span>break</span>;<br>            }<br>        }<br>        page&#43;&#43;;<br>    }<br>    <span>return</span> _fileEntries;<br>}<br><br><span>private</span> FileEntry ParseFileIndexString(<span>string</span> index)<br>{<br>    <span>if</span>(!index.StartsWith(FileEntryHeader))<br>        <span>return</span> <span>null</span>;<br><br>    <span>string</span>[] fileEntry = index.Split(Convert.ToChar(FileEntrySeparator));<br>    FileEntry fe = <span>new</span> FileEntry()<br>                    {<br>                        Filename = fileEntry[0].Replace(FileEntryHeader, <span>string</span>.Empty),<br>                        StartStatus = <span>int</span>.Parse(fileEntry[1]),<br>                        EndStatus = <span>int</span>.Parse(fileEntry[2]),<br>                        Length = <span>int</span>.Parse(fileEntry[3]),<br>                        FileIndex = <span>int</span>.Parse(fileEntry[4])<br>                    };<br>    <span>return</span> fe;<br>}</pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> GetFileIndex() <span>As</span> IList(Of FileEntry)<br>    <span>Dim</span> [<span>end</span>] <span>As</span> <span>Boolean</span> = <span>False</span><br>    <span>Dim</span> page <span>As</span> <span>Integer</span> = 1<br><br>    <span>' the index should be the last things tweeted, but if we have a failed upload, it may not be</span><br>    <span>Do</span> <span>While</span> (<span>Not</span> [<span>end</span>]) <span>AndAlso</span> page &lt; 5<br>        <span>Dim</span> indexes <span>As</span> IList(Of Status) = _twitter.GetUserTimeline(page, 200)<br><br>        _fileEntries.Clear()<br><br>        <span>' parase out the file entries</span><br>        <span>For</span> <span>Each</span> index <span>As</span> Status <span>In</span> indexes<br>            <span>Dim</span> fe <span>As</span> FileEntry = ParseFileIndexString(index.Text)<br>            <span>If</span> fe IsNot <span>Nothing</span> <span>Then</span><br>                fe.IndexStatusId = index.ID<br>                _fileEntries.Add(fe)<br>            <span>End</span> <span>If</span><br><br>            <span>If</span> index.Text.StartsWith(FileEntryEnd) <span>Then</span><br>                [<span>end</span>] = <span>True</span><br>                <span>Exit</span> <span>For</span><br>            <span>End</span> <span>If</span><br>        <span>Next</span> index<br>        page &#43;= 1<br>    <span>Loop</span><br>    <span>Return</span> _fileEntries<br><span>End</span> <span>Function</span><br><br><span>Private</span> <span>Function</span> ParseFileIndexString(<span>ByVal</span> index <span>As</span> <span>String</span>) <span>As</span> FileEntry<br>    <span>If</span> (<span>Not</span> index.StartsWith(FileEntryHeader)) <span>Then</span><br>        <span>Return</span> <span>Nothing</span><br>    <span>End</span> <span>If</span><br><br>    <span>Dim</span> fileEntry() <span>As</span> <span>String</span> = index.Split(Convert.ToChar(FileEntrySeparator))<br>    <span>Dim</span> fe <span>As</span> <span>New</span> FileEntry() <span>With</span> {.Filename = fileEntry(0).Replace(FileEntryHeader, <span>String</span>.Empty), .StartStatus = <span>Integer</span>.Parse(fileEntry(1)), .EndStatus = <span>Integer</span>.Parse(fileEntry(2)), .Length = <span>Integer</span>.Parse(fileEntry(3)), .FileIndex = <span>Integer</span>.Parse(fileEntry(4))}<br>    <span>Return</span> fe<br><span>End</span> Function</pre>
<br>
</div>
<p>This code will retrieve the user's timeline, loop through the tweets, looking for file index entries (those that start with the proper delimiter).&nbsp; When one is found, the data is parsed back into a
<b>FileEntry</b> object and added to the in-memory cache.&nbsp; You will note that the
<b>GetFileIndex</b> method will read up to 1000 tweets looking for the end marker before giving up.</p>
<p>Now that we can upload files and build the index, we need to be able to download, decode and save a file.&nbsp; This is done in the obviously named
<b>DownloadFile </b>method:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> <span>void</span> DownloadFile(FileEntry fe, <span>string</span> path)<br>{<br>    StringBuilder sb = <span>new</span> StringBuilder(fe.Length * 140);<br><br>    <span>// get statuses for this user starting/ending at the IDs for this file</span><br>    IList&lt;Status&gt; chunks = _twitter.GetUserTimeline(fe.StartStatus-1, fe.EndStatus, 1, 200);<br><br>    <span>// order them from oldest to newest</span><br>    var orderedChunks = from chunk <span>in</span> chunks<br>                        orderby chunk.ID ascending<br>                        select chunk;<br><br>    <span>foreach</span>(Status chunk <span>in</span> orderedChunks)<br>    {<br>        <span>// trim off any extra characters</span><br>        <span>string</span> newChunk = chunk.Text.TrimEnd(<span>'.'</span>).Trim();<br>        sb.Append(newChunk);<br><br>        <span>// notify listeners that we downloaded a chunk</span><br>        <span>if</span>(ChunkDownload != <span>null</span>)<br>            ChunkDownload(<span>this</span>, <span>new</span> ChunkEventArgs(chunk, newChunk.Length, fe.Length * 140));<br>    }<br><br>    <span>// decode and write the file</span><br>    <span>byte</span>[] buff = DecodeFile(sb.ToString());<br>    File.WriteAllBytes(Path.Combine(path, fe.Filename), buff);<br><br>    <span>// notify that we're done</span><br>    <span>if</span>(TransferComplete != <span>null</span>)<br>        TransferComplete(<span>this</span>, <span>null</span>);<br>}<br></pre>
<br>
</div>
<p>&nbsp;<b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> DownloadFile(<span>ByVal</span> fe <span>As</span> FileEntry, <span>ByVal</span> filepath <span>As</span> <span>String</span>)<br>    <span>Dim</span> sb <span>As</span> <span>New</span> StringBuilder(fe.Length * 140)<br><br>    <span>' get statuses for this user starting/ending at the IDs for this file</span><br>    <span>Dim</span> chunks <span>As</span> IList(Of Status) = _twitter.GetUserTimeline(fe.StartStatus-1, fe.EndStatus, 1, 200)<br><br>    <span>' order them from oldest to newest</span><br>    <span>Dim</span> orderedChunks = _<br>        From chunk <span>In</span> chunks _<br>        Order By chunk.ID Ascending _<br>        <span>Select</span> chunk<br><br>    <span>For</span> <span>Each</span> chunk <span>As</span> Status <span>In</span> orderedChunks<br>        <span>' trim off any extra characters</span><br>        <span>Dim</span> newChunk <span>As</span> <span>String</span> = chunk.Text.TrimEnd(<span>&quot;.&quot;</span>c).Trim()<br>        sb.Append(newChunk)<br><br>        <span>' notify listeners that we downloaded a chunk</span><br>        <span>RaiseEvent</span> ChunkDownload(<span>Me</span>, <span>New</span> ChunkEventArgs(chunk, newChunk.Length, fe.Length * 140))<br>    <span>Next</span> chunk<br><br>    <span>' decode and write the file</span><br>    <span>Dim</span> buff() <span>As</span> <span>Byte</span> = DecodeFile(sb.ToString())<br>    File.WriteAllBytes(Path.Combine(filepath, fe.Filename), buff)<br><br>    <span>' notify that we're done</span><br>    <span>RaiseEvent</span> TransferComplete(<span>Me</span>, <span>Nothing</span>)<br><span>End</span> Function</pre>
<br>
</div>
<p>This method returns the user's timeline starting and ending at the tweets specified in the
<b>FileEntry</b> object.&nbsp; The status list is ordered in ascending order (i.e. oldest to newest).&nbsp; Each status is appended to the previous using a
<b>StringBuilder</b> object.&nbsp; When all chunks are processed, the file is decoded and saved to the chosen location.</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>public</span> <span>byte</span>[] DecodeFile(<span>string</span> data)<br>{<br>    <span>// base64 to binary</span><br>    <span>byte</span>[] buff = Convert.FromBase64String(data);<br><br>    <span>// decompress</span><br>    MemoryStream ms = <span>new</span> MemoryStream(buff);<br>    GZipStream gs = <span>new</span> GZipStream(ms, CompressionMode.Decompress, <span>false</span>);<br><br>    <span>// original</span><br>    <span>byte</span>[] decompressed = ReadAllBytes(gs);<br>    <span>return</span> decompressed;<br>}<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>Public</span> <span>Function</span> DecodeFile(<span>ByVal</span> data <span>As</span> <span>String</span>) <span>As</span> <span>Byte</span>()<br>    <span>' base64 to binary</span><br>    <span>Dim</span> buff() <span>As</span> <span>Byte</span> = Convert.FromBase64String(data)<br><br>    <span>' decompress</span><br>    <span>Dim</span> ms <span>As</span> <span>New</span> MemoryStream(buff)<br>    <span>Dim</span> gs <span>As</span> <span>New</span> GZipStream(ms, CompressionMode.Decompress, <span>False</span>)<br><br>    <span>' original</span><br>    <span>Dim</span> decompressed() <span>As</span> <span>Byte</span> = ReadAllBytes(gs)<br>    <span>Return</span> decompressed<br><span>End</span> Function</pre>
<br>
</div>
<p>To decode the file, we do the opposite of what we did before: the file is converted to bytes from the base64 encoded string, a
<b>GZipStream</b> is used to decompress the data, and the final, uncompressed file contents are returned to the caller to be saved to the disk.</p>
<p>Be sure to look through the entire <b><a class="linkification-ext" title="Linkification: http://TwitterDrive.cs/vb" href="http://TwitterDrive.cs/vb">TwitterDrive.cs/vb</a></b> file for the full picture, but these are the important parts.</p>
<h4>User Interface</h4>
<p>The final piece is the user interface.</p>
<p><img title="4-1-2009 4-01-42 AM" border="0" alt="4-1-2009 4-01-42 AM" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9525376/4-1-2009_204-01-42_20AM_3.png" width="289" height="350">
</p>
<p>A very simple UI for uploading, downloading and deleting files.&nbsp; At the start of the application, the three TwitterDrive events are hooked:
<b>ChunkUpload</b>, <b>ChunkDownload</b>, and <b>TransferComplete</b>.&nbsp; These three event handlers are used to update the progress bar on a dialog box that pops up during the file transfer.</p>
<p>When upload or download is selected, the file is selected, and a new thread is created to start the actual process.&nbsp; Here is what the download process looks like:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>// start a new thread to grab the file</span><br>Thread t = <span>new</span> Thread(() =&gt; _twitterDrive.DownloadFile(fe, fbd.SelectedPath));<br>t.Start();<br><br><span>if</span>(_progress.ShowDialog() == DialogResult.Cancel)<br>    t.Abort();<br><span>else</span><br>    MessageBox.Show(<span>&quot;File download complete.&quot;</span>, <span>&quot;TwitterDrive&quot;</span>, MessageBoxButtons.OK, MessageBoxIcon.Information);<br></pre>
<br>
</div>
<p><b>VB</b></p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet"><span>' start a new thread to grab the file</span><br><span>Dim</span> t <span>As</span> <span>New</span> Thread(<span>CType</span>(<span>Function</span>() _twitterDrive.DownloadFile(fe, fbd.SelectedPath), ThreadStart))<br>t.Start()<br><br><span>If</span> _progress.ShowDialog() = System.Windows.Forms.DialogResult.Cancel <span>Then</span><br>    t.Abort()<br><span>Else</span><br>    MessageBox.Show(<span>&quot;File download complete.&quot;</span>, <span>&quot;TwitterDrive&quot;</span>, MessageBoxButtons.OK, MessageBoxIcon.Information)<br><span>End</span> <span>If</span><br></pre>
<br>
</div>
<p>A new thread is created, whose <b>ThreadStart</b> parameter is the <b>DownloadFile</b> method of the
<b>TwitterDrive</b> class.&nbsp; The thread is started, and the progress dialog box is shown.&nbsp; If the progress box is cancelled, the thread is aborted, otherwise the dialog box is closed in response to the
<b>TransferComplete</b> event sent by the <b>TwitterDrive</b> class.</p>
<h4>Using the Application</h4>
<ol>
<li>Create a new Twitter account for use in TwitterDrive. </li><li>Enter the credentials for this new account in the provided textboxes and click Refresh.&nbsp; Or, if you want to download files from someone else, enter just the username and click Refresh.
</li><li>Upload and download data at will. </li></ol>
<h4>Conclusion</h4>
<p>And there we have it.&nbsp; A functionally useless application that actually works.&nbsp; Give it a try and find out what the limitations are.&nbsp; Just be sure to use a Twitter account that isn't your main feed otherwise you'll have some pretty angry followers.</p>
<h4>Thanks</h4>
<p>A special thanks to <a href="http://www.markzaugg.com/" target="_blank">Mark Zaugg</a>,
<a href="http://blogs.msdn.com/danielfe" target="_blank">Dan Fernandez</a>, and <a href="http://www.gmontrone.com/" target="_blank">
Giovanni Montrone</a> for helping me test this application.&nbsp; Giovanni is also partly responsible for this horrible idea after joking that I should Twitter him a file.&nbsp; So blame him.</p>
<p>Also thanks to <a href="http://www.betterthaneveryone.com/" target="_blank">Clint Rutkas</a> for throwing together the icon (it's a combo of the SkyDrive icon &#43; the Twitter icon).</p>
<h4>Bio</h4>
<p>Brian is a <a href="https://mvp.support.microsoft.com/profile/Brian.Peek">Microsoft C# MVP</a> who has been actively developing in .NET since its early betas in 2000, and who has been developing solutions using Microsoft technologies and platforms for even
 longer. Along with .NET, Brian is particularly skilled in the languages of C, C&#43;&#43; and assembly language for a variety of CPUs. He is also well-versed in a wide variety of technologies including web development, document imaging, GIS, graphics, game development,
 and hardware interfacing. Brian has a strong background in developing applications for the health-care industry, as well as developing solutions for portable devices, such as tablet PCs and PDAs. Additionally, Brian has co-authored the book &quot;<a href="http://www.amazon.com/exec/obidos/ASIN/0596520743/brianpcom-20">Coding4Fun:
 10 .NET Programming Projects for Wiimote, YouTube, World of Warcraft, and More</a>&quot; published
<a href="http://www.oreilly.com/">O'Reilly</a>. He previously co-authored the book &quot;<a href="http://www.amazon.com/dp/0735711410/">Debugging ASP.NET</a>&quot; published by New Riders.&nbsp; Brian is also an author for MSDN's
<a href="http://blogs.msdn.com/coding4fun/">Coding4Fun</a> website.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:e3cd532524cb4af88f7a9e7600cceaa1">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/TwitterDrive--The-Revolution-in-Cloud-Storage</comments>
      <itunes:summary>



&amp;nbsp;

In this article, Brian Peek will provide a technical overview of TwitterDrive, an application used to store and retrieve files via the Twitter messaging service.



Brian Peek
ASPSOFT, Inc.

Difficulty: Intermediate
Time Required: 2-3 hours
Cost: Free
Software: Visual C# Express 2008 SP1, Visual Basic Express 2008 SP1, or Visual Studio 2008 SP1, .NET Framework 3.5 SP1
Hardware: None
Download: Application,
Source Code
Discussion Forum: Forum




&amp;nbsp; 
Introduction
As you&#39;ve probably guessed by now, TwitterDrive is my April Fool&#39;s Day application for Coding4Fun this year.&amp;nbsp; While the application does actually work, the limitations of Twitter make it functionally useless.&amp;nbsp; That said, I&#39;ll still take you through
 the important parts as there is some value in the code with regard to the Twitter API, LINQ to XML, threading, and a couple other things. 
How It Works
Not very well, actually.&amp;nbsp; The concept is we take a file, compress it, uuencode/base64 encode it (that is, make a text representation of the binary contents), and then upload it 140 characters at a time to Twitter as status messages.&amp;nbsp; When the file upload
 is complete, an index is written of every file that is currently stored on Twitter with some information that can be used to later retrieve the file. 
Twitter
Let&#39;s start with the Twitter API.&amp;nbsp; Full documentation on this API can be found at: 
http://apiwiki.twitter.com/ 
TwitterDrive only requires a very small subset of this functionality to work.&amp;nbsp; We need the ability to post a new status message, download a user timeline, destroy a status, and verify the user&#39;s credentials.&amp;nbsp; All of these things are handled in the
TwitterService class. 
The heart of this class consists of two methods:&amp;nbsp; GetTwitter and PostTwitter.&amp;nbsp;
GetTwitter will make a GET request to Twitter of the specified URL, and 
PostTwitter will make a POST request to Twitter of the specified URL with the supplied data. 
C# 

private XDocument Get</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/TwitterDrive--The-Revolution-in-Cloud-Storage</link>
      <pubDate>Wed, 01 Apr 2009 04:05:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/TwitterDrive--The-Revolution-in-Cloud-Storage</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9525376_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9525376_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>3</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/TwitterDrive--The-Revolution-in-Cloud-Storage/RSS</wfw:commentRss>
      <category>Productivity</category>
      <category>utility</category>
      <category>Web</category>
      <category>Windows</category>
      <category>Holiday</category>
      <category>april fools day</category>
    </item>
  <item>
      <title>Xbox 360 Virtual Fireplace</title>
      <description><![CDATA[If you enjoyed the <a href="http://blog.seanalexander.com/2008/12/23/UpdatedYuleLogVisualizationForWindowsMediaPlayer11VistaXP.aspx">Windows Media Player Yule Log visualization</a> but don’t have a PC in your living room, you may want to check out <a href="http://marketplace.xbox.com/en-US/games/offers/00000001-0000-4000-8000-00005855014c?cid=MajorNelson&amp;partner=MajorNelson">this virtual fireplace</a> instead. As&nbsp;<a href="http://majornelson.com/archive/2008/12/21/xbox-360-virtual-fireplace.aspx">Major Nelson reports</a>, an Xbox LIVE Member <a href="http://live.xbox.com/en-US/profile/profile.aspx?pp=0&amp;GamerTag=SniperED007">SniperED007</a> used the XNA tools to create this visualization “that has all the sights and sounds of a nice wintery fireplace.”<br><br>You can see the fireplace in action here at <a href="http://catalog.xna.com/en-US/GameDetails.aspx?catalogEntryId=d7cd3acb-c786-4140-958d-e87c10d42b89&amp;type=2">XNA.com</a> and you can <a href="http://marketplace.xbox.com/en-US/games/offers/00000001-0000-4000-8000-00005855014c?cid=MajorNelson&amp;partner=MajorNelson">add the demo directly to your Xbox 360 download queue</a>. <br><br>According to SniperED007, Fireplace will allow you to “Enjoy the awesome ambiance of a crackling fireplace in your living room. With realistic smoldering embers and flickering flames it sets the perfect backdrop for a relaxing evening.”&nbsp; The demo is free, the full version is 400 points.  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:6f0d168d36ac481394a59e0e0027c785">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/Xbox-360-Virtual-Fireplace</comments>
      <itunes:summary>If you enjoyed the Windows Media Player Yule Log visualization but don’t have a PC in your living room, you may want to check out this virtual fireplace instead. As&amp;nbsp;Major Nelson reports, an Xbox LIVE Member SniperED007 used the XNA tools to create this visualization “that has all the sights and sounds of a nice wintery fireplace.”You can see the fireplace in action here at XNA.com and you can add the demo directly to your Xbox 360 download queue. According to SniperED007, Fireplace will allow you to “Enjoy the awesome ambiance of a crackling fireplace in your living room. With realistic smoldering embers and flickering flames it sets the perfect backdrop for a relaxing evening.”&amp;nbsp; The demo is free, the full version is 400 points. </itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/Xbox-360-Virtual-Fireplace</link>
      <pubDate>Fri, 26 Dec 2008 08:16:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/Xbox-360-Virtual-Fireplace</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/320/on10_480ab192-7571-4dfb-bac0-fb5804baa29f.jpg" height="0" width="0"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/85/on10_5687591b-ebdc-47cf-9d8b-8a679bff19c0.jpg" height="64" width="85"></media:thumbnail>      
      <dc:creator>Sarah Perez</dc:creator>
      <itunes:author>Sarah Perez</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/Xbox-360-Virtual-Fireplace/RSS</wfw:commentRss>
      <category>Visualization</category>
      <category>Xbox 360</category>
      <category>XNA</category>
      <category>Holiday</category>
      <category>XNA framework</category>
    </item>
  <item>
      <title>Get the Windows Media Player Yule Log Visualization for Vista</title>
      <description><![CDATA[Ah, just in time for the holidays! Sean Alexander has released an updated Yule Log Visualization for Windows Media Player. Originally released&nbsp; as a part of the <a href="http://www.microsoft.com/windows/windowsmedia/player/bonuspack/default.aspx">Windows Media Bonus Pack for Windows XP</a>, this visualization is simply a fireplace complete with crackling logs and dancing flames perfect for bringing a bit of holiday spirit to our PCs. <br><br>Although the Yule Log was a popular visualization for XP users, it had not been updated for later versions of Windows. But now, thanks to Sean’s (<em>unofficial) </em>version, you can enjoy this holiday treat once again. <br><br>To install, first <a href="http://cid-16779c80218545f3.skydrive.live.com/self.aspx/Yule%20Log%20Viz/WMP%7C_Yule%7C_Viz.msi">download the executable</a><em> (works for both 32 and 64-bit versions of Windows),</em> then go to Now Playing –&gt; Visualization –&gt; Yule Log. Now, just play your music! <br><br>If you want to tweak the effects, choose &quot;Options&quot;, then select the Yule Log Visualization and click the Properties button.&nbsp; There you'll find a slider for sensitivity which you can adjust. <br><br>Thanks, Sean, and happy holidays to all!  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:4ef9e912afd84c308de99e0e0027c23e">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/Get-the-Windows-Media-Player-Yule-Log-Visualization-for-Vista</comments>
      <itunes:summary>Ah, just in time for the holidays! Sean Alexander has released an updated Yule Log Visualization for Windows Media Player. Originally released&amp;nbsp; as a part of the Windows Media Bonus Pack for Windows XP, this visualization is simply a fireplace complete with crackling logs and dancing flames perfect for bringing a bit of holiday spirit to our PCs. Although the Yule Log was a popular visualization for XP users, it had not been updated for later versions of Windows. But now, thanks to Sean’s (unofficial) version, you can enjoy this holiday treat once again. To install, first download the executable (works for both 32 and 64-bit versions of Windows), then go to Now Playing –&amp;gt; Visualization –&amp;gt; Yule Log. Now, just play your music! If you want to tweak the effects, choose &amp;quot;Options&amp;quot;, then select the Yule Log Visualization and click the Properties button.&amp;nbsp; There you&#39;ll find a slider for sensitivity which you can adjust. Thanks, Sean, and happy holidays to all! </itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/Get-the-Windows-Media-Player-Yule-Log-Visualization-for-Vista</link>
      <pubDate>Fri, 26 Dec 2008 08:01:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/Get-the-Windows-Media-Player-Yule-Log-Visualization-for-Vista</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/320/on10_bb48e98f-ba24-417c-874e-badcc5e58c08.jpg" height="0" width="0"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/85/on10_e739fcc2-1e28-44f2-abff-fddfb3f0ec9c.jpg" height="64" width="85"></media:thumbnail>      
      <dc:creator>Sarah Perez</dc:creator>
      <itunes:author>Sarah Perez</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/Get-the-Windows-Media-Player-Yule-Log-Visualization-for-Vista/RSS</wfw:commentRss>
      <category>Visualization</category>
      <category>Visual Effects</category>
      <category>Windows Media Player</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Controlling Your Festive Lights with the .NET Micro Framework</title>
      <description><![CDATA[
<table class="" cellspacing="0" cellpadding="2" width="470" border="0">
<tbody>
<tr>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Author:</strong></td>
<td class="" valign="top" width="363">Rob Miles: <a href="http://www.robmiles.com">
www.robmiles.com</a> </td>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Download:</strong></td>
<td class="" valign="top" width="363"><a title="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/festivelights1.0.zip" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/festivelights1.0.zip">Download</a></td>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Software:</strong></td>
<td class="" valign="top" width="363">Visual Studio 2008 Express Edition or better,
<br>
<a href="http://www.microsoft.com/netmf/about/gettingstarted.mspx">.NET Micro Framework 3.0</a></td>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Hardware:</strong></td>
<td class="" valign="top" width="363"><a href="http://www.digi.com/products/embeddedsolutions/digiconnectme.jsp">Digi Connect-ME</a>
<br>
<a href="http://www.ghielectronics.com/embeddedmaster.php">GHI Electronics Embedded Master</a>
<br>
<a href="http://devicesolutions.net/Products/Tahoe.aspx">Devices Solutions Tahoe II
</a></td>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Time Required:</strong></td>
<td class="" valign="top" width="363">3 hours</td>
</tr>
<tr>
<td class="" valign="top" width="105"><strong>Cost:</strong></td>
<td class="" valign="top" width="363">30 dollars for lights plus the .NET Micro Framework device</td>
</tr>
</tbody>
</table>
<p>The Micro Framework is one of the newest kids on the .NET block, but it does something really rather wonderful. It brings embedded development within the reach of any C# programmer. If you know C# and love Visual Studio, you can now get started building
 hardware and controlling it with your software. Moreover, it lets developers achieve one of their most cherished dreams, to control their festive lights using programs that they have written. This project shows you how to do just that and adds an extra magical
 feature, in that you can make all your festive lights flash red whenever I, Rob Miles, make a new post on that most famous of blogs,
<a href="http://www.robmiles.com">www.robmiles.com</a>. </p>
<p>Actually, you can modify the code so that you can make your lights do most anything in response to an event that happens on the web. You could signal home that you are running late, send the weather forecast to your Christmas tree or explore any number of
 communication options. You might decide that this is so useful that you leave your decorations up all year round.</p>
<p>If you just want to play with the .NET Micro Framework and get a feel for how easy it is to create software for tiny devices you don't actually need to use any extra hardware at all. The project comes with a complete emulation of the lights display so that
 you can run the whole thing on your computer and learn how hardware and software can be made to work together without burning your fingers with a soldering iron.</p>
<p>However building the hardware will give you an understanding of how some simple electronic components can be controlled from C# and even how serial and parallel data transfer works. It is also great fun.</p>
<p>To get started you will need some hardware and some software. Let's take each in turn.</p>
<h1>Hardware</h1>
<h2>Processor Hardware</h2>
<p>The .NET Micro Framework lets you run C# programs on tiny embedded devices. There are a number of these available today, and they are getting progressively cheaper. You can base this project on any.NET Micro Framework device that has a network port and three
 or more output ports. The ones I'd recommend are:</p>
<ul>
<li>Digi Connect-ME: <a href="http://www.digi.com/products/embeddedsolutions/digiconnectme.jsp">
http://www.digi.com/products/embeddedsolutions/digiconnectme.jsp</a> </li><li>GHI Electronics Embedded Master: <a href="http://www.ghielectronics.com/embeddedmaster.php">
http://www.ghielectronics.com/embeddedmaster.php</a> </li><li>Devices Solutions Tahoe II: <a href="http://devicesolutions.net/Products/Tahoe.aspx">
http://devicesolutions.net/Products/Tahoe.aspx</a> </li></ul>
<p>I built the project for Digi Connect board but the code can be customised for any of the above platforms. The beauty of the .NET Micro Framework is that you hardly need to change your program even if the underlying hardware is completely replaced. The only
 thing you will have to do is adjust the code to target different output pins. I'll flag this part of the program up when we get to it.</p>
<p>The project as supplied runs on a special emulator that runs on the PC and behaves like a .NET Micro Framework device with lights connected, so you can get started exploring the code right away.</p>
<h2>Lights</h2>
<p>I'm keeping things deliberately low voltage for this project. This means that kids of all ages can have a go at building the hardware without messing around with mains. The lights that I used were supplied as lines of twenty leds wired up as four strands
 of five leds each. All the leds in each strand were the same colour. The lights were fitted with a little battery box which held three AA batteries and a tiny controller. To get my display I simply removed the battery box and connected the strands to my hardware.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image.png"><img title="image" height="226" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb.png" width="324" border="0"></a>&nbsp;
<br>
<strong>Figure 1: My Battery Powered Lights</strong></p>
<p>You can do the same with any low power lighting kit that you wish to use. The drivers that I'm using can handle around 500 milliamps of continuous current and so you can connect a fair number of lights to each strand.
</p>
<h2>Buying the Lights</h2>
<p>The lights I used can be bought in the UK from Lights4Fun: www.lights4fun.co.uk and are called &quot;C-LED-4.5-M 20 Multi Coloured Battery Operated LED Fairy Lights&quot;. They are supplied with a battery box and controller that you can remove to connect to the Darlington
 drivers. I used an old 5 volt mobile phone charger to power the lights. If you search eBay for &quot;led christmas lights battery&quot; you should find plenty of suppliers.</p>
<h2>Driver Hardware</h2>
<p>We can't connect a .NET Micro Framework device directly to our lights. There are two reasons for this:</p>
<ol>
<li>The Micro Framework device will not be able to switch the amount of current that we need to drive the lights themselves.
</li><li>The Micro Framework device will not have enough outputs to control all the lights that we want to use.
</li></ol>
<p>This means that we need to make some hardware that goes between the processor and our lights. I actually don't see this as a problem. Making hardware is great fun, seeing something that you've built spring into life is very nice. The hardware we are going
 to use will provide a means by which we can control many hundreds of lights from a single Micro Framework board if we wish. It also has the ability to switch reasonable amounts of current, so you can use quite large numbers of lights if you wish. We are going
 to use two semiconductor components, a CD4094 Shift Register/Latch and a ULN2803 Octal Darlington Driver. A pair of these chips will allow us to control 8 outputs. If you want to control more outputs you simply get more chips and chain them together. For my
 version of the project I just used one of each chip, you can use as many as you like.The shift registers and Darlington amplifiers can be obtained in the UK from Maplin:
<a href="http://www.maplin.co.uk">www.maplin.co.uk</a>. The chip numbers and part numbers as are as follows: QW54J 4094 Shift Register, QY79L ULN2803A Darlington Driver. In the US you can obtain the components and breadboard from Digi-Key:
<a href="http://www.digikey.com">www.digikey.com</a>. </p>
<h2>Serial and Parallel Data</h2>
<p>You might be wondering how we can use just three output lines to control lots of lights. We are going to do this by using the three output lines to provide a
<i>serial</i> data stream which is converted by our hardware into <i>parallel</i> data that can be used to control our lights. This is a fundamental principle of digital electronics and is how, amongst many other things, computer networks transfer data.</p>
<p>We are going to use three signals which are called <b>clock</b>, <b>data</b> and
<b>latch</b>. Each of these can be set high (a voltage is present) or low (no voltage is present) by the .NET Micro Framework device under the control of our software. The signals are connected to the clock, data and latch inputs of our CD4094 shift register
 so that the program can talk to it.</p>
<p>The clock line triggers the shift register to do two things:</p>
<ol>
<li>Shift all the bits along to make room. </li><li>Sample the value of the data input and store this value in the space that was created.
</li></ol>
<p>To get a feel for how this works, take a look at Figure 2 below. It shows a shift register with a pattern of bits in it. The pattern is
<b>01100001</b>. Note that although this represents a number; it can also be regarded as a pattern of 0s and 1s in the shift register itself. The value 0 means 0 volts and the value 1 means some volts. These are the signals that will be used to control our
 lights. I'm going to call them 0 and 1 from now on. The Shift Register has Clock, Data and Latch signals connected and they are all set to 1. We can ignore the latch part of the chip for now.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_3.png"><img title="image" height="251" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_3.png" width="500" border="0"></a>
</p>
<p><strong>Figure 2: A shift register and latch with some data in it</strong></p>
<p>When the clock signal changes from 1 to 0 this causes the shift register to perform the two steps described above. First the data is shifted along to the right. Note that this means that there is an &quot;empty&quot; location at the start of the register, and that
 the right most bit in the register &quot;falls off&quot; the register and disappears. Figure 3 shows how this works.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_4.png"><img title="image" height="236" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_4.png" width="500" border="0"></a>
</p>
<p><strong>Figure 3: Shifting along the values in the shift register</strong></p>
<p>Once the shift has finished the shift register can copy the data signal into the empty bit at the left as shown in Figure 4 below.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_5.png"><img title="image" height="251" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_5.png" width="500" border="0"></a>
<strong><br>
Figure 4: Storing the new data bit</strong></p>
<p>By repeating this process 8 times a program can load a new pattern of 8 bits into the shift register. Then it is time to latch the new value to control the lights. This is the point at which the lights will appear to change. When the latch value is changed
 from 0 to 1 this causes the chip to copy the value in the Shift Register into the latch, as shown in Figure 5 below.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_6.png"><img title="image" height="251" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_6.png" width="500" border="0"></a>
</p>
<p><strong>Figure 5: Copying the shift register pattern into the latch.</strong></p>
<p>The latch is required so that the lights will not flicker as the new patterns are shifted into position. Each of the bits in the latch is connected to an output pin on the CD4094 which is used to switch a particular light colour on or off.</p>
<p>We need to create some C# that will provide the appropriate sequence of signals. It turns out that using the .NET Micro Framework to achieve this is actually very easy. The
<b>displayByte</b> method below sends an 8 bit value into a shift register and then latches it into the output. If you read through the code you can see how the clock, data and latch values are all set to true (high) or false (low) to first clock the data out
 and then trigger the latch to display the pattern on the lights. The input is an 8 bit byte value and the program uses a mask to pick out the value of each bit in turn and set the data output accordingly.</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> displayByte(<span class="kwrd">byte</span> <span class="kwrd">value</span>)
{
    latchPort.Write(<span class="kwrd">false</span>);
    clockPort.Write(<span class="kwrd">false</span>);

    <span class="kwrd">byte</span> mask = 1;

    <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; 8; i&#43;&#43;)
    {
        <span class="kwrd">if</span> ((<span class="kwrd">value</span> &amp; mask) &gt; 0)
        {
            dataPort.Write(<span class="kwrd">true</span>);
        }
        <span class="kwrd">else</span>
        {
            dataPort.Write(<span class="kwrd">false</span>);
        }
        clockPort.Write(<span class="kwrd">true</span>);
        clockPort.Write(<span class="kwrd">false</span>);
        mask &lt;&lt;= 1;
    }
    latchPort.Write(<span class="kwrd">true</span>);
    latchPort.Write(<span class="kwrd">false</span>);
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The <b>dataPort</b>, <b>clockPort</b> and <b>latchPort</b> variables are instances of the .NET Micro Framework class
<b>OutputPort</b>, which provides a method called <b>Write</b> which can be used to control the state of the output signal. We will consider how these are created a little later in the article.</p>
<p>The sample code for this project comes with a software emulator of the CD4094 which shows how it works. Figure 6 below shows that a new pattern is in the process of being shifted into the shift register, while the lights retain the previous one in the latch.
 The Clock and Data signals are high and the next statement will drop the Clock signal to add the next bit into the new pattern.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_7.png"><img title="image" height="303" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_7.png" width="264" border="0"></a>
</p>
<p><strong>Figure 6: The light emulator</strong></p>
<p>This figure also shows that I have two bits in the pattern controlling a strand of each colour. You can single step through the displayByte method above and watch it perform this output.</p>
<p>You can use this technique every time you want to control a large number of outputs using a small number of output pins. The CD4094 has &quot;daisy chain&quot; inputs and outputs so that the devices can be connected in sequence. If I used two devices I could control
 16 bits, with three I could control 24 and so on. This would require only minimal changes to the software.</p>
<h2>Output Driver</h2>
<p>The CD4094 device will produce a signal output, but it is not really powerful enough to drive things like lights. To do this we need an amplifier and the ULN2803 Octal Darlington Driver is perfect for this. It is packaged as a single chip which contains
 8 pairs of transistors. Each transistor pair is wired in a &quot;Darlington&quot; configuration and can be used as a switch which is controlled by on output from the CD4094. When the transistors are turned on they allow current to pass through them and this will cause
 the lamps to light. The lights that I bought used a &quot;pull down&quot; arrangement to make them light up. All of the light emitting diode (LED) lamps had one end wired to a common line that was connected to the positive supply. To make the a chain of LEDs light the
 other end that controls that chain needed to be pulled down to the ground level. This is a common arrangement with lights like these. The ULN2803 driver has the transistors wired in an arrangement that allows it to pull signals low in this way. Figure 7 shows
 how this arrangement works. The resistor shown is actually wired into each LED in the set of lights that I used.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_8.png"><img title="image" height="201" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_8.png" width="226" border="0"></a>
<br>
<strong>Figure 7: Lighting the LEDs</strong></p>
<h5>Complete Circuit</h5>
<p>The complete circuit shown in Figure 8 simply links each output of the CD4094 shift register to an input on the ULN2803 Darlington Driver. Note that there is no reason to link any particular bit with any other, the diagram shown is one which will translate
 most easily to a prototype &quot;breadboard&quot;.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_9.png"><img title="image" height="260" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_9.png" width="500" border="0"></a>
<br>
<strong>Figure 8: The Complete Circuit</strong></p>
<p>The diagram just shows four lights connected to OUT1 from pin 18 of the ULN2803, the other 7 channels are connected in exactly the same way. Some of the pins can be left unconnected. Pins 9 and 10 of the CD4094 are only required if you are connecting multiple
 shift registers together and the common connection on pin 10 of the ULN2803 is not required. The Latch, Data and Clock signals on the CD4094 are connected to the output signals from the Micro Framework device.
</p>
<p>Figure 9 shows the completed circuit built up on a prototype breadboard. The chip on the left is the CD4094 and the one on the right is the ULN2803.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_10.png"><img title="image" height="331" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9149635/image_thumb_10.png" width="484" border="0"></a>
<strong><br>
Figure 9: The Completed Circuit</strong></p>
<p>The red wires carry the positive voltage from the power supply, which is connected to the top left of the circuit. The green wires are ground. Other coloured wires are used for signals. The Clock, Latch and Data signals are brought out to a connector which
 will fit a Digi-ME prototyping board.</p>
<h2>Selecting Lights</h2>
<p>Each bit in the value sent to the <b>displayByte</b> method and then into the shift register will be mapped to a particular chain of lights. The mapping of these is not particularly important, since you can use program constants to represent particular values.
 I wired the red signals to output pins 4 and 8. To light up just the red lights I used the value 0x88 which is the appropriate bit pattern. I then set up constants for all the other colors:</p>
<pre class="csharpcode"><span class="kwrd">const</span> <span class="kwrd">byte</span> GREEN = 0x11;
<span class="kwrd">const</span> <span class="kwrd">byte</span> BLUE = 0x22;
<span class="kwrd">const</span> <span class="kwrd">byte</span> YELLOW = 0x44;
<span class="kwrd">const</span> <span class="kwrd">byte</span> RED = 0x88;</pre>
<h2>Setting Up the Hardware</h2>
<p>The .NET Micro Framework provides a set of classes that can be used to represent the hardware in a system. The program uses instances of the
<b>OutputPort</b> class to represent the output pins. These are created in the method that sets up the hardware:</p>
<pre class="csharpcode"><span class="kwrd">const</span> Cpu.Pin clockPin = Cpu.Pin.GPIO_Pin0;
<span class="kwrd">const</span> Cpu.Pin dataPin = Cpu.Pin.GPIO_Pin1;
<span class="kwrd">const</span> Cpu.Pin latchPin = Cpu.Pin.GPIO_Pin2;

<span class="kwrd">static</span> OutputPort clockPort;
<span class="kwrd">static</span> OutputPort dataPort;
<span class="kwrd">static</span> OutputPort latchPort;

<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> setupOutputs()
{
    clockPort = <span class="kwrd">new</span> OutputPort(clockPin, <span class="kwrd">false</span>);
    dataPort = <span class="kwrd">new</span> OutputPort(dataPin, <span class="kwrd">false</span>);
    latchPort = <span class="kwrd">new</span> OutputPort(latchPin, <span class="kwrd">false</span>);
}</pre>
<p>In this version of the hardware I have connected pin 0 of the processor to the clock, pin 1 to the data and pin 2 to the latch. If you use different pins you can change the settings above.</p>
<h1>Software</h1>
<p>Now that we have working hardware we can consider how the software is to work. Note that this version of the program works correctly but lacks exception handlers that would make it truly robust. I've left these out to simplify the explanation. To make sense
 of this description you will need to have a copy of the program itself available for reference.</p>
<p>You can develop the code using Visual Studio 2008 Express edition, which you can download from
<a href="http://www.microsoft.com/express/">http://www.microsoft.com/express/</a>
</p>
<p>The software is written for the .NET Micro Framework 3.0 which you can download from
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9356ed6f-f1f0-43ef-b21a-4644dd089b4a&amp;displaylang=en">
http://www.microsoft.com/downloads/details.aspx?FamilyID=9356ed6f-f1f0-43ef-b21a-4644dd089b4a&amp;displaylang=en</a>
</p>
<h2>Reading the Blog</h2>
<p>The program reads the RSS feed from a blog and looks for the <b>&lt;pubDate&gt;</b> value. This contains the date when the feed was last updated. Whenever this date changes the lights must flash red for a few seconds before resuming a random display. Users of
 the full .NET Framework can use the <b>HTTPRequest</b> class to build a <b>GET</b> command to be sent to a server. Unfortunately the .NET Micro Framework does not support this, so we have to access the web feed using socket based communication. This part of
 the program is heavily based on the <b>SocketClient</b> example supplied with the .NET Micro Framework.</p>
<pre class="csharpcode"><span class="rem">// This method requests a page from the specified server.</span>
<span class="kwrd">private</span> <span class="kwrd">static</span> String GetWebPage(String server, <span class="kwrd">string</span> webPage)
{
    <span class="kwrd">const</span> Int32 c_httpPort = 80;
    <span class="kwrd">const</span> Int32 c_microsecondsPerSecond = 1000000;

    <span class="rem">// Create a socket connection to the specified server and port.</span>
    <span class="kwrd">using</span> (Socket serverSocket = ConnectSocket(server, c_httpPort))
    {
        <span class="rem">// Send request to the server.</span>
        String request = <span class="str">&quot;GET &quot;</span>&#43; webPage &#43; 
             <span class="str">&quot; HTTP/1.1\r\nHost: &quot;</span> &#43; server &#43; 
             <span class="str">&quot;\r\nConnection: Close\r\n\r\n&quot;</span>;
        Byte[] bytesToSend = Encoding.UTF8.GetBytes(request);
        serverSocket.Send(bytesToSend, bytesToSend.Length, 0);

        <span class="rem">// Allocate a buffer to receive HTML chunks</span>
        Byte[] buffer = <span class="kwrd">new</span> Byte[1024];

        <span class="rem">// 'page' refers to the HTML data as it is built up.</span>
        String page = String.Empty; 

        <span class="rem">// Wait up to 30 seconds for initial data </span>
        <span class="rem">// Will throw exception if connection closed</span>
        DateTime timeoutAt = DateTime.Now.AddSeconds(30);
        <span class="kwrd">while</span> (serverSocket.Available == 0 &amp;&amp; 
               DateTime.Now &lt; timeoutAt)
        {
            System.Threading.Thread.Sleep(100);
        }

        <span class="rem">// Poll for data until 30 second time out</span>
        <span class="rem">// Returns true for data and connection closed</span>
        <span class="kwrd">while</span> (serverSocket.Poll(30 * c_microsecondsPerSecond,
                                 SelectMode.SelectRead))
        {
            <span class="rem">// Zero all bytes in the re-usable buffer</span>
            Array.Clear(buffer, 0, buffer.Length);

            <span class="rem">// Read a buffer-sized HTML chunk</span>
            Int32 bytesRead = serverSocket.Receive(buffer);

            <span class="rem">// If 0 bytes in buffer, then connection is closed, </span>
            <span class="rem">// or we have timed out</span>
            <span class="kwrd">if</span> (bytesRead == 0)
                <span class="kwrd">break</span>;

            <span class="rem">// Append the chunk to the string</span>
            page &#43;= <span class="kwrd">new</span> String(Encoding.UTF8.GetChars(buffer));
        }

        <span class="kwrd">return</span> page;   <span class="rem">// Return the complete string</span>
    }
}</pre>
<p>This method is called to fetch the journal RSS feed from my blog:</p>
<pre class="csharpcode"><span class="kwrd">string</span> address = <span class="str">&quot;www.robmiles.com&quot;</span>;
<span class="kwrd">string</span> name = <span class="str">&quot;/journal/rss.xml&quot;</span>;

<span class="kwrd">string</span> html = GetWebPage(address, name);</pre>
<p>You can use it to download from any RSS feed or page on the web. It will throw an exception if the page cannot be read. This version of my program does not perform exception handling however.</p>
<h2>Getting the Published Date</h2>
<p>The date is held in the form:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">pubDate</span><span class="kwrd">&gt;</span>Wed, 05 Nov 2008 22:38:52 &#43;0000<span class="kwrd">&lt;/</span><span class="html">pubDate</span><span class="kwrd">&gt;</span></pre>
<p>It would be enough just to record this content and check for changes in the text, but I decided that I might want to use the date information in a later version of the program and so I created some small helper methods to read numbers from the input string
 and a larger method to read the publish date itself:</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">static</span> DateTime getRecentPubDate(<span class="kwrd">string</span> html, <span class="kwrd">string</span> startTag)
{
    <span class="kwrd">int</span> index = html.IndexOf(startTag) ;

    <span class="kwrd">if</span> (index &lt; 0) 
        <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">&quot;Missing tag &quot;</span> &#43; startTag);

    index &#43;= startTag.Length;

    <span class="rem">// spin past the name of the day</span>
    <span class="kwrd">while</span> (index &lt; html.Length &amp;&amp; html[index] != <span class="str">','</span>) index&#43;&#43;;
    <span class="kwrd">if</span> (index == html.Length) 
        <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">&quot;Short publish date&quot;</span>);

    <span class="kwrd">int</span> dayValue = getInt(html, <span class="kwrd">ref</span> index, <span class="str">' '</span>);

    <span class="kwrd">string</span> monthName = getString(html, <span class="kwrd">ref</span> index, <span class="str">' '</span>);
    <span class="kwrd">int</span> monthValue = getMonth(monthName);

    <span class="kwrd">int</span> yearValue = getInt(html, <span class="kwrd">ref</span> index, <span class="str">' '</span>);
    <span class="kwrd">int</span> hourValue = getInt(html, <span class="kwrd">ref</span> index, <span class="str">':'</span>);
    <span class="kwrd">int</span> minuteValue = getInt(html, <span class="kwrd">ref</span> index, <span class="str">':'</span>);
    <span class="kwrd">int</span> secondValue = getInt(html, <span class="kwrd">ref</span> index, <span class="str">' '</span>);

    <span class="kwrd">return</span> <span class="kwrd">new</span> DateTime(yearValue, monthValue, dayValue, 
                        hourValue, minuteValue, secondValue);
}</pre>
<p>The main body of the program uses this method to extract the date out of the RSS feed. When a new date is found it is time to update the lights.</p>
<h2>Lights and Threads</h2>
<p>My first version of the program flashed the lights for a while and then checked to see if a new blog post had been made. This worked OK, but the process of loading the RSS feed from the server and checking the dates can take a few seconds, which meant that
 the flashing lights would freeze every now and then. This did not look very good, and so I decided to use two threads instead. One is in charge of flashing the lights in a random pattern and the other loads the RSS feed from my blog and checks the date of
 the most recent publication. </p>
<p>Note that the threading I am using is exactly the same as threading in the full .NET Framework.
</p>
<h2>Thread Communication</h2>
<p>The two threads communicate by means of a single boolean variable which is set to true when the blog alert is to take place. The display thread reads this flag and flashes the lights red if it is time to alert.
</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> alert = <span class="kwrd">false</span>;

<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> flasher()
{
    setupOutputs();

    <span class="kwrd">while</span> (<span class="kwrd">true</span>)
    {
        randomDisplay(400, 10);
        <span class="kwrd">if</span> (alert)
        {
            alert = <span class="kwrd">false</span>;
            flashRed(600, 20);
        }
    }
}</pre>
<p>The methods <b>randomDisplay</b> and <b>flashRed</b> do exactly what you would expect. Each of them gets two numbers to control the lights. The first number gives the delay in milliseconds between flashes (a few hundred milliseconds giving best results).
 The second gives the number of times that the lights should be flashed before the method finishes.
<b>RandomDisplay</b> displays random colors, whereas <b>flashRed</b> is simply flashes the red lights. The
<b>alert</b> flag is cleared before the red lights are flashed so that the system will resume normal display after the alert.</p>
<p>The second thread in the system performs the blog download and date test behaviour. This all happens inside the
<b>Main</b> method:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main()
{
    flashThread = <span class="kwrd">new</span> System.Threading.Thread(flasher);

    flashThread.Start();

    <span class="kwrd">string</span> address = <span class="str">&quot;www.robmiles.com&quot;</span>;
    <span class="kwrd">string</span> name = <span class="str">&quot;/journal/rss.xml&quot;</span>;

    String html = GetWebPage(address, name);

    DateTime lastUpdate = getRecentPubDate(html, <span class="str">&quot;&lt;pubDate&gt;&quot;</span>);

    Debug.Print(<span class="str">&quot;Initial Update Value : &quot;</span> &#43; lastUpdate.ToString());

    <span class="kwrd">while</span> (<span class="kwrd">true</span>)
    {
        System.Threading.Thread.Sleep(10000);

        html = GetWebPage(address, name);

        DateTime blogUpdate = getRecentPubDate(html, <span class="str">&quot;&lt;pubDate&gt;&quot;</span>);

        <span class="kwrd">if</span> (!blogUpdate.Equals(lastUpdate))
        {
            Debug.Print(<span class="str">&quot;Updated at : &quot;</span> &#43; blogUpdate.ToString());
            lastUpdate = blogUpdate;
            alert = <span class="kwrd">true</span>;
        }
    }
}</pre>
<p>To reduce the load on the network the system only checks the blog feed every 10 seconds.</p>
<h1>Future Work</h1>
<p>The program itself works fine, but the error handling is not wonderful. Although some of the methods used throw exceptions these are not caught anywhere, causing the blog reading thread to terminate. This does not stop the lights flashing, but it does mean
 that there will be no more alerts. However, it is not too hard to create a version which contains proper error handling and even flashes the lights different colors to indicate the alarm conditions. I have created a version that flashes the lights yellow every
 now and then if the network connection fails. There is also considerable scope for reading other web based sources and changing the output accordingly. Feel free to do all these things and make sure that you have fun.</p>
<h2>Thanks</h2>
<p>Thanks go to Ian Mitchell of Ormston Technology (<a href="http://www.ormtec.co.uk/">http://www.ormtec.co.uk/</a>) for doing such a great job of hardware design and build.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:90ff2e0eefa3449089ad9e7600cda780">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Controlling-Your-Festive-Lights-with-the-NET-Micro-Framework</comments>
      <itunes:summary>





Author:
Rob Miles: 
www.robmiles.com 


Download:
Download


Software:
Visual Studio 2008 Express Edition or better,

.NET Micro Framework 3.0


Hardware:
Digi Connect-ME

GHI Electronics Embedded Master

Devices Solutions Tahoe II



Time Required:
3 hours


Cost:
30 dollars for lights plus the .NET Micro Framework device



The Micro Framework is one of the newest kids on the .NET block, but it does something really rather wonderful. It brings embedded development within the reach of any C# programmer. If you know C# and love Visual Studio, you can now get started building
 hardware and controlling it with your software. Moreover, it lets developers achieve one of their most cherished dreams, to control their festive lights using programs that they have written. This project shows you how to do just that and adds an extra magical
 feature, in that you can make all your festive lights flash red whenever I, Rob Miles, make a new post on that most famous of blogs,
www.robmiles.com.  
Actually, you can modify the code so that you can make your lights do most anything in response to an event that happens on the web. You could signal home that you are running late, send the weather forecast to your Christmas tree or explore any number of
 communication options. You might decide that this is so useful that you leave your decorations up all year round. 
If you just want to play with the .NET Micro Framework and get a feel for how easy it is to create software for tiny devices you don&#39;t actually need to use any extra hardware at all. The project comes with a complete emulation of the lights display so that
 you can run the whole thing on your computer and learn how hardware and software can be made to work together without burning your fingers with a soldering iron. 
However building the hardware will give you an understanding of how some simple electronic components can be controlled from C# and even how serial and parallel data transfer works. It is also great fun.</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Controlling-Your-Festive-Lights-with-the-NET-Micro-Framework</link>
      <pubDate>Fri, 28 Nov 2008 01:58:46 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Controlling-Your-Festive-Lights-with-the-NET-Micro-Framework</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9149635_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9149635_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Rob Miles</dc:creator>
      <itunes:author>Rob Miles</itunes:author>
      <slash:comments>6</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Controlling-Your-Festive-Lights-with-the-NET-Micro-Framework/RSS</wfw:commentRss>
      <category>.NET Micro Framework</category>
      <category>Hardware</category>
      <category>Robotics</category>
      <category>Home Automation</category>
      <category>Holiday</category>
      <category>.NET Microframework</category>
      <category>hardwarehacks</category>
    </item>
  <item>
      <title>Microsoft&#39;s Holiday Preview - Windows Vista Powered PC&#39;s and Accessories</title>
      <description><![CDATA[This Holiday season is certain to be merry considering all the great new products being offered to you from <a href="http://www.microsoft.com/hardware/">Microsoft Hardware</a>,&nbsp;<a href="http://www.microsoft.com/windows/windows-vista/default.aspx">Vista</a> powered machines and <a href="http://www.gamesforwindows.com/en-US/Pages/index.aspx">Games for Windows</a>. Check out some of the sexy new <a href="http://www.dell.com/laptops">Dell laptops</a>,&nbsp; <a href="http://www.microsoft.com/hardware/mouseandkeyboard/tracklanding.mspx">BlueTrack</a><a href="http://www.microsoft.com/hardware/mouseandkeyboard/tracklanding.mspx"> mice</a> and of course...some great games for Windows like&nbsp;<a href="http://fallout.bethsoft.com/">Fallout 3</a> and <a href="http://batman.lego.com/">Lego Batman</a>.<br><br>Also-make sure to check out what you can expect from <a href="http://www.on10.net/blogs/laura/Microsofts-Holiday-Preview-Windows-Mobile/">Windows Mobile</a>&nbsp;and <a href="http://www.on10.net/blogs/tina/Microsofts-Holiday-Preview-Xbox-360/">Xbox 360</a>.  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:5cb5c2f0eb3744b8ba459e0f01015982">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Vista-Powered-PCs-and-Accessories</comments>
      <itunes:summary>This Holiday season is certain to be merry considering all the great new products being offered to you from Microsoft Hardware,&amp;nbsp;Vista powered machines and Games for Windows. Check out some of the sexy new Dell laptops,&amp;nbsp; BlueTrack mice and of course...some great games for Windows like&amp;nbsp;Fallout 3 and Lego Batman.Also-make sure to check out what you can expect from Windows Mobile&amp;nbsp;and Xbox 360. </itunes:summary>
      <itunes:duration>236</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Vista-Powered-PCs-and-Accessories</link>
      <pubDate>Mon, 15 Sep 2008 14:36:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Vista-Powered-PCs-and-Accessories</guid>
      <media:thumbnail url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_large_on10.jpg" height="240" width="320"></media:thumbnail>
      <media:thumbnail url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_small_on10.jpg" height="64" width="85"></media:thumbnail>
      <media:group>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_2MB_on10.wmv" expression="full" duration="236" fileSize="70927019" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_on10.mp3" expression="full" duration="236" fileSize="1888676" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_on10.mp4" expression="full" duration="236" fileSize="13082399" type="video/mp4" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_on10.wma" expression="full" duration="236" fileSize="1921743" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_on10.wmv" expression="full" duration="236" fileSize="14670639" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_Zune_on10.wmv" expression="full" duration="236" fileSize="18711051" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="mms://mschnlnine.wmod.llnwd.net/a1809/d1/on10/8/9/4/3/VistaPower_s_on10.wmv" expression="full" duration="236" fileSize="196" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://mschnlnine.vo.llnwd.net/d1/on10/8/9/4/3/VistaPower_on10.wmv" length="14670639" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Laura Foy</dc:creator>
      <itunes:author>Laura Foy</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Vista-Powered-PCs-and-Accessories/RSS</wfw:commentRss>
      <category>Games</category>
      <category>Vista</category>
      <category>Windows</category>
      <category>Windows Vista</category>
      <category>Xbox 360</category>
      <category>Games for Windows</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Microsoft&#39;s Holiday Preview - Windows Mobile</title>
      <description><![CDATA[Call Santa because the Holidays are on their way - and call him from your <a href="http://www.microsoft.com/windowsmobile/en-us/default.mspx">Windows Mobile Phone</a>. In this episode of our Holiday Preview Guide we check out the sexy new phones coming your way like the <a href="http://www.htc.com/www/product.aspx?id=46278">HTC Diamond</a>, the <a href="http://www.htc.com/www/product.aspx?id=142">HTC Touch Dual</a>&nbsp;and the <a href="http://www.samsungmobileusa.com/blackjackII/">Samsung BlackJack II</a>. There's plenty of reason to celebrate and if you need more- take at episode 1 of our <a href="http://www.on10.net/blogs/tina/Microsofts-Holiday-Preview-Xbox-360/">Holiday Guide on the Xbox 360</a>. <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:670c151c2ad740dbb2aa9e0f01015493">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Mobile</comments>
      <itunes:summary>Call Santa because the Holidays are on their way - and call him from your Windows Mobile Phone. In this episode of our Holiday Preview Guide we check out the sexy new phones coming your way like the HTC Diamond, the HTC Touch Dual&amp;nbsp;and the Samsung BlackJack II. There&#39;s plenty of reason to celebrate and if you need more- take at episode 1 of our Holiday Guide on the Xbox 360.</itunes:summary>
      <itunes:duration>122</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Mobile</link>
      <pubDate>Fri, 12 Sep 2008 13:01:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Mobile</guid>
      <media:thumbnail url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_large_on10.jpg" height="240" width="320"></media:thumbnail>
      <media:thumbnail url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_small_on10.jpg" height="64" width="85"></media:thumbnail>
      <media:group>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_2MB_on10.wmv" expression="full" duration="122" fileSize="37654335" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_on10.mp3" expression="full" duration="122" fileSize="976689" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_on10.mp4" expression="full" duration="122" fileSize="6649158" type="video/mp4" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_on10.wma" expression="full" duration="122" fileSize="1002475" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_on10.wmv" expression="full" duration="122" fileSize="7790839" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_Zune_on10.wmv" expression="full" duration="122" fileSize="9702323" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="mms://mschnlnine.wmod.llnwd.net/a1809/d1/on10/3/0/5/3/2/HolidayMobile_s_on10.wmv" expression="full" duration="122" fileSize="206" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://mschnlnine.vo.llnwd.net/d1/on10/3/0/5/3/2/HolidayMobile_on10.wmv" length="7790839" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Laura Foy</dc:creator>
      <itunes:author>Laura Foy</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LauraFoy/Microsofts-Holiday-Preview-Windows-Mobile/RSS</wfw:commentRss>
      <category>Microsoft</category>
      <category>Mobile</category>
      <category>Windows</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Animated Musical Holiday Light Show - Version 2.0</title>
      <description><![CDATA[<table width="100%" border="0" cellspacing="0" cellpadding="1"><tbody><tr class="entry_overview"><td width="50">&nbsp;</td><td><span class="entry_description">Create an animated holiday light show for indoor or outdoor use using some <a href="http://www.phidgets.com/" target="_blank">Phidget Interface Kits</a>, extension cords, and .NET.</span></td></tr><tr><td colspan="2"><div class="entry_author"><a href="http://www.brianpeek.com/" target="_blank">Brian Peek</a></div><br><div class="entry_details"><strong>Difficulty: </strong><span class="entry_details_input">Intermediate</span></div><div class="entry_details"><strong>Time Required:</strong> <span class="entry_details_input">3-6 hours</span></div><div class="entry_details"><strong>Cost: </strong><span class="entry_details_input">$100-$200</span></div><div class="entry_details"><strong>Software: </strong><span class="entry_details_input"><a href="http://msdn.microsoft.com/express/" target="_blank">Visual Basic or Visual C# 2008 Express Editions</a>, <a href="http://www.phidgets.com/downloads.php?os_id=1" target="_blank">Phidgets .NET libraries</a></span></div><div class="entry_details"><strong>Hardware: </strong><span class="entry_details_input"><a href="http://www.trossenrobotics.com/store/p/3203-InterfaceKit-0-0-4.aspx" target="_blank">Phidget Interface Kit 0/0/4</a>, extension cords, wire nuts, spare wire</span></div><div class="entry_details"><strong>Download:&nbsp;</strong><a href="http://www.c4fbook.com/downloads/LightSequencer.zip" target="_blank">Download</a></div></td></tr></tbody></table><p>Welcome to version 2.0 of the software and article!&nbsp; I have rewritten the key points of this article to address the new features in the latest version of the software.&nbsp; Read on for a full explanation...</p><p><strong>New Features for 2.0</strong></p><ul><li>MIDI support <ul><li>Load a MIDI file and a sequence will be automatically created based on the data contained in the file.&nbsp; You can automatically create your own show with barely any effort at all! </li></ul></li><li>Playlists <ul><li>Load up several sequences and have them play in order to create a multi-song show! </li></ul></li><li>More accurate timing <ul><li>The timing algorithm used in the last version was very imprecise...it worked, but it wasn't perfect.&nbsp; The new version uses a method which gives millisecond precision timing </li></ul></li><li>Cut/Copy/Paste <ul><li>One can now cut/copy/paste cells on the grid...makes it easy to repeat chunks of sequences without having to tap out the rhythm by hand over and over again </li></ul></li><li>Edit existing sequences <ul><li>After loading a sequence created by someone else (or yourself), you can now re-assign Phidget boards, serial numbers, output ports, etc. to get them to run on your setup. </li></ul></li></ul><p>Note that any sequences created with the old version will continue to play just fine, but editing them could be troublesome due to the new timing method.</p><p>And now back to the article with updates.&nbsp; The hardware section remains the same, but the <a href="http://blogs.msdn.com/controlpanel/blogs/posteditor.aspx?SelectedNavItem=Posts&amp;sectionid=4539&amp;postid=1230660#software">software</a> discussion below is updated with new information.</p><hr><p>I'm sure by now everyone with a computer has seen the videos of holiday light shows timed to holiday music such as <a href="http://www.youtube.com/watch?v=nD8_7c36yfw" target="_blank">this one</a>.&nbsp; For this holiday season, I decided to create my own indoor show using some off-the-shelf components and .NET.</p><h3>&nbsp;</h3><p>&nbsp;</p><p><strong>WARNING:&nbsp; The hardware portion of this project uses standard 120V AC current.&nbsp; As you are likely aware, this is enough voltage to seriously hurt or kill you.&nbsp; Please be careful and follow the instructions closely.</strong></p><h3>What You Will Need</h3><ul><li><a href="http://www.trossenrobotics.com/store/p/3203-InterfaceKit-0-0-4.aspx">Phidget Interface Kit</a> 0/0/4 – a USB-controlled board with 4 relays.&nbsp; I used 2 kits for a total of 8 channels.&nbsp; Any number can be used. </li><li>5 6' (or longer/shorter for your needs) indoor or outdoor 2-prong extension cords for each Phidget board used.&nbsp; I was able to find these at the local home improvement store for about $1 each.&nbsp; If you will be creating an outdoor show, be sure to purchase extension cords that are meant for outdoor use. </li></ul><blockquote><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/extension_cord14.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/extension_cord_thumb12.jpg" alt="" width="240" height="180" border="0"></a></p></blockquote><ul><li>Some 14-16 gauge wire.&nbsp; If in doubt, simply buy one additional extension cord to use for the additional wire. </li><li>2 wire nuts that can handle the wire gauge selected above for each Phidget board used. </li></ul><blockquote><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wirenuts1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wirenuts.jpg" alt="" width="240" height="180" border="0"></a>&nbsp;</p></blockquote><ul><li>A project box large enough to hold one or many Phidget boards and associated wiring.&nbsp; I chose a 7&quot;L x 5&quot;W x 3&quot;H enclosure from Radio Shack which provides ample room to hold 2 Phidget Interface Kits and wiring. </li><li>Some holiday lights </li><li>External speakers (or possibly an FM transmitter for an outdoor show) </li><li><a href="http://www.phidgets.com/downloads.php?os_id=1" target="_blank">Phidgets .NET libraries</a> </li><li><a href="http://msdn.com/express/">Microsoft Visual Basic or Visual C# Express Editions</a> </li></ul><h3>Building the Hardware</h3><p>The hardware we are going to build will allow for one Phidget board to be plugged into a single AC outlet and provide 4 output outlets that can be switched off and on by the Phidget board's relays.&nbsp; By building two of these and placing them in a project box, I have a neat and tidy control box with 2 USB inputs, 2 AC male plugs for the wall, and 8 AC female plugs for my lights.&nbsp; The following description will be for building a single unit.</p><p>Let's start by preparing the extension cords.&nbsp; Cut the female end off of one extension cord.&nbsp; Split the cord up the center and strip the insulation off each of the wires to expose the ends.&nbsp; Twist the ends with your fingers to create a neat, twisted wire as shown:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/male_end1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/male_end.jpg" alt="" width="240" height="180" border="0"></a></p><p>Next, take the remaining four extension cords and cut the male ends off each.&nbsp; As before, split the cord up the center a small bit, strip off some insulation, and twist the exposed ends as shown:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/female_end1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/female_end.jpg" alt="" width="240" height="180" border="0"></a></p><p>Now, cut 4 equal lengths of your 14-16 gauge wire.&nbsp; These should be no longer than 2-4 inches in length.&nbsp; Strip some insulation off each end and twist up any loose wires.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wire1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wire.jpg" alt="" width="240" height="180" border="0"></a></p><p>For the next part, you will need to pay close attention.&nbsp; Each extension cord <strong>should</strong> have two different types of insulation around the wires.&nbsp; One side should have a ribbed edge, and one side should have a smooth edge shown below:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/smooth5.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/smooth_thumb3.jpg" alt="" width="450" height="337" border="0"></a> <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/ribbed2.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/ribbed_thumb.jpg" alt="" width="450" height="337" border="0"></a></p><p>The ribbed side should be in line with the &quot;fat&quot; prong/receptacle (the neutral side) and the smooth side should be in line with the smaller prong/receptacle (the active/&quot;hot&quot; side).&nbsp; It is important that the next steps be followed carefully, noting which wires I am referring to.&nbsp; Using the wrong wire can lead to a short, blown fuses, kicked circuit breakers, or even worse things.</p><p>Take the 4 short wires you cut earlier and twist them all together along with the ribbed/neutral wire from the extension cord with the male end still attached.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/twisted_wires1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/twisted_wires.jpg" alt="" width="240" height="180" border="0"></a></p><p>Twist a wire nut over the exposed ends to keep them together and covered.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wires_nut1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/wires_nut.jpg" alt="" width="240" height="180" border="0"></a></p><p>Next, twist together the smooth/&quot;hot&quot; wire from the four extension cords with the female ends still attached along with the smooth/&quot;hot&quot; wire from the extension cord with the male end attached (i.e. the other wire from the male cord used above).</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/cords_twisted1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/cords_twisted.jpg" alt="" width="240" height="180" border="0"></a></p><p>Again, twist on a wire nut to keep things covered and safe.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/cords_nut1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/cords_nut.jpg" alt="" width="240" height="180" border="0"></a></p><p>You should now be left with the opposite ends of the 4 cut wires exposed, and the 4 ribbed/neutral wires of the female extension exposed.&nbsp; These will all be put into the screw terminals of the Phidget Interface Kit.</p><p>The Phidget Interface Kit board has 4 groups of screw terminals.&nbsp; Each group contains 3 items:&nbsp; NO, XC, and NC, where X is the relay number in question.&nbsp; These stand for &quot;Normally Open&quot;, &quot;Common&quot;, and &quot;Normally Closed&quot;.&nbsp; For this project, the lights should normally be off and switched on via the software, so the NO (Normally Open) and XC (Common) ports will be used.</p><p>Place one wire from each exposed bundle into each NO and XC port.&nbsp; Note that it does not matter which wire you plug into which terminal of each group, just that each group has only one short wire and only one extension cord wire.</p><p>In the end, there will be one each of the 4 short wires in each group on the board, and one each of the extension cord wires in each group on the board as pictured:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/phidget_done1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/phidget_done.jpg" alt="" width="240" height="180" border="0"></a></p><p>Below is a very simple schematic of the wiring of a single board:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/Schematic8.png"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/Schematic_thumb4.png" alt="" width="240" height="124" border="0"></a></p><p>I decided to keep things neat and tidy and mount the Phidget boards into a project box.&nbsp; Since I have 2 boards to manage, I placed both inside a single, large box.&nbsp; I drilled holes in the short sides to expose the boards' USB ports.&nbsp; I then notched out some spaces on the top edge and lid for the extension cords to pass through.&nbsp; I mounted the boards inside the box with some carefully placed two-sided foam tape.</p><p>The finished product can be seen below:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/internals1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/internals.jpg" alt="" width="240" height="180" border="0"></a>&nbsp;<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/finished1.jpg"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/finished.jpg" alt="" width="240" height="180" border="0"></a></p><p>And that's it!&nbsp; If this box will be placed outside, take the time to properly weatherproof the box so the elements cannot damage anything inside.</p><h3>A Word on Amperages</h3><p>Your individual light strings will be plugged into each extension cord outlet.&nbsp; An average strand of mini-lights draws about .3 amps. An average string of larger bulbs will draw 1-2 amps.&nbsp; The relays on the Phidget board are rated at 10 amps.&nbsp; Additionally, a standard house circuit will allow up to 15-20 amps before overloading.&nbsp; Check the circuit breaker in your home on which the outlet you'll be using lives for the allowed amperage.&nbsp; Also, keep in mind that any other devices that are plugged into that circuit elsewhere in the house will be drawing power, so you may not be able to draw a full 15 amps from it.&nbsp; So, be sure to not draw more than 10A per channel, nor more than 15-20A in total, <strong>including</strong> all additional devices plugged into that circuit.&nbsp; Keep this in mind as you string your lights together on each channel.</p><p><a title="software" name="software"></a></p><h3>Writing the Software</h3><p>Ensure the <a href="http://www.phidgets.com" target="_blank">Phidgets libraries for .NET</a> are installed on the development machine.&nbsp; To compile the source code, <a href="http://msdn.microsoft.com/express/" target="_blank">Visual Basic and/or Visual C# Express 2005</a> will also be need to be installed and working.</p><p>The <strong>Light Sequencer</strong> application uses a grid-style interface to show the list of channels and when each channel is switched on and off.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/image.png"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/image_thumb.png" alt="image" width="454" height="339" border="0"></a></p><p>Squares can be toggled on or off by highlighting them, right-clicking with the mouse and selecting On or Off from the context menu.&nbsp; They can also be toggled by pressing the O (for on) or F (for off) keys on the keyboard.</p><p>Additionally, sequences can be &quot;recorded&quot; by pressing the Record button in the toolbar.&nbsp; This will start the music and allow the user to tap out the rhythm for each channel by pressing the number key on the keyboard corresponding to the channel.</p><p>Sequences can be saved at any time and reloaded for editing or play with the Phidgets devices connected.</p><p>When I first started the software for this project, the first problem I ran into was the fact that the <strong>DataGridView</strong> control does no support multiple headers.&nbsp; As is shown in the screenshot above, the grid is broken down into seconds and then milliseconds.&nbsp; For display purposes. it is easier to break the header down into two segments, one showing the labeled second markers, and one showing the subdivisions per second.</p><p>To accomplish this, I created two DataGridViews:&nbsp; one for the header, which contains no data and is only as tall as the header row, and one for the sub-header and the data below it.&nbsp; This works great except for scrolling.&nbsp; To accomplish this, I simply listen for the <strong>Scroll</strong> event on the main grid and apply the scrolling offset to the header grid:</p><p><strong>Visual C#</strong></p><div><pre><span>private</span> <span>void</span> dgvMain_Scroll(<span>object</span> sender, ScrollEventArgs e)<br>{<br>    dgvHeader.HorizontalScrollingOffset = e.NewValue;<br>}</pre></div><p><strong>Visual Basic</strong></p><div><pre><span>Private</span> <span>Sub</span> dgvMain_Scroll(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> ScrollEventArgs) <span>Handles</span> dgvMain.Scroll<br>    dgvHeader.HorizontalScrollingOffset = e.NewValue<br><span>End</span> Sub</pre></div><p>Additionally, I ran into some performance issues drawing the grid.&nbsp; At first, drawing a grid with so many columns was quite slow.&nbsp; By setting the grid's <strong>Visible</strong> property to false before adding the rows and columns and then returning the <strong>Visible</strong> property to true, the grid now draws quite quickly.</p><p>The next issue tackled was starting and stopping a music file.&nbsp; In version 2, the software supports sampled music (MP3, WAV, etc.) as well as MIDI files.&nbsp; As I was attempting to write a MIDI file parser and player (so I could have access to the internal data for auto-generating a sequence) I found a fantastic MIDI library written by Leslie Sanford.&nbsp; This library is used by the Light Sequencer application.</p><p>With two playback libraries in place, I created an interface which contains Start, Stop, Load, etc. methods so that the front-end could use any playback engine interchangeably.&nbsp; The MCIPlayback engine uses standard MCI commands for playing sampled music.&nbsp; Commands are executed by passing them to the <strong>mciSendString</strong> function exported by winmm.dll.&nbsp; In order to use this function from .NET, we must import the method and setup its signature as follows:</p><p><strong>Visual C#</strong></p><div><pre>[DllImport(<span>&quot;winmm.dll&quot;</span>)]<br><span>static</span> <span>extern</span> Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);</pre></div><p><strong>Visual Basic</strong></p><div><pre><span>Declare</span> <span>Function</span> mciSendString <span>Lib</span> <span>&quot;winmm.dll&quot;</span> <span>Alias</span> <span>&quot;mciSendStringA&quot;</span> (<span>ByVal</span> command <span>As</span> <span>String</span>, _<br>   <span>ByVal</span> buffer <span>As</span> StringBuilder, <span>ByVal</span> bufferSize <span>As</span> Int32, _<br>   <span>ByVal</span> hwndCallback <span>As</span> IntPtr) <span>As</span> Int32</pre></div><p>To open a music file, the <strong>open</strong> command is used as follows:</p><p>open &quot;&lt;path to file&gt;&quot; type mpegvideo alias MediaFile</p><p>This opens the file and creates an alias named MediaFile which can be used to refer to the file for all future commands.&nbsp; Send the above command using the <strong>mciSendString</strong> method would look as follows:</p><p><strong>Visual C#</strong></p><div><pre><span>string</span> cmd = <span>&quot;open \&quot;&quot;</span> &#43; _musicFile &#43; <span>&quot;\&quot; type mpegvideo alias MediaFile&quot;</span>;<br>mciSendString(cmd, <span>null</span>, 0, IntPtr.Zero);</pre></div><p><strong>Visual Basic</strong></p><div><pre><span>Dim</span> cmd <span>As</span> <span>String</span> = <span>&quot;open &quot;</span><span>&quot;&quot;</span> &#43; file &#43; <span>&quot;&quot;</span><span>&quot; type mpegvideo alias MediaFile&quot;</span><br>mciSendString(cmd, <span>Nothing</span>, 0, IntPtr.Zero)</pre></div><p>The remaining commands we will need are:</p><ul><li>play MediaFile from 0 -- Play loaded file from beginning </li><li>stop MediaFile -- Stop playing current file </li><li>close MediaFile -- Close the file </li></ul><p>Next, the Phidget boards behavior needed to be implemented.&nbsp; Talking to the Phidget board is very easy.&nbsp; After creating an instance of the <strong>InterfaceKit</strong> object, a specific device can be opened by calling the <strong>open</strong> method, passing in the serial number of the device to be opened.</p><p>The serial numbers for each attached Phidget device can be determined by creating an instance of the <strong>Phidgets.Manager</strong> class, setting up the <strong>Attach</strong> event handler, and listening for the attach events as follows:</p><p><strong>Visual C#</strong></p><div><pre>...<br>Phidgets.Manager phidgetsManager = <span>new</span> Phidgets.Manager();<br>phidgetsManager.Attach &#43;= <span>new</span> AttachEventHandler(phidgetsManager_Attach);<br>phidgetsManager.open();<br>...<br><br><span>void</span> phidgetsManager_Attach(<span>object</span> sender, AttachEventArgs e)<br>{<br>    Debug.WriteLine(e.Device.Name &#43; <span>&quot; - &quot;</span> &#43; e.Device.SerialNumber)<br>}</pre></div><p><strong>Visual Basic</strong></p><div><pre>...<br><span>Dim</span> phidgetsManager <span>as</span> <span>New</span> Phidgets.Manager<br><span>AddHandler</span> phidgetsManager.Attach, <span>AddressOf</span> <span>Me</span>.phidgetsManager_Attach<br>phidgetsManager.open()<br>...<br><br><span>Private</span> <span>Sub</span> phidgetsManager_Attach(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> AttachEventArgs)<br>    Debug.WriteLine(e.Device.Name &amp; <span>&quot; - &quot;</span> &amp; e.device.SerialNumber)<br><span>End</span> Sub</pre></div><p>Setting the relay state is as easy as indexing into the <strong>outputs </strong>array of the <strong>InterfaceKit</strong> object and setting the indexed output to <strong>true </strong>or <strong>false</strong>.</p><p>In code, all of this would look like:</p><p><strong>Visual C#</strong></p><div><pre>InterfaceKit ik = <span>new</span> InterfaceKit();<br>ik.open(1234);<br>ik.outputs[0] = <span>true</span>;</pre></div><p><strong>Visual Basic</strong></p><div><pre><span>Dim</span> ik <span>as</span> <span>New</span> InterfaceKit<br>ik.open(1234)<br>ik.outputs(0) = True</pre></div><p>In order to maintain precise timing, the <strong>Stopwatch</strong> class from the<strong> System.Diagnostics</strong> namespace is used.&nbsp; This internally uses the <strong>QueryPerformanceCounter</strong> Win32 API method to give extremely precise time values.</p><p>When it is time to playback a sequence, a thread is started which starts the music using the appropriate playback engine, and then sits in a loop, waiting for the number of milliseconds to pass specified in the sequence (50ms as default).&nbsp; When that amount of time has elapsed, we send the channel states of the current tick to the relays connected.</p><p>Recording a sequence with the keyboard works in a similar fashion.&nbsp; A thread is started and the music is played.&nbsp; While the music is playing, <strong>KeyDown</strong> and <strong>KeyUp</strong> events are listened for.&nbsp; After translating the <strong>KeyCode</strong> of the pressed key to the channel number, an internal array of which keys are &quot;on and off&quot; are maintained.&nbsp; When the number of milliseconds elapsed hits the appropriate mark, every channel is updated with the current value of that array.&nbsp; That is, which keys are up and down.</p><p>When the user stops playback, or the song ends, the channel data is returned to the main form and displayed in the main grid.</p><p>If a MIDI file is selected, sequence data is automatically generated based on the MIDI data.&nbsp; A MIDI file contains a series of tracks or channels with a series of commands.&nbsp; These commands tell the MIDI hardware what note to turn on, when, and for how long (among other things).&nbsp; When the MIDI file is loaded, every command from every channel is enumerated and its time values are converted into milliseconds.&nbsp; Once all the commands are gathered and organized, they are placed into this application's channel structure and displayed on the grid.&nbsp; This allows the lights to flash in precise time to the MIDI file being played.</p><p><strong>Using the Software</strong></p><p>Ensure that the Phidget devices you will be using are attached to the PC.&nbsp; Start by creating a new sequence from the <strong>File</strong> menu or by clicking the <strong>New Sequence</strong> button.&nbsp; In the dialog that appears, locate a music file to play back and enter the length of time that the sequence should run.&nbsp; Be sure to note which Phidget devices are attached and which channels they map to on the grid.&nbsp; Click <strong>OK</strong> when complete.</p><p>The screen will redraw and present the grid interface for the length of time specified.&nbsp; At this point, cells can be turned on and off by highlighting a cell and right-clicking, or by pressing the &quot;O&quot; key to turn the cell On, and the &quot;F&quot; key to turn the cell off.&nbsp; Multiple cells can be selected and changed at once.</p><p>To use the recording interface, click the <strong>Record Sequence</strong> button or choose <strong>Record Sequence</strong> from the <strong>Sequence</strong> menu.&nbsp; Be sure to select the correct choice of &quot;Overwrite channel data&quot; or &quot;Append channel data.&quot;&nbsp; As you record additional channels, you will almost always want to append and not overwrite.</p><p>Click the start button and a brief countdown will begin.&nbsp; When the countdown reaches 0, the music will begin.&nbsp; A channel can be recorded by pressing the keyboard key of the channel number.&nbsp; For example, to tap out the rhythm of channel 1, press the 1 key at the appropriate times.</p><p>When complete, press the Escape key, or click the Stop button.&nbsp; When the Record window is closed, the main grid will be updated with the sequence recorded.</p><p>Creating a sequence is certainly a time consuming task since each channel needs to be recorded.&nbsp; While the rhythm interface allows one to record many channels simultaneously, I think it would be impossible for anyone to type out an entire sequence for all channels in one go.&nbsp; In my opinion, it is easiest to record one or two channels at a time and append the data as you go.&nbsp; In the end, you can use the grid interface to tweak the values and clean up any mistakes.</p><p>The sequence can be played back at any time. Simply press the <strong>Play</strong> button and watch your holiday lights play back to the timing you created.&nbsp; Press the <strong>Stop</strong> button to end the current playback.</p><p>Sequences can be saved at any time by selecting <strong>Save</strong> from the file menu.</p><p>To test the channels by hand, select &quot;Test Channels&quot; from the &quot;Tools&quot; menu.&nbsp; As with the recording screen, press the number keys associated with the channel to turn on or off to test that channel.</p><p>I found it was much easier to also have the lights plugged into the appropriate channels as I created my sequence.&nbsp; That way I could see the results of my recordings immediately.</p><p>To create a playlist of many sequences, select <strong>New Playlist</strong> from the <strong>File</strong> menu.&nbsp; Add your existing sequence files, order them as you wish, and save the playlist.&nbsp; From this screen you can also play the playlist, set it up to repeat, advance tracks, etc.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/image_3.png"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1230660/image_thumb_3.png" alt="image" width="454" height="379" border="0"></a></p><p>To edit data on an existing sequence (Phidget serial numbers, mapped MIDI channels, etc.) select <strong>Edit Sequence Properties</strong> from the <strong>Sequence</strong> menu.&nbsp; This will display the <strong>New Sequence</strong> dialog box and allow you to edit the existing setup.</p><h3>Setting It All Up</h3><p>So now that you have hardware, music and an animated sequence, it's time to hook it all up!&nbsp; If you are doing an indoor show, a set of external speakers should be more than ample for playing the music for your light show.&nbsp; For an outdoor show, you may wish to purchase an FM transmitter to output the music over a very low-powered FM frequency so that visitors can listen to the music on their car radios.&nbsp; I personally have not gone this route, however you can find a variety of FM transmitters for sale around the 'net.&nbsp; In a quick search, I found <a href="http://www.ramseyelectronics.com/site/default.asp?search=fm&#43;transmitter&amp;page=search&amp;x=0&amp;y=0" target="_blank">Ramsey Electronics</a> which sells a variety of FM transmission hardware that is more than appropriate depending on your budget.&nbsp; I am certain there are plenty of other devices that fit the bill as well.</p><p>To fire up the show, just plug in your USB Phidget devices, plug the lights into the appropriate channels, load the Light Sequencer application, and press the Play button!</p><h3>Conclusion</h3><p>And there we have it!&nbsp; Holiday lights timed to your favorite holiday song.&nbsp; Take your time in creating a sequence and show us what you've created!</p><p>I plan on maintaining and updating this article as we get closer and closer to the holidays, so please check back often for updates.&nbsp; I will note updates at the top of the article.&nbsp; Additionally, please send me any and all feedback, bug reports, feature requests, or anything else you have to say!&nbsp; You can find my contact info in the readme.txt file located in the source code download linked above, or visit <a href="http://www.brianpeek.com/" target="_blank">my website</a>.</p><h3>Thanks</h3><p>Special thanks to Michelle Leavitt for help setting up lights and sequence ideas, and my dad for advice on wiring up the relays.</p><p>Thanks to <a href="http://www.lesliesanford.com/" target="_blank">Leslie Sanford</a> for the incredible <a href="http://www.lesliesanford.com/Programming/MIDIToolkit.shtml" target="_blank">MIDI Toolkit</a>.</p><p>And, a big thank you to the beta testers for version 2: Allen Leno, Steve Runion, Steve Trueman, Corey Emmert.</p><h3>Bio</h3><p>Brian is a Microsoft C# MVP and a recognized .NET expert with over 6 years experience developing .NET solutions, and over 9 years of professional experience architecting and developing solutions using Microsoft technologies and platforms, although he has been &quot;coding for fun&quot; for as long as he can remember.&nbsp; Outside the world of .NET and business applications, Brian enjoys developing both hardware and software projects in the areas of gaming, robotics, and whatever else strikes his fancy for the next ten minutes. He rarely passes up an opportunity to dive into a C/C&#43;&#43; or assembly language project.&nbsp; You can reach Brian via his blog at <a href="http://www.brianpeek.com/">http://www.brianpeek.com/</a>.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:0f8ca45942b447feaff19e7600d0c258">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Animated-Musical-Holiday-Light-Show-Version-20</comments>
      <itunes:summary>&amp;nbsp;Create an animated holiday light show for indoor or outdoor use using some Phidget Interface Kits, extension cords, and .NET.Brian PeekDifficulty: IntermediateTime Required: 3-6 hoursCost: $100-$200Software: Visual Basic or Visual C# 2008 Express Editions, Phidgets .NET librariesHardware: Phidget Interface Kit 0/0/4, extension cords, wire nuts, spare wireDownload:&amp;nbsp;DownloadWelcome to version 2.0 of the software and article!&amp;nbsp; I have rewritten the key points of this article to address the new features in the latest version of the software.&amp;nbsp; Read on for a full explanation... New Features for 2.0 MIDI support Load a MIDI file and a sequence will be automatically created based on the data contained in the file.&amp;nbsp; You can automatically create your own show with barely any effort at all! Playlists Load up several sequences and have them play in order to create a multi-song show! More accurate timing The timing algorithm used in the last version was very imprecise...it worked, but it wasn&#39;t perfect.&amp;nbsp; The new version uses a method which gives millisecond precision timing Cut/Copy/Paste One can now cut/copy/paste cells on the grid...makes it easy to repeat chunks of sequences without having to tap out the rhythm by hand over and over again Edit existing sequences After loading a sequence created by someone else (or yourself), you can now re-assign Phidget boards, serial numbers, output ports, etc. to get them to run on your setup. Note that any sequences created with the old version will continue to play just fine, but editing them could be troublesome due to the new timing method. And now back to the article with updates.&amp;nbsp; The hardware section remains the same, but the software discussion below is updated with new information. I&#39;m sure by now everyone with a computer has seen the videos of holiday light shows timed to holiday music such as this one.&amp;nbsp; For this holiday season, I decided to create my own indoor show using some off-the-shel</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Animated-Musical-Holiday-Light-Show-Version-20</link>
      <pubDate>Sun, 23 Dec 2007 19:25:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Animated-Musical-Holiday-Light-Show-Version-20</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1230660_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1230660_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>26</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Animated-Musical-Holiday-Light-Show-Version-20/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>Windows</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Winter Visualization for Windows Media Player in C++</title>
      <description><![CDATA[
<p class="head"><img height="50" width="50" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/small.png" align="left" alt="small" border="0"> Ever wondered what's behind a visualization? This is your opportunity to learn something
 new because there are only a couple of Windows Media Player Visualizations that deliver source code. You'll learn to build a new visualization with Visual C&#43;&#43; 2005 Express (you won't even require a Standard Edition)! Winter is here... Snow is here... we'll
 render <a target="_blank" href="http://mathworld.wolfram.com/KochSnowflake.html">
Koch Snowflake Fractals</a> that depend on the waveform of the playing song with the Windows Graphics Device Interface. This article will also change the way you ever looked at a visualization. Enjoy!</p>
<p>Paul-Valentin Borza - <a href="http://www.borza.ro">http://www.borza.ro</a> </p>
<blockquote>
<p><strong>Difficulty:</strong> Intermediate<br>
<strong>Cost:</strong> Free<br>
<strong>Time required:</strong> 1-3 hours<br>
<strong>Software:</strong> <a target="_blank" href="http://www.microsoft.com/express/2005/download/default.aspx">
Visual C&#43;&#43; 2005 Express</a>, <a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?familyid=484269E2-3B89-47E3-8EB7-1F2BE6D7123A&amp;displaylang=en">
Windows Server 2003 R2 Platform SDK</a>, <a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4377F86D-C913-4B5C-B87E-EF72E5B4E065&amp;displaylang=en">
Windows Software Development Kit for Windows Vista</a><br>
<strong>Hardware:</strong> None<br>
<strong>Download Source: </strong><a target="_blank" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/wintervisualization.zip" title="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/wintervisualization.zip">Winter Visualization Source Code</a>
</p>
</blockquote>
<h3>How do we build a visualization?</h3>
<p>Please install (don't change the default installation directory):</p>
<ul>
<li><a target="_blank" href="http://www.microsoft.com/express/2005/download/default.aspx">Visual C&#43;&#43; 2005 Express</a>
</li><li><a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?familyid=484269E2-3B89-47E3-8EB7-1F2BE6D7123A&amp;displaylang=en">Windows Server 2003 R2 Platform SDK</a> (contains MFC and ATL headers and libraries)
</li><li><a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4377F86D-C913-4B5C-B87E-EF72E5B4E065&amp;displaylang=en">Windows Software Development Kit for Windows Vista</a> (contains Windows Media Player 11 SDK)
</li></ul>
<p>We need to make Visual C&#43;&#43; 2005 Express work with visualizations:</p>
<ol>
<li>Navigate to '<em>C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\Multimedia\WMP_11\Wizards\VSNET</em>';
</li><li>Copy '<em>wmpwiz2005.vsz</em>', '<em>wmpwiz.vsdir</em>' and '<em>wmpwiz.ico</em>';
</li><li>Navigate to '<em>C:\Program Files\Microsoft Visual Studio 8\VC\Express\VCProjects</em>';
</li><li>Paste '<em>wmpwiz2005.vsz</em>', '<em>wmpwiz.vsdir</em>' and '<em>wmpwiz.ico</em>';
</li><li>Rename '<em>wmpwiz2005.vsz</em>' to '<em>wmpwiz.vsz</em>' (you're in '<em>C:\Program Files\Microsoft Visual Studio 8\VC\Express\VCProjects</em>');
</li><li>Edit '<em>wmpwiz.vsz</em>' using <em>Notepad</em> and change the line '<em>Param=&quot;ABSOLUTE_PATH = &lt;path to wmpwiz directory goes here&gt;&quot;</em>' with '<em>Param=&quot;ABSOLUTE_PATH = C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\Multimedia\WMP_11\Wizards\VSNET&quot;</em>';
</li><li>The <em>Windows Media Player Plug-in Wizard</em> is now installed. Launch <em>
Visual C&#43;&#43; 2005 Express</em>.
<ol>
<li>Click on '<em>File</em>' &gt; '<em>New</em>' &gt; '<em>Project...</em>'; </li><li>In '<em>Project types:</em>' select '<em>Visual C&#43;&#43;</em>'; </li><li>In '<em>Templates:</em>' select '<em>Windows Media Player Plug-in Wizard</em>';
</li><li>Change '<em>Name:</em>' from '<em>wmpplugin1</em>' to '<em>MyWinterVisualization</em>' and click '<em>OK</em>';
</li><li>The <em>Windows Media Player Plug-in Wizard</em> appears; </li><li>On the '<em>Welcome to the Windows Media Player Plug-in Wizard</em>' select '<em>Visualization</em>' and click '<em>Next</em>';
</li><li>On the '<em>Visualization Plug-in</em>' change '<em>Friendly Name:</em>' from '<em>MyWinterVisualization Plugin</em>' to '<em>Coding4Fun Winter Visualization</em>' and '<em>Description:</em>' from '<em>Description of MyWinterVisualization plugin</em>' to
 '<em>Description of Coding4Fun Winter Visualization</em>'; don't check '<em>Property Page</em>' or '<em>Listen to events</em>';
</li><li>Click '<em>Next</em>'. The wizard will create a new visualization for you; you're almost done!
</li></ol>
</li></ol>
<p>You'll notice that the created project won't compile because the '<em>atlbase.h</em>', '<em>wmpplug.h</em>', '<em>effects.h</em>' and '<em>winres.h</em>' can't be opened; to overcome:</p>
<ol>
<li>Click on '<em>Project</em>' &gt; '<em>Properties</em>'; </li><li>Expand '<em>Configuration Properties</em>' &gt; '<em>C/C&#43;&#43;</em>' &gt; '<em>General</em>';
</li><li>In '<em>Additional Include Directories</em>' add '<em>&quot;C:\Program Files\Microsoft SDKs\Windows\v6.0\Include&quot;</em>' and click '<em>OK</em>';
</li><li>Expand '<em>Configuration Properties</em>' &gt; '<em>Linker</em>' &gt; '<em>Input</em>';
</li><li>In '<em>Additional Dependencies</em>' add '<em>msimg32.lib</em>' (we'll need this to give smoothness to the visualization);
</li><li>Click on '<em>Tools</em>' &gt; '<em>Options...</em>'; </li><li>Expand '<em>Projects and Solutions</em>' &gt; '<em>VC&#43;&#43; Directories</em>'; </li><li>In '<em>Platform:</em>' select '<em>Win32</em>' and in '<em>Show directories for:</em>' select '<em>Include files</em>';
</li><li>Add '<em>&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\atl&quot;</em>' and '<em>&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\mfc&quot;</em>';
</li></ol>
<p>One last trick... Edit '<em>C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\atl\atlbase.h</em>' using
<em>Notepad</em>. Find the following text (begins on line <em>287</em>): </p>
<div>
<p><span>&nbsp; 287</span> PVOID <span>__stdcall</span> __AllocStdCallThunk(VOID);</p>
<p><span>&nbsp; 288</span> VOID&nbsp; <span>__stdcall</span> __FreeStdCallThunk(PVOID);</p>
<p><span>&nbsp; 289</span>&nbsp;</p>
<p><span>&nbsp; 290</span>&nbsp;<span>#define</span> AllocStdCallThunk() __AllocStdCallThunk()</p>
<p><span>&nbsp; 291</span>&nbsp;<span>#define</span> FreeStdCallThunk(p) __FreeStdCallThunk(p)</p>
<p><span>&nbsp; 292</span>&nbsp;</p>
<p><span>&nbsp; 293</span>&nbsp;<span>#pragma</span> <span>comment</span>(<span>lib</span>,
<span>&quot;atlthunk.lib&quot;</span>)</p>
</div>
<p>Comment line <em>287</em> to <em>293</em> and add '<em>AllocStdCallThunk</em>' and '<em>FreeStdCallThunk</em>' to look like:</p>
<div>
<p><span>&nbsp; 287</span>&nbsp;<span>/*</span></p>
<p><span>&nbsp; 288</span>&nbsp;<span>PVOID __stdcall __AllocStdCallThunk(VOID);</span></p>
<p><span>&nbsp; 289</span>&nbsp;<span>VOID&nbsp; __stdcall __FreeStdCallThunk(PVOID);</span></p>
<p><span>&nbsp; 290</span>&nbsp;</p>
<p><span>&nbsp; 291</span>&nbsp;<span>#define AllocStdCallThunk() __AllocStdCallThunk()</span></p>
<p><span>&nbsp; 292</span>&nbsp;<span>#define FreeStdCallThunk(p) __FreeStdCallThunk(p)</span></p>
<p><span>&nbsp; 293</span>&nbsp;</p>
<p><span>&nbsp; 294</span>&nbsp;<span>#pragma comment(lib, &quot;atlthunk.lib&quot;)</span></p>
<p><span>&nbsp; 295</span>&nbsp;<span>*/</span></p>
<p><span>&nbsp; 296</span>&nbsp;</p>
<p><span>&nbsp; 297</span>&nbsp;<span>#define</span> AllocStdCallThunk() HeapAlloc(GetProcessHeap(), 0,
<span>sizeof</span>(_stdcallthunk))</p>
<p><span>&nbsp; 298</span>&nbsp;<span>#define</span> FreeStdCallThunk(p) HeapFree(GetProcessHeap(), 0, p)</p>
</div>
<p>You should now be able to compile a visualization. Compile your visualization and launch
<em>Windows Media Player</em>.</p>
<ol>
<li>Play a song; you can try <em>My Fair Lady</em> by <em>David Byrne</em> over <a target="_blank" href="http://ccmixter.org/media/people/wired">
ccMixter</a> (this is the melody from the video preview); </li><li>Click on '<em>Now Playing</em>'; </li><li>Right-click inside <em>Windows Media Player</em> and click '<em>Coding4Fun Winter Visualization</em>' &gt; '<em>Coding4Fun Winter Visualization Bars</em>' or '<em>Coding4Fun Winter Visualization Wave</em>';
</li><li>Please take a good look at the generated visualization. Do you see the flicker (the flashing effect that you wouldn't want to see)? Don't worry, we'll make the visualization flicker-free in a few minutes.
</li></ol>
<h3>How do we debug a visualization?</h3>
<p>We know how to build and try a visualization; however, how do we debug one? Simple - we attach to the '<em>wmplayer.exe</em>' process.</p>
<ol>
<li>Click on '<em>Project</em>' &gt; '<em>Properties</em>'; </li><li>Expand '<em>Configuration Properties</em>' &gt; '<em>Debugging</em>'; </li><li>In '<em>Command</em>' enter '<em>C:\Program Files\Windows Media Player\wmplayer.exe</em>';
</li><li>Change '<em>Attach</em>' from '<em>No</em>' to '<em>Yes</em>'; </li><li>Click '<em>OK</em>'; </li><li>Open '<em>MyWinterVisualization.cpp</em>' and locate '<em>CMyWinterVisualization::Render</em>';
</li><li>Add a breakpoint at line '<em>60</em>' in '<em>MyWinterVisualization.cpp</em>';
</li><li><em>Build Solution</em> and launch <em>Windows Media Player</em>; </li><li><em>Start Debugging</em> and select your visualization in <em>Windows Media Player</em>; the visualization should break in
<em>Visual Studio</em>. </li></ol>
<h3>The Winter Visualization</h3>
<p>From now on, we'll take a look at the source code for the Winter Visualization. A visualization can have one or more
<em>presets</em> (<em>Bars</em> and <em>Wave</em> for example). I've decided to go with two presents for the Winter Visualization and named them:
<em>Snow Flakes</em> (draws blue snowflakes) and <em>Snow Flames</em> (draws red snowflakes).</p>
<h3>Configuration</h3>
<p>Open '<em>WinterVisualization.h</em>' and check the configuration values:</p>
<div>
<p><span>&nbsp;&nbsp; 18</span>&nbsp;<span>#define</span> EQ_ANGLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1.0471975511965977461542144610932f&nbsp;&nbsp;&nbsp;
<span>// - PI / 3</span></p>
<p><span>&nbsp;&nbsp; 19</span>&nbsp;<span>#define</span> SNOW_MIN_SIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 23&nbsp;&nbsp;&nbsp; <span>// in pixels</span></p>
<p><span>&nbsp;&nbsp; 20</span>&nbsp;<span>#define</span> SNOW_MAX_SIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 337&nbsp;&nbsp;&nbsp; <span>
// in pixels</span></p>
<p><span>&nbsp;&nbsp; 21</span>&nbsp;<span>#define</span> SNOW_STEP_SIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp;&nbsp; <span>// in pixels</span></p>
<p><span>&nbsp;&nbsp; 22</span>&nbsp;<span>#define</span> SNOW_COUNT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13&nbsp;&nbsp;&nbsp; <span>
// number of snowflakes</span></p>
<p><span>&nbsp;&nbsp; 23</span>&nbsp;<span>#define</span> SNOW_FLAKE_COLOR_COUNT&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp; <span>// number of blue colors</span></p>
<p><span>&nbsp;&nbsp; 24</span>&nbsp;<span>#define</span> SNOW_FLAME_COLOR_COUNT&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp; <span>// number of red colors</span></p>
<p><span>&nbsp;&nbsp; 25</span>&nbsp;<span>#define</span> SNOW_ALPHA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 237&nbsp;&nbsp;&nbsp; <span>
// alpha value</span></p>
<p><span>&nbsp;&nbsp; 26</span>&nbsp;<span>#define</span> KOCH_IT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp; <span>
// number of iterations for Koch</span></p>
</div>
<p>Don't modify <em>EQ_ANGLE</em> as it's needed to make equilateral triangles for the Koch Snowflake Fractal. If you change
<em>SNOW_FLAKE_COLOR_COUNT</em> or <em>SNOW_FLAME_COLOR_COUNT</em>, modify the appropriate lines in
<em>CWinterVisualization::FinalConstruct</em>. The visualization involves a lot of computations and changing any configuration value could potentially slow it down. However, you're more than welcome to try anything... For example, increasing
<em>KOCH_IT</em> to <em>6</em> will make the visualization run slower, but the snowflakes will have a more defined border. Try playing with
<em>SNOW_ALPHA</em> (value should be between 0 and 255).</p>
<h3>Initialization</h3>
<p>Open '<em>WinterVisualization.cpp</em>':</p>
<div>
<p><span>&nbsp;&nbsp; 37</span> HRESULT CWinterVisualization::FinalConstruct()</p>
<p><span>&nbsp;&nbsp; 38</span> {</p>
<p><span>&nbsp;&nbsp; 39</span>&nbsp;&nbsp;&nbsp;&nbsp; tsPrev&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous time stamp</span></p>
<p><span>&nbsp;&nbsp; 40</span>&nbsp;&nbsp;&nbsp;&nbsp; rcPrev.left&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous drawing surface</span></p>
<p><span>&nbsp;&nbsp; 41</span>&nbsp;&nbsp;&nbsp;&nbsp; rcPrev.top&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous drawing surface</span></p>
<p><span>&nbsp;&nbsp; 42</span>&nbsp;&nbsp;&nbsp;&nbsp; rcPrev.right&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous drawing surface</span></p>
<p><span>&nbsp;&nbsp; 43</span>&nbsp;&nbsp;&nbsp;&nbsp; rcPrev.bottom&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous drawing surface</span></p>
<p><span>&nbsp;&nbsp; 44</span>&nbsp;</p>
<p><span>&nbsp;&nbsp; 45</span>&nbsp;&nbsp;&nbsp;&nbsp; hdcPrev&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous handler to device context</span></p>
<p><span>&nbsp;&nbsp; 46</span>&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapPrev&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// previous drawing bitmap</span></p>
<p><span>&nbsp;&nbsp; 47</span>&nbsp;</p>
<p><span>&nbsp;&nbsp; 48</span>&nbsp;&nbsp;&nbsp;&nbsp; hdcMem&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// memory handler to device context</span></p>
<p><span>&nbsp;&nbsp; 49</span>&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapMem&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp; <span>// memory drawing bitmap</span></p>
<p><span>&nbsp;&nbsp; 50</span>&nbsp;</p>
<p><span>&nbsp;&nbsp; 51</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Create Elapsed Font */</span></p>
<p><span>&nbsp;&nbsp; 52</span>&nbsp;&nbsp;&nbsp;&nbsp; LOGFONT lfElapsed;</p>
<p><span>&nbsp;&nbsp; 53</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfHeight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 23;</p>
<p><span>&nbsp;&nbsp; 54</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfWidth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 55</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfEscapement&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 56</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfOrientation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 57</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfWeight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FW_BOLD;</p>
<p><span>&nbsp;&nbsp; 58</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfItalic&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 59</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfUnderline&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 60</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfStrikeOut&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 61</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfCharSet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = DEFAULT_CHARSET;</p>
<p><span>&nbsp;&nbsp; 62</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfOutPrecision&nbsp;&nbsp;&nbsp; = OUT_DEFAULT_PRECIS;</p>
<p><span>&nbsp;&nbsp; 63</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfClipPrecision&nbsp;&nbsp;&nbsp; = CLIP_DEFAULT_PRECIS;</p>
<p><span>&nbsp;&nbsp; 64</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfQuality&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = ANTIALIASED_QUALITY;</p>
<p><span>&nbsp;&nbsp; 65</span>&nbsp;&nbsp;&nbsp;&nbsp; lfElapsed.lfPitchAndFamily&nbsp;&nbsp;&nbsp; = FF_MODERN;</p>
<p><span>&nbsp;&nbsp; 66</span>&nbsp;&nbsp;&nbsp;&nbsp; _tcscpy_s(lfElapsed.lfFaceName, TEXT(<span>&quot;\0&quot;</span>));</p>
<p><span>&nbsp;&nbsp; 67</span>&nbsp;&nbsp;&nbsp;&nbsp; hfElapsed = CreateFontIndirect(&amp;lfElapsed);</p>
<p><span>&nbsp;&nbsp; 68</span>&nbsp;</p>
<p><span>&nbsp;&nbsp; 69</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Create Plus Font */</span></p>
<p><span>&nbsp;&nbsp; 70</span>&nbsp;&nbsp;&nbsp;&nbsp; LOGFONT lfPlus;</p>
<p><span>&nbsp;&nbsp; 71</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfHeight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 9;</p>
<p><span>&nbsp;&nbsp; 72</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfWidth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 73</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfEscapement&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 74</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfOrientation&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp;&nbsp; 75</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfWeight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FW_BOLD;</p>
<p><span>&nbsp;&nbsp; 76</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfItalic&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 77</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfUnderline&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 78</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfStrikeOut&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = FALSE;</p>
<p><span>&nbsp;&nbsp; 79</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfCharSet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = DEFAULT_CHARSET;</p>
<p><span>&nbsp;&nbsp; 80</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfOutPrecision&nbsp;&nbsp;&nbsp; = OUT_DEFAULT_PRECIS;</p>
<p><span>&nbsp;&nbsp; 81</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfClipPrecision&nbsp;&nbsp;&nbsp; = CLIP_DEFAULT_PRECIS;</p>
<p><span>&nbsp;&nbsp; 82</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfQuality&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = ANTIALIASED_QUALITY;</p>
<p><span>&nbsp;&nbsp; 83</span>&nbsp;&nbsp;&nbsp;&nbsp; lfPlus.lfPitchAndFamily&nbsp;&nbsp;&nbsp; = FF_MODERN;</p>
<p><span>&nbsp;&nbsp; 84</span>&nbsp;&nbsp;&nbsp;&nbsp; _tcscpy_s(lfPlus.lfFaceName, TEXT(<span>&quot;\0&quot;</span>));</p>
<p><span>&nbsp;&nbsp; 85</span>&nbsp;&nbsp;&nbsp;&nbsp; hfPlus = CreateFontIndirect(&amp;lfPlus);</p>
<p><span>&nbsp;&nbsp; 86</span>&nbsp;</p>
<p><span>&nbsp;&nbsp; 87</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Flake Colors */</span></p>
<p><span>&nbsp;&nbsp; 88</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[0] = CreatePen(PS_SOLID, 1, RGB(99, 184, 255));&nbsp;&nbsp;&nbsp;
<span>// #63B8FF</span></p>
<p><span>&nbsp;&nbsp; 89</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[1] = CreatePen(PS_SOLID, 1, RGB(92, 172, 238));&nbsp;&nbsp;&nbsp;
<span>// #5CACEE</span></p>
<p><span>&nbsp;&nbsp; 90</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[2] = CreatePen(PS_SOLID, 1, RGB(30, 144, 255));&nbsp;&nbsp;&nbsp;
<span>// #1E90FF</span></p>
<p><span>&nbsp;&nbsp; 91</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[3] = CreatePen(PS_SOLID, 1, RGB(28, 134, 238));&nbsp;&nbsp;&nbsp;
<span>// #1C86EE</span></p>
<p><span>&nbsp;&nbsp; 92</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[4] = CreatePen(PS_SOLID, 1, RGB(16, 78, 139));&nbsp;&nbsp;&nbsp;
<span>// #104E8B</span></p>
<p><span>&nbsp;&nbsp; 93</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Flame Colors */</span></p>
<p><span>&nbsp;&nbsp; 94</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[5] = CreatePen(PS_SOLID, 1, RGB(220, 20, 60));&nbsp;&nbsp;&nbsp;
<span>// #DC143C</span></p>
<p><span>&nbsp;&nbsp; 95</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[6] = CreatePen(PS_SOLID, 1, RGB(255, 48, 48));&nbsp;&nbsp;&nbsp;
<span>// #FF3030</span></p>
<p><span>&nbsp;&nbsp; 96</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[7] = CreatePen(PS_SOLID, 1, RGB(238, 44, 44));&nbsp;&nbsp;&nbsp;
<span>// #EE2C2C</span></p>
<p><span>&nbsp;&nbsp; 97</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[8] = CreatePen(PS_SOLID, 1, RGB(205, 38, 38));&nbsp;&nbsp;&nbsp;
<span>// #CD2626</span></p>
<p><span>&nbsp;&nbsp; 98</span>&nbsp;&nbsp;&nbsp;&nbsp; hpSnowColor[9] = CreatePen(PS_SOLID, 1, RGB(139, 26, 26));&nbsp;&nbsp;&nbsp;
<span>// #8B1A1A</span></p>
<p><span>&nbsp;&nbsp; 99</span>&nbsp;</p>
<p><span>&nbsp; 100</span>&nbsp;&nbsp;&nbsp;&nbsp; hBrushBack = CreateSolidBrush(RGB(0, 0, 0));</p>
<p><span>&nbsp; 101</span>&nbsp;</p>
<p><span>&nbsp; 102</span>&nbsp;&nbsp;&nbsp;&nbsp; iKochCount = (SNOW_MAX_SIZE - SNOW_MIN_SIZE) / SNOW_STEP_SIZE;</p>
<p><span>&nbsp; 103</span>&nbsp;&nbsp;&nbsp;&nbsp; CreateSnow(); <span>// populate pKoch</span></p>
<p><span>&nbsp; 104</span>&nbsp;</p>
<p><span>&nbsp; 105</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>// Make snowflakes re-initialize in DrawSnow</span></p>
<p><span>&nbsp; 106</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT i = 0; i &lt; SNOW_COUNT; &#43;&#43;i)</p>
<p><span>&nbsp; 107</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iSnowSize[i] = iKochCount - 1;</p>
<p><span>&nbsp; 108</span>&nbsp;</p>
<p><span>&nbsp; 109</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span> S_OK;</p>
<p><span>&nbsp; 110</span> }</p>
</div>
<p>The surface size, the device contexts, the fonts, the pens and the brushes are initialized (the variables are declared in '<em>WinterVisualization.h</em>'). Notice that I'm also precomputing the Koch Snowflake Fractal because it doesn't make sense to compute
 it each time a snowflake is drawn; see <em>CWinterVisualization::CreateSnow</em> for more details.<br>
Don't forget that we're in the native C&#43;&#43; world and we have to release memory! The article won't cover the memory deallocation, but you can find it inside
<em>CWinterVisualization::FinalRelease</em>.</p>
<h3>Rendering the Elapsed Time</h3>
<p><em>CWinterVisualization::DrawText</em> renders the elapsed time in the top-right corner; use this method when you want to see how frequent your
<em>CWinterVisualization::Render</em> gets called by <em>Windows Media Player</em>.</p>
<div>
<p><span>&nbsp; 414</span>&nbsp;<span>void</span> CWinterVisualization::DrawText(TimedLevel * pLevels, HDC hdcMem, RECT rcMem)</p>
<p><span>&nbsp; 415</span> {</p>
<p><span>&nbsp; 416</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>// don't display elapsed text when screen is too small</span></p>
<p><span>&nbsp; 417</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (rcMem.bottom &lt; 240)</p>
<p><span>&nbsp; 418</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span>;</p>
<p><span>&nbsp; 419</span>&nbsp;</p>
<p><span>&nbsp; 420</span>&nbsp;&nbsp;&nbsp;&nbsp; HFONT hfOld = <span>static_cast</span>&lt;HFONT&gt;(SelectObject(hdcMem, hfElapsed));</p>
<p><span>&nbsp; 421</span>&nbsp;</p>
<p><span>&nbsp; 422</span>&nbsp;&nbsp;&nbsp;&nbsp; SetBkMode(hdcMem, TRANSPARENT);</p>
<p><span>&nbsp; 423</span>&nbsp;&nbsp;&nbsp;&nbsp; SetTextAlign(hdcMem, TA_RIGHT | TA_TOP);</p>
<p><span>&nbsp; 424</span>&nbsp;&nbsp;&nbsp;&nbsp; SetTextColor(hdcMem, RGB(255, 255, 255));</p>
<p><span>&nbsp; 425</span>&nbsp;</p>
<p><span>&nbsp; 426</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Convert time stamp to string */</span></p>
<p><span>&nbsp; 427</span>&nbsp;&nbsp;&nbsp;&nbsp; TCHAR tcElapsed[32];</p>
<p><span>&nbsp; 428</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (_i64tot_s(pLevels-&gt;timeStamp, tcElapsed, _countof(tcElapsed), 10) == 0)</p>
<p><span>&nbsp; 429</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextOut(hdcMem, rcMem.right, rcMem.top, tcElapsed, <span>
static_cast</span>&lt;<span>int</span>&gt;(_tcslen(tcElapsed)));</p>
<p><span>&nbsp; 430</span>&nbsp;</p>
<p><span>&nbsp; 431</span>&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem, hfOld);</p>
<p><span>&nbsp; 432</span> }</p>
</div>
<p><em>pLevels-&gt;timeStamp</em> is measured in 100 nanoseconds and indicates the elapsed time inside the playing song. Be aware that the '<em>SelectObject</em>' method returns the previous/old selected object in the device context; you're advised to select the
 old object back in the device context after you've finished working with the new one.</p>
<h3>Rendering the Wave</h3>
<p>If you watched the video preview, you've seen that there is a wave in the middle of the screen. The
<em>CWinterVisualization::DrawPlus</em> method draws plusses ('<em>&#43;</em>') to build the wave (drawing plusses instead of connected lines gives a better effect).</p>
<div>
<p><span>&nbsp; 382</span>&nbsp;<span>void</span> CWinterVisualization::DrawPlus(TimedLevel * pLevels, HDC hdcMem, RECT rcMem)</p>
<p><span>&nbsp; 383</span> {</p>
<p><span>&nbsp; 384</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>// don't display plus line when screen is too small</span></p>
<p><span>&nbsp; 385</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (rcMem.right &lt; 240)</p>
<p><span>&nbsp; 386</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span>;</p>
<p><span>&nbsp; 387</span>&nbsp;</p>
<p><span>&nbsp; 388</span>&nbsp;&nbsp;&nbsp;&nbsp; HFONT hfOld = <span>static_cast</span>&lt;HFONT&gt;(SelectObject(hdcMem, hfPlus));</p>
<p><span>&nbsp; 389</span>&nbsp;</p>
<p><span>&nbsp; 390</span>&nbsp;&nbsp;&nbsp;&nbsp; SetBkMode(hdcMem, TRANSPARENT);</p>
<p><span>&nbsp; 391</span>&nbsp;&nbsp;&nbsp;&nbsp; SetTextAlign(hdcMem, TA_RIGHT | TA_TOP);</p>
<p><span>&nbsp; 392</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>switch</span> (m_nPreset)</p>
<p><span>&nbsp; 393</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 394</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>case</span> PRESET_FLAKE:</p>
<p><span>&nbsp; 395</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetTextColor(hdcMem, RGB(176, 226, 255));</p>
<p><span>&nbsp; 396</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>break</span>;</p>
<p><span>&nbsp; 397</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>case</span> PRESET_FLAME:</p>
<p><span>&nbsp; 398</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetTextColor(hdcMem, RGB(255, 64, 64));</p>
<p><span>&nbsp; 399</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>break</span>;</p>
<p><span>&nbsp; 400</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 401</span>&nbsp;</p>
<p><span>&nbsp; 402</span>&nbsp;&nbsp;&nbsp;&nbsp; TCHAR tcPlus[] = TEXT(<span>&quot;&#43;&quot;</span>);</p>
<p><span>&nbsp; 403</span>&nbsp;&nbsp;&nbsp;&nbsp; INT iPlusLen = <span>static_cast</span>&lt;INT&gt;(_tcslen(tcPlus));</p>
<p><span>&nbsp; 404</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT i = 0; i &lt; SA_BUFFER_SIZE; &#43;&#43;i)</p>
<p><span>&nbsp; 405</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 406</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT x = <span>static_cast</span>&lt;INT&gt;(rcMem.right * i / 1024.0f);</p>
<p><span>&nbsp; 407</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT y = <span>static_cast</span>&lt;INT&gt;(rcMem.bottom * pLevels-&gt;waveform[0][i] / 256.0f);</p>
<p><span>&nbsp; 408</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextOut(hdcMem, x, y, tcPlus, iPlusLen);</p>
<p><span>&nbsp; 409</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 410</span>&nbsp;</p>
<p><span>&nbsp; 411</span>&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem, hfOld);</p>
<p><span>&nbsp; 412</span> }</p>
</div>
<p>This method depends on the currently selected preset and changes the color of the wave: blue for Flakes and red for Flames. We'll be rendering only the first channel (mono) waveform
<em>pLevels-&gt;waveform[0]</em>. If you decide to use both channels (stereo), you'll have to use
<em>pLevels-&gt;waveform[0]</em> and <em>pLevels-&gt;waveform[1]</em>; if the song is mono, then the second array is undefined (take care)! The method scales the values to the canvas size and draws the linked plusses.</p>
<h3>Creating a Koch Snowflake</h3>
<p><em>CWinterVisualization::CreateSnow</em> computes the Koch Snowflake as described on the
<a target="_blank" href="http://mathworld.wolfram.com/KochSnowflake.html">MathWorld Web Site</a>. We construct an equilateral triangle with 3 vertices and start iterating: at the first iteration we have a polygon (which starts to resemble with a snowflake)
 with 12 vertices; at the second iteration we have a better snowflake/polygon with 48 vertices... at the fifth iteration we have a snowflake with 3072 vertices.</p>
<div>
<p><span>&nbsp; 272</span>&nbsp;<span>void</span> CWinterVisualization::CreateSnow()</p>
<p><span>&nbsp; 273</span> {</p>
<p><span>&nbsp; 274</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Create Koch */</span></p>
<p><span>&nbsp; 275</span>&nbsp;&nbsp;&nbsp;&nbsp; pKoch = <span>new</span> POINT * [iKochCount];</p>
<p><span>&nbsp; 276</span>&nbsp;</p>
<p><span>&nbsp; 277</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Frames */</span></p>
<p><span>&nbsp; 278</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT w = 0; w &lt; iKochCount; &#43;&#43;w)</p>
<p><span>&nbsp; 279</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 280</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Initialize Koch Fractal Snowflake with the equilateral triangle */</span></p>
<p><span>&nbsp; 281</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iVertexNowCount&nbsp;&nbsp;&nbsp; = 3;</p>
<p><span>&nbsp; 282</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT * pVertexNow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = <span>new</span> POINT[iVertexNowCount];</p>
<p><span>&nbsp; 283</span>&nbsp;</p>
<p><span>&nbsp; 284</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT iSize = (SNOW_MIN_SIZE &#43; w * SNOW_STEP_SIZE) / 2;</p>
<p><span>&nbsp; 285</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[0].x = - iSize;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[0].y = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span>// A</span></p>
<p><span>&nbsp; 286</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[1].x = &#43; iSize;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[1].y = 23;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span>// B</span></p>
<p><span>&nbsp; 287</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[2] = MakeEqTriangle(pVertexNow[0], pVertexNow[1]);&nbsp;&nbsp;&nbsp;
<span>// C</span></p>
<p><span>&nbsp; 288</span>&nbsp;</p>
<p><span>&nbsp; 289</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* http://mathworld.wolfram.com/KochSnowflake.html */</span></p>
<p><span>&nbsp; 290</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT q = 1; q &lt; KOCH_IT &#43; 1; &#43;&#43;q)</p>
<p><span>&nbsp; 291</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 292</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iVertexNewCount = iVertexNowCount * 4;</p>
<p><span>&nbsp; 293</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT * pVertexNew&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = <span>new</span> POINT[iVertexNewCount];</p>
<p><span>&nbsp; 294</span>&nbsp;</p>
<p><span>&nbsp; 295</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT i = 0; i &lt; iVertexNowCount; &#43;&#43;i)</p>
<p><span>&nbsp; 296</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 297</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT j = (i &#43; 1) % iVertexNowCount;</p>
<p><span>&nbsp; 298</span>&nbsp;</p>
<p><span>&nbsp; 299</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT pA = pVertexNow[i];</p>
<p><span>&nbsp; 300</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT pE = pVertexNow[j];</p>
<p><span>&nbsp; 301</span>&nbsp;</p>
<p><span>&nbsp; 302</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG lWidth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = pE.x - pA.x;</p>
<p><span>&nbsp; 303</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG lHeight&nbsp;&nbsp;&nbsp; = pE.y - pA.y;</p>
<p><span>&nbsp; 304</span>&nbsp;</p>
<p><span>&nbsp; 305</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT pB;</p>
<p><span>&nbsp; 306</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pB.x = pA.x &#43; lWidth / 3;</p>
<p><span>&nbsp; 307</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pB.y = pA.y &#43; lHeight / 3;</p>
<p><span>&nbsp; 308</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT pD;</p>
<p><span>&nbsp; 309</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pD.x = pA.x &#43; lWidth * 2 / 3;</p>
<p><span>&nbsp; 310</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pD.y = pA.y &#43; lHeight * 2 / 3;</p>
<p><span>&nbsp; 311</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT pC = MakeEqTriangle(pD, pB); <span>// equilateral triangle for the inner third</span></p>
<p><span>&nbsp; 312</span>&nbsp;</p>
<p><span>&nbsp; 313</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT k = i * 4;</p>
<p><span>&nbsp; 314</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNew[k &#43; 0] = pA;</p>
<p><span>&nbsp; 315</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNew[k &#43; 1] = pB;</p>
<p><span>&nbsp; 316</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNew[k &#43; 2] = pC;</p>
<p><span>&nbsp; 317</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNew[k &#43; 3] = pD;</p>
<p><span>&nbsp; 318</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 319</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>// move to the next Koch iteration</span></p>
<p><span>&nbsp; 320</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>delete</span>[] pVertexNow;</p>
<p><span>&nbsp; 321</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = pVertexNew;</p>
<p><span>&nbsp; 322</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iVertexNowCount&nbsp;&nbsp;&nbsp; = iVertexNewCount;</p>
<p><span>&nbsp; 323</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 324</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Done */</span></p>
<p><span>&nbsp; 325</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pKoch[w] = pVertexNow;</p>
<p><span>&nbsp; 326</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 327</span> }</p>
</div>
<h3>Rendering the Snowflakes</h3>
<p>There are 13 (this is the default value) snowflakes that need to be rendered on the device context. When a snowflake reaches its maximum size, it gets reinitialized: its size depends on the waveform, its color depends on the preset and it's randomly distributed
 across the surface. Each snowflake is translated and rotated to its target position (this is required because of the precomputation where we considered the snowflake to be around x=0 and y=0).</p>
<div>
<p><span>&nbsp; 329</span>&nbsp;<span>void</span> CWinterVisualization::DrawSnow(TimedLevel * pLevels, HDC hdcMem, RECT rcMem)</p>
<p><span>&nbsp; 330</span> {</p>
<p><span>&nbsp; 331</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT i = 0; i &lt; SNOW_COUNT; &#43;&#43;i)</p>
<p><span>&nbsp; 332</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 333</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Initialize snowflake when reached SNOW_MAX_SIZE */</span></p>
<p><span>&nbsp; 334</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (&#43;&#43;iSnowSize[i] == iKochCount)</p>
<p><span>&nbsp; 335</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 336</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>// size depends on waveform</span></p>
<p><span>&nbsp; 337</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iSnowSize[i] = iKochCount * pLevels-&gt;waveform[0][SA_BUFFER_SIZE * i / SNOW_COUNT] / 256;</p>
<p><span>&nbsp; 338</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>switch</span> (m_nPreset)</p>
<p><span>&nbsp; 339</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 340</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>case</span> PRESET_FLAKE:</p>
<p><span>&nbsp; 341</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iSnowColor[i] = rand() % SNOW_FLAKE_COLOR_COUNT;</p>
<p><span>&nbsp; 342</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>break</span>;</p>
<p><span>&nbsp; 343</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>case</span> PRESET_FLAME:</p>
<p><span>&nbsp; 344</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iSnowColor[i] = SNOW_FLAKE_COLOR_COUNT &#43; rand() % SNOW_FLAME_COLOR_COUNT;</p>
<p><span>&nbsp; 345</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>break</span>;</p>
<p><span>&nbsp; 346</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 347</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>// distribute snowflakes on the screen</span></p>
<p><span>&nbsp; 348</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pSnowPosition[i].x = rcMem.right * i / SNOW_COUNT;</p>
<p><span>&nbsp; 349</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pSnowPosition[i].y = rand() % rcMem.bottom;</p>
<p><span>&nbsp; 350</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 351</span>&nbsp;</p>
<p><span>&nbsp; 352</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Prepare snowflake for drawing */</span></p>
<p><span>&nbsp; 353</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT iVertexNowCount&nbsp;&nbsp;&nbsp; = <span>static_cast</span>&lt;INT&gt;(3 * pow(4.0f, KOCH_IT));</p>
<p><span>&nbsp; 354</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POINT * pVertexNow&nbsp;&nbsp;&nbsp; = <span>new</span> POINT[iVertexNowCount];</p>
<p><span>&nbsp; 355</span>&nbsp;</p>
<p><span>&nbsp; 356</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT j = 0; j &lt; iVertexNowCount; &#43;&#43;j)</p>
<p><span>&nbsp; 357</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 358</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Just translation */</span></p>
<p><span>&nbsp; 359</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>//pVertexNow[j].x = pKoch[iSnowSize[i]][j].x &#43; pSnowPosition[i].x;</span></p>
<p><span>&nbsp; 360</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>//pVertexNow[j].y = pKoch[iSnowSize[i]][j].y &#43; pSnowPosition[i].y;</span></p>
<p><span>&nbsp; 361</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Translation and rotation */</span></p>
<p><span>&nbsp; 362</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FLOAT fAngle = pLevels-&gt;waveform[0][SA_BUFFER_SIZE * i / SNOW_COUNT] * 3.1415926535897932384626433832795f / 256.0f;</p>
<p><span>&nbsp; 363</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FLOAT fAngleCos = cos(fAngle);</p>
<p><span>&nbsp; 364</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FLOAT fAngleSin = sin(fAngle);</p>
<p><span>&nbsp; 365</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[j].x = <span>static_cast</span>&lt;LONG&gt;(fAngleCos * pKoch[iSnowSize[i]][j].x - fAngleSin * pKoch[iSnowSize[i]][j].y &#43; pSnowPosition[i].x);</p>
<p><span>&nbsp; 366</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pVertexNow[j].y = <span>static_cast</span>&lt;LONG&gt;(fAngleSin * pKoch[iSnowSize[i]][j].x &#43; fAngleCos * pKoch[iSnowSize[i]][j].y &#43; pSnowPosition[i].y);</p>
<p><span>&nbsp; 367</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 368</span>&nbsp;</p>
<p><span>&nbsp; 369</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Draw Koch Snowflake */</span></p>
<p><span>&nbsp; 370</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HPEN hpOld = <span>static_cast</span>&lt;HPEN&gt;(SelectObject(hdcMem, hpSnowColor[iSnowColor[i]]));</p>
<p><span>&nbsp; 371</span>&nbsp;</p>
<p><span>&nbsp; 372</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MoveToEx(hdcMem, pVertexNow[0].x, pVertexNow[0].y, 0);</p>
<p><span>&nbsp; 373</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PolylineTo(hdcMem, pVertexNow, iVertexNowCount);</p>
<p><span>&nbsp; 374</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LineTo(hdcMem, pVertexNow[0].x, pVertexNow[0].y);</p>
<p><span>&nbsp; 375</span>&nbsp;</p>
<p><span>&nbsp; 376</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem, hpOld);</p>
<p><span>&nbsp; 377</span>&nbsp;</p>
<p><span>&nbsp; 378</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>delete</span>[] pVertexNow;</p>
<p><span>&nbsp; 379</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 380</span> }</p>
</div>
<p><em>PolylineTo</em> is the fastest way to draw a polygon when you use a pen with width
<em>1</em>. The width of the pen has to be one!</p>
<h3>Wrapping up: Blending and Rendering</h3>
<p>So far, we've seen some methods that did something if someone called them. <em>
CWinterVisualization::Render</em> calls those methods and in turn is called by <em>
Windows Media Player</em> (which decides how frequent to call it). Notice the line
<em>169</em> which allows this method to be called only 30 times per second. Because the size of the drawing surface can change (when you resize
<em>Windows Media Player</em>), the device contexts are deleted and created again.</p>
<div>
<p><span>&nbsp; 167</span> STDMETHODIMP CWinterVisualization::Render(TimedLevel *pLevels, HDC hdc, RECT *prc)</p>
<p><span>&nbsp; 168</span> {</p>
<p><span>&nbsp; 169</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (_abs64(pLevels-&gt;timeStamp - tsPrev) &lt; 333333)
<span>// 10^7 is 1 second; use only 30fps</span></p>
<p><span>&nbsp; 170</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span> S_OK;</p>
<p><span>&nbsp; 171</span>&nbsp;&nbsp;&nbsp;&nbsp; tsPrev = pLevels-&gt;timeStamp; <span>// keep time stamp</span></p>
<p><span>&nbsp; 172</span>&nbsp;</p>
<p><span>&nbsp; 173</span>&nbsp;&nbsp;&nbsp;&nbsp; RECT rcMem = {0, 0, prc-&gt;right - prc-&gt;left, prc-&gt;bottom - prc-&gt;top};
<span>// memory rectangle</span></p>
<p><span>&nbsp; 174</span>&nbsp;</p>
<p><span>&nbsp; 175</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Check whether drawing surface changed */</span></p>
<p><span>&nbsp; 176</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> ((rcMem.left != rcPrev.left) || (rcMem.top != rcPrev.top) ||
</p>
<p><span>&nbsp; 177</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (rcMem.right != rcPrev.right) || (rcMem.bottom != rcPrev.bottom))</p>
<p><span>&nbsp; 178</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 179</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rcPrev = rcMem; <span>// keep memory rectangle</span></p>
<p><span>&nbsp; 180</span>&nbsp;</p>
<p><span>&nbsp; 181</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Delete Prev */</span></p>
<p><span>&nbsp; 182</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (hNewBitmapPrev)</p>
<p><span>&nbsp; 183</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 184</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcPrev, hOldBitmapPrev);</p>
<p><span>&nbsp; 185</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteObject(hNewBitmapPrev);</p>
<p><span>&nbsp; 186</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 187</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapPrev&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 188</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmapPrev&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 189</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (hdcPrev)</p>
<p><span>&nbsp; 190</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hdcPrev);</p>
<p><span>&nbsp; 191</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcPrev&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 192</span>&nbsp;</p>
<p><span>&nbsp; 193</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Delete Mem */</span></p>
<p><span>&nbsp; 194</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (hNewBitmapMem)</p>
<p><span>&nbsp; 195</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 196</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem, hOldBitmapMem);</p>
<p><span>&nbsp; 197</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteObject(hNewBitmapMem);</p>
<p><span>&nbsp; 198</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 199</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapMem&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 200</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmapMem&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 201</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (hdcMem)</p>
<p><span>&nbsp; 202</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hdcMem);</p>
<p><span>&nbsp; 203</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcMem&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;</p>
<p><span>&nbsp; 204</span>&nbsp;</p>
<p><span>&nbsp; 205</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>// Make snowflakes re-initialize in DrawSnow</span></p>
<p><span>&nbsp; 206</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>for</span> (INT i = 0; i &lt; SNOW_COUNT; &#43;&#43;i)</p>
<p><span>&nbsp; 207</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iSnowSize[i] = iKochCount - 1;</p>
<p><span>&nbsp; 208</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 209</span>&nbsp;</p>
<p><span>&nbsp; 210</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Create Prev */</span></p>
<p><span>&nbsp; 211</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (!hdcPrev)</p>
<p><span>&nbsp; 212</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcPrev = CreateCompatibleDC(hdc);</p>
<p><span>&nbsp; 213</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (!hNewBitmapPrev)</p>
<p><span>&nbsp; 214</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 215</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapPrev = CreateCompatibleBitmap(hdc, rcMem.right, rcMem.bottom);</p>
<p><span>&nbsp; 216</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmapPrev = <span>static_cast</span>&lt;HBITMAP&gt;(SelectObject(hdcPrev, hNewBitmapPrev));</p>
<p><span>&nbsp; 217</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 218</span>&nbsp;</p>
<p><span>&nbsp; 219</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Create Mem */</span></p>
<p><span>&nbsp; 220</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (!hdcMem)</p>
<p><span>&nbsp; 221</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcMem = CreateCompatibleDC(hdc);</p>
<p><span>&nbsp; 222</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>if</span> (!hNewBitmapMem)</p>
<p><span>&nbsp; 223</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><span>&nbsp; 224</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hNewBitmapMem = CreateCompatibleBitmap(hdc, rcMem.right, rcMem.bottom);</p>
<p><span>&nbsp; 225</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmapMem = <span>static_cast</span>&lt;HBITMAP&gt;(SelectObject(hdcMem, hNewBitmapMem));</p>
<p><span>&nbsp; 226</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span>&nbsp; 227</span>&nbsp;</p>
<p><span>&nbsp; 228</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Draw background on Mem */</span></p>
<p><span>&nbsp; 229</span>&nbsp;&nbsp;&nbsp;&nbsp; FillRect(hdcMem, &amp;rcMem, hBrushBack);</p>
<p><span>&nbsp; 230</span>&nbsp;</p>
<p><span>&nbsp; 231</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Blend Prev with Mem */</span>&nbsp;&nbsp;&nbsp; </p>
<p><span>&nbsp; 232</span>&nbsp;&nbsp;&nbsp;&nbsp; BLENDFUNCTION bfPrev = {AC_SRC_OVER, 0, SNOW_ALPHA, AC_SRC_ALPHA};</p>
<p><span>&nbsp; 233</span>&nbsp;&nbsp;&nbsp;&nbsp; AlphaBlend(hdcMem, rcMem.left, rcMem.top, rcMem.right, rcMem.bottom,
</p>
<p><span>&nbsp; 234</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcPrev, rcMem.left, rcMem.top, rcMem.right, rcMem.bottom, bfPrev);</p>
<p><span>&nbsp; 235</span>&nbsp;</p>
<p><span>&nbsp; 236</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Draw Snow on Mem */</span></p>
<p><span>&nbsp; 237</span>&nbsp;&nbsp;&nbsp;&nbsp; DrawSnow(pLevels, hdcMem, rcMem);</p>
<p><span>&nbsp; 238</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Draw Plus on Mem */</span></p>
<p><span>&nbsp; 239</span>&nbsp;&nbsp;&nbsp;&nbsp; DrawPlus(pLevels, hdcMem, rcMem);</p>
<p><span>&nbsp; 240</span>&nbsp;</p>
<p><span>&nbsp; 241</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Copy Mem to Prev */</span></p>
<p><span>&nbsp; 242</span>&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hdcPrev, rcMem.left, rcMem.top, rcMem.right, rcMem.bottom,</p>
<p><span>&nbsp; 243</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcMem, rcMem.left, rcMem.top, SRCCOPY);</p>
<p><span>&nbsp; 244</span>&nbsp;</p>
<p><span>&nbsp; 245</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Draw Text on Mem */</span></p>
<p><span>&nbsp; 246</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Uncomment the following line to draw elapsed text in the top-right corner */</span></p>
<p><span>&nbsp; 247</span>&nbsp;&nbsp;&nbsp;&nbsp; DrawText(pLevels, hdcMem, rcMem);</p>
<p><span>&nbsp; 248</span>&nbsp;</p>
<p><span>&nbsp; 249</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>/* Copy Mem to WMP */</span></p>
<p><span>&nbsp; 250</span>&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hdc, prc-&gt;left, prc-&gt;top, prc-&gt;right - prc-&gt;left, prc-&gt;bottom - prc-&gt;top,
</p>
<p><span>&nbsp; 251</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hdcMem, rcMem.left, rcMem.top, SRCCOPY);</p>
<p><span>&nbsp; 252</span>&nbsp;</p>
<p><span>&nbsp; 253</span>&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span> S_OK;</p>
<p><span>&nbsp; 254</span> }</p>
</div>
<p>I haven't said anything about the flicker... how was that avoided? Take a good look at this method (especially at line
<em>250</em>): we weren't drawing directly on the default device context as the wizard-generated visualization did, instead we were drawing on a memory device context
<em>hdcMem</em> which was copied to the default device context only when everything was ready. It's a simple solution and it avoids the flicker! Never draw directly to the
<em>hdc</em> received as the argument!<br>
What about the smooth effect? We needed the <em>msimg32.lib</em>, especially the <em>
AlphaBlend</em> method which blends two device contexts together. The blend between
<em>hdcPrev</em> and <em>hdcMem</em> lets the previous rendered scene to be drawn again with a darker shade, while the new scene is as vivid as it should be;
<em>hdcMem</em> is saved to <em>hdcPrev</em> to keep it for the next rendering when it becomes the old scene. That's it!</p>
<h3>Conclusion</h3>
<p>Winter Visualization, Snow Flakes:<br>
<img height="529" width="691" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/capture1.png" alt="capture1" border="0"></p>
<p>Winter Visualization, Snow Flames:<br>
<img height="529" width="691" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/capture2.png" alt="capture2" border="0"></p>
<p>You've created a beautiful winter visualization... Watch the dancing snowflakes and download the
<a target="_blank" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/WinterVisualization.zip">
Winter Visualization Source Code</a> or download only the installer <a target="_blank" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/6821379/WinterVisualizationSetup.msi">
WinterVisualizationSetup.msi</a> (share the Winter Visualization with your friends). I hope you enjoyed working with C&#43;&#43; and you like what you've learned today!<br>
Thanks to the Microsoft Student Partners - Microsoft Academic Program Team Romania for support. Happy Holidays!</p>
<h3>Reference</h3>
<ul>
<li><a target="_blank" href="http://msdn2.microsoft.com/en-us/library/bb249675.aspx">Windows Media Player Custom Visualizations</a>
</li></ul>
<h3>Bio</h3>
<p>Paul-Valentin Borza is in its third year of study at the <a target="_blank" href="http://www.ubbcluj.ro">
Babeş-Bolyai University of Cluj-Napoca</a>, Romania. Driven by his passion for technology, he was invited in 2005 to be a
<a target="_blank" href="http://www.student-partners.com">Microsoft Student Partners</a> member - Microsoft Academic Program at the
<a target="_blank" href="http://www.cs.ubbcluj.ro">Faculty of Mathematics and Computer Science</a>. He can be reached through his web site at
<a target="_blank" href="http://www.borza.ro">www.borza.ro</a> or on the Windows Live Network with windowslive@borza.ro.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:5e1d440d38084c4c82e89e7600d0d253">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Winter-Visualization-for-Windows-Media-Player-in-C</comments>
      <itunes:summary>
 Ever wondered what&#39;s behind a visualization? This is your opportunity to learn something
 new because there are only a couple of Windows Media Player Visualizations that deliver source code. You&#39;ll learn to build a new visualization with Visual C&amp;#43;&amp;#43; 2005 Express (you won&#39;t even require a Standard Edition)! Winter is here... Snow is here... we&#39;ll
 render 
Koch Snowflake Fractals that depend on the waveform of the playing song with the Windows Graphics Device Interface. This article will also change the way you ever looked at a visualization. Enjoy! 
Paul-Valentin Borza - http://www.borza.ro  

Difficulty: Intermediate
Cost: Free
Time required: 1-3 hours
Software: 
Visual C&amp;#43;&amp;#43; 2005 Express, 
Windows Server 2003 R2 Platform SDK, 
Windows Software Development Kit for Windows Vista
Hardware: None
Download Source: Winter Visualization Source Code
 

How do we build a visualization?
Please install (don&#39;t change the default installation directory): 

Visual C&amp;#43;&amp;#43; 2005 Express
Windows Server 2003 R2 Platform SDK (contains MFC and ATL headers and libraries)
Windows Software Development Kit for Windows Vista (contains Windows Media Player 11 SDK)

We need to make Visual C&amp;#43;&amp;#43; 2005 Express work with visualizations: 

Navigate to &#39;C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\Multimedia\WMP_11\Wizards\VSNET&#39;;
Copy &#39;wmpwiz2005.vsz&#39;, &#39;wmpwiz.vsdir&#39; and &#39;wmpwiz.ico&#39;;
Navigate to &#39;C:\Program Files\Microsoft Visual Studio 8\VC\Express\VCProjects&#39;;
Paste &#39;wmpwiz2005.vsz&#39;, &#39;wmpwiz.vsdir&#39; and &#39;wmpwiz.ico&#39;;
Rename &#39;wmpwiz2005.vsz&#39; to &#39;wmpwiz.vsz&#39; (you&#39;re in &#39;C:\Program Files\Microsoft Visual Studio 8\VC\Express\VCProjects&#39;);
Edit &#39;wmpwiz.vsz&#39; using Notepad and change the line &#39;Param=&amp;quot;ABSOLUTE_PATH = &amp;lt;path to wmpwiz directory goes here&amp;gt;&amp;quot;&#39; with &#39;Param=&amp;quot;ABSOLUTE_PATH = C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\Multimedia\WMP_11\Wizards\VSNET&amp;quot;&#39;;
The Windows Media Player Plug-in Wizard is now installed. Launch 
Visual C&amp;#</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Winter-Visualization-for-Windows-Media-Player-in-C</link>
      <pubDate>Thu, 20 Dec 2007 19:52:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Winter-Visualization-for-Windows-Media-Player-in-C</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/6821379_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/6821379_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Paul-Valentin Borza </dc:creator>
      <itunes:author>Paul-Valentin Borza </itunes:author>
      <slash:comments>25</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Winter-Visualization-for-Windows-Media-Player-in-C/RSS</wfw:commentRss>
      <category>Media</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Christmas CoolWall</title>
      <description><![CDATA[You may be familiar with the <a href="http://www.topgear.com/jsp/coolwall/">Top Gear CoolWall</a>, but not all of us watch TV that comes from the UK.&nbsp; Sometimes those of us in the US just like the idea and <a href="http://en.wikipedia.org/wiki/The_Office">make our version</a> and stick Steve Carell in it.&nbsp; Well, Steve Carell didn't make it for this adventure, but recently a US-based developer took a prototype of a <a href="http://www.mycooluncool.com/">Christmas-themed CoolWall</a> (incidentally prototyped by a <a href="http://www.dotnetsolutions.ltd.uk/main/">UK-based agency</a>)&nbsp;and released it in production mode.<br><br>We caught up with him at his house and got the story on why he did this and what&nbsp;we can do with the&nbsp;Christmas CoolWall.<br><br>Go to his blog for more of&nbsp;<a href="http://adamkinney.com/blog/289/default.aspx">the boring technical details</a> or head over to <a href="http://www.mycooluncool.com/">the CoolWall</a> to create your own Christmas wishlist.<br><br>Then send it to&nbsp;a friend.&nbsp; They need to know what would be &quot;Seriously UnCool&quot; to give you. <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3657c6cc33944e088c499e0f00f33215">]]></description>
      <comments>http://channel9.msdn.com/Blogs/AdamKinney/Christmas-CoolWall</comments>
      <itunes:summary>You may be familiar with the Top Gear CoolWall, but not all of us watch TV that comes from the UK.&amp;nbsp; Sometimes those of us in the US just like the idea and make our version and stick Steve Carell in it.&amp;nbsp; Well, Steve Carell didn&#39;t make it for this adventure, but recently a US-based developer took a prototype of a Christmas-themed CoolWall (incidentally prototyped by a UK-based agency)&amp;nbsp;and released it in production mode.We caught up with him at his house and got the story on why he did this and what&amp;nbsp;we can do with the&amp;nbsp;Christmas CoolWall.Go to his blog for more of&amp;nbsp;the boring technical details or head over to the CoolWall to create your own Christmas wishlist.Then send it to&amp;nbsp;a friend.&amp;nbsp; They need to know what would be &amp;quot;Seriously UnCool&amp;quot; to give you.</itunes:summary>
      <itunes:duration>513</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/AdamKinney/Christmas-CoolWall</link>
      <pubDate>Fri, 14 Dec 2007 20:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/AdamKinney/Christmas-CoolWall</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/content/on10/blogs/coolwallinterview_10.jpg" height="240" width="320"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/content/on10/blogs/coolwallinterview_10_small.jpg" height="64" width="85"></media:thumbnail>
      <media:group>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_2MB_on10.wmv" expression="full" duration="513" fileSize="162256755" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_on10.mp3" expression="full" duration="513" fileSize="4155060" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_on10.mp4" expression="full" duration="513" fileSize="31772581" type="video/mp4" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_on10.wma" expression="full" duration="513" fileSize="4210673" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_on10.wmv" expression="full" duration="513" fileSize="29864033" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_Zune_on10.wmv" expression="full" duration="513" fileSize="41160637" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="mms://mschnlnine.wmod.llnwd.net/a1809/d1/on10/4/0/1/0/2/CoolAdam_s_on10.wmv" expression="full" duration="513" fileSize="196" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://mschnlnine.vo.llnwd.net/d1/on10/4/0/1/0/2/CoolAdam_on10.wmv" length="29864033" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Adam Kinney</dc:creator>
      <itunes:author>Adam Kinney</itunes:author>
      <slash:comments>10</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/AdamKinney/Christmas-CoolWall/RSS</wfw:commentRss>
      <category>Silverlight</category>
      <category>Holiday</category>
      <category>coolwall</category>
      <category>christmas</category>
    </item>
  <item>
      <title>Holiday wishes</title>
      <description><![CDATA[We all love to go shopping, and especially around the Holiday times. Sometimes for ourselves, sometimes for others. Whatever the case may be, I decided to head down to our largest electronics store and see what people had in their goodie bags. <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:9e62d58d7096436582ba9e0f00ffbd3d">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LauraFoy/Holiday-wishes</comments>
      <itunes:summary>We all love to go shopping, and especially around the Holiday times. Sometimes for ourselves, sometimes for others. Whatever the case may be, I decided to head down to our largest electronics store and see what people had in their goodie bags.</itunes:summary>
      <itunes:duration>258</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LauraFoy/Holiday-wishes</link>
      <pubDate>Fri, 07 Dec 2007 22:11:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LauraFoy/Holiday-wishes</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/content/on10/entries/preview/wishlist_large_on10.jpg" height="240" width="320"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/content/on10/entries/previewsmall/wishlist_small_on10.jpg" height="64" width="85"></media:thumbnail>
      <media:group>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_2MB_on10.wmv" expression="full" duration="258" fileSize="80295171" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_on10.mp3" expression="full" duration="258" fileSize="2065891" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_on10.mp4" expression="full" duration="258" fileSize="15568835" type="video/mp4" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_on10.wma" expression="full" duration="258" fileSize="2095849" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_on10.wmv" expression="full" duration="258" fileSize="16324395" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_Zune_on10.wmv" expression="full" duration="258" fileSize="20439063" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="mms://mschnlnine.wmod.llnwd.net/a1809/d1/on10/9/7/9/9/1/wishlist_s_on10.wmv" expression="full" duration="258" fileSize="196" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://mschnlnine.vo.llnwd.net/d1/on10/9/7/9/9/1/wishlist_on10.wmv" length="16324395" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Laura Foy</dc:creator>
      <itunes:author>Laura Foy</itunes:author>
      <slash:comments>9</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LauraFoy/Holiday-wishes/RSS</wfw:commentRss>
      <category>Electronics</category>
      <category>Holiday</category>
      <category>Shopping</category>
    </item>
  <item>
      <title>Possessed PC Pranks for Halloween</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50"><img height="47" alt="Pumpkin" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/Pumkin.gif" width="50" border="0">
</td>
<td><span class="entry_description">In this application, Brian Peek demonstrates how to create two spooky Halloween applications to trick your friends and colleagues.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author"><a href="http://www.brianpeek.com/" target="_blank">Brian Peek</a></div>
<div class="entry_company"><a href="http://www.aspsoft.com/">ASPSOFT, Inc.</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Less than 1 hour</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Basic or Visual C# Express Editions</a>,
<a href="http://msdn2.microsoft.com/en-us/directx/Aa937789.aspx" target="_blank">
DirectX SDK (for application #1)</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input">None</span></div>
<div class="entry_details"><b>Download: </b><a href="http://channel9.msdn.com/ShowPost.aspx?PostID=351868" target="_blank">Download</a>
</div>
</td>
</tr>
</tbody>
</table>
<p></span>&nbsp;</p>
<h3>Introduction</h3>
<p>Last year I wrote two articles on how to annoy your friends and family by <a href="http://blogs.msdn.com/coding4fun/archive/2006/10/30/905508.aspx" target="_blank">
dripping blood down their computer screen</a>, or by <a href="http://blogs.msdn.com/coding4fun/archive/2006/10/30/905480.aspx" target="_blank">
squirting them with (hopefully) fake blood from (even more hopefully) a fake skull</a>.&nbsp; Halloween is just around the corner, so here are two more applications which you can use to further bother the people around you.</p>
<p>&nbsp;</p>
<h3>Application #1 - Cursed Video</h3>
<p>If you have ever seen the horror film <a href="http://www.imdb.com/title/tt0298130/" target="_blank">
The Ring</a>, then you can likely guess the basic premise of this application.&nbsp; For those that haven't, the film is about a video tape which, when watched, will cause the viewer to die within a week of viewing it.&nbsp; So, what better way to annoy and terrify your
 friends than by playing the &quot;cursed video&quot; at a time you schedule without their knowing?</p>
<p>This application will use a library from Managed DirectX to play the video.&nbsp; If you haven't already, grab the full
<a href="http://msdn2.microsoft.com/en-us/directx/Aa937789.aspx" target="_blank">
DirectX SDK</a> and install.&nbsp; Note that we will be creating a dependency on DirectX, so the victim's PC will need to have DirectX 9.0c installed.&nbsp; Almost every XP desktop has it installed at this point, but be sure to test the app on the target PC.&nbsp; Additionally,
 I have had mixed success drawing a semi-transparent video with every method I've tried (DX, WPF, etc.).&nbsp; It is very dependent on video drivers, so the intended effect may not be perfect on all PCs.&nbsp; Again, be sure to test.</p>
<p>Next, create a new C#/VB Windows Application project and set references to the Microsoft.DirectX and Microsoft.DirectX.AudioVideoPlayback assemblies as shown:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/image.png"><img height="160" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/image_thumb.png" width="332" border="0"></a>
</p>
<p>Next, we need to make some modifications to the form.&nbsp; The video will be played at 50% transparency against the victim's desktop, which gives a very creepy effect.&nbsp; The form should also be hidden from view until the video is ready to be played at the selected
 time.&nbsp; To do this, set the following properties on the form:</p>
<table cellspacing="0" cellpadding="2" width="400" border="1">
<tbody>
<tr>
<td valign="top" width="200"><strong>Property</strong></td>
<td valign="top" width="200"><strong>Value</strong></td>
</tr>
<tr>
<td valign="top" width="200">BackColor</td>
<td valign="top" width="200">Fuchsia</td>
</tr>
<tr>
<td valign="top" width="200">FormBorderStyle</td>
<td valign="top" width="200">None</td>
</tr>
<tr>
<td valign="top" width="200">WindowState</td>
<td valign="top" width="200">Minimized</td>
</tr>
<tr>
<td valign="top" width="200">Opacity</td>
<td valign="top" width="200">50%</td>
</tr>
<tr>
<td valign="top" width="200">ShowInTaskbar</td>
<td valign="top" width="200">False</td>
</tr>
<tr>
<td valign="top" width="200">TopMost</td>
<td valign="top" width="200">True</td>
</tr>
<tr>
<td valign="top" width="200">TransparencyKey</td>
<td valign="top" width="200">Fuchsia</td>
</tr>
</tbody>
</table>
<p>Next, we need to provide a surface onto which the video can be drawn.&nbsp; Drop a <strong>
PictureBox</strong> control onto the form and set its properties as follows:</p>
<table cellspacing="0" cellpadding="2" width="400" border="1">
<tbody>
<tr>
<td valign="top" width="200"><strong>Property</strong></td>
<td valign="top" width="200"><strong>Value</strong></td>
</tr>
<tr>
<td valign="top" width="200">BackColor</td>
<td valign="top" width="200">Fuchsia</td>
</tr>
<tr>
<td valign="top" width="200">Dock</td>
<td valign="top" width="200">Fill</td>
</tr>
</tbody>
</table>
<p>Now we need a method which will play the video.&nbsp; Bring in the <strong>Microsoft.DirectX.AudioVideoPlayback</strong> namespace with the using/Imports keyword and then add the following method to the form:</p>
<p><strong>C#</strong></p>
<span id="c4fmetadata">
<div>
<pre><span>using</span> Microsoft.DirectX.AudioVideoPlayback;

...

Video _video;

<span>public</span> <span>void</span> StartShow()
{
    <span>// create a new video from a filename</span>
    <span>this</span>._video = Video.FromFile(<span>&quot;ring.wmv&quot;</span>);

    <span>// set the drawable surface to the picturebox</span>
    <span>this</span>._video.Owner = pictureBox1;

    <span>// setup an event handler so we can pop up a msgbox when the video is over</span>
    <span>this</span>._video.Ending &#43;= <span>new</span> EventHandler(video_Ending);

    <span>// play it!</span>
    <span>this</span>._video.Play();
}

<span>void</span> video_Ending(<span>object</span> sender, EventArgs e)
{
    <span>// called when the video ends</span>
    MessageBox.Show(<span>&quot;Happy Halloween!&quot;</span>);
    <span>this</span>.Close();
}</pre>
</div>
</span>
<p><strong>VB</strong></p>
<div>
<pre><span>Imports</span> Microsoft.DirectX.AudioVideoPlayback

...

<span>Private</span> _video <span>As</span> Video

<span>Public</span> <span>Sub</span> StartShow()
    <span>' create a new video from a filename</span>
    <span>Me</span>._video = Video.FromFile(<span>&quot;ring.wmv&quot;</span>)

    <span>' set the drawable surface to the picturebox</span>
    <span>Me</span>._video.Owner = pictureBox1

    <span>' setup an event handler so we can pop up a msgbox when the video is over</span>
    <span>AddHandler</span> _video.Ending, <span>AddressOf</span> video_Ending

    <span>' play it!</span>
    <span>Me</span>._video.Play()
<span>End</span> <span>Sub</span>

<span>Private</span> <span>Sub</span> video_Ending(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs)
    <span>' called when the video ends</span>
    MessageBox.Show(<span>&quot;Happy Halloween!&quot;</span>)
    <span>Me</span>.Close()
<span>End</span> Sub</pre>
</div>
<p>This simply creates a new <strong>Video</strong> object by loading a specific filename (ring.wmv), then assigns the video's
<strong>Owner</strong> property to the <strong>PictureBox</strong>, which is where the video will be drawn.&nbsp; Next, an event is setup so we are notified when the clip has ended, and finally, the video is played with the
<strong>Play</strong> method.</p>
<p>The <strong>video_Ending</strong> event handler displays a message box and closes down the application.</p>
<p><strong>x86/x64</strong></p>
<p>The Managed DirectX assemblies are compiled to run in x86 mode only.&nbsp; If you are compiling the application on an x64 OS, you will have to ensure that the main application is built as an x86 target.&nbsp; To do so, choose
<strong>Configuration Manager</strong> from the build menu.&nbsp; In the dialog that appears, choose
<strong>&lt;New...&gt;</strong> from the <strong>Active solution platform</strong> drop down:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/new.png"><img height="310" alt="new" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/new_thumb.png" width="494" border="0"></a>
</p>
<p>Finally, choose <strong>x86</strong> from the <strong>Type or select the new platform</strong> drop down:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/x86.png"><img height="229" alt="x86" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/x86_thumb.png" width="353" border="0"></a>
</p>
<p>Get back to the project and rebuild and you will have an x86-native application which will run successfully on both x86 and x64 platforms.</p>
<h5></h5>
<h5>Config/Test/Scheduler</h5>
<p>The code which handles the configuration, scheduling and testing will be the same for both of these applications, so please jump to that section by clicking
<a href="#scheduler">here</a>.</p>
<p>&nbsp;</p>
<h3>Application #2 - The Shining</h3>
<p>If you have seen <a href="http://www.imdb.com/title/tt0081505/" target="_blank">
The Shining</a>, you can probably guess where this one is heading, too.&nbsp; The basic plot is that an author and his family retreat to an isolated hotel for the winter, and some paranormal activity causes the father to go a bit insane, among other things.&nbsp; In
 the film, as the author goes crazy, he starts typing &quot;All work and no play makes Jack a dull boy&quot; over and over again on the typewriter.&nbsp; So, this application will mimic that by, at the appointed time, popping up an instance of Notepad and having the computer
 type the phrase over and over again on its own.</p>
<p>Once again, create a new VB/C# Windows Application project.&nbsp; As with the previous project, we want the main form to be hidden, but this time, it should be hidden at all times.&nbsp; So, set the form properties as follows:</p>
<table cellspacing="0" cellpadding="2" width="402" border="1">
<tbody>
<tr>
<td valign="top" width="200"><strong>Property</strong></td>
<td valign="top" width="200"><strong>Value</strong></td>
</tr>
<tr>
<td valign="top" width="200">FormBorderStyle</td>
<td valign="top" width="200">None</td>
</tr>
<tr>
<td valign="top" width="200">WindowState</td>
<td valign="top" width="200">Minimized</td>
</tr>
<tr>
<td valign="top" width="200">ShowInTaskbar</td>
<td valign="top" width="200">False</td>
</tr>
<tr>
<td valign="top" width="200">Size</td>
<td valign="top" width="200">10, 10</td>
</tr>
</tbody>
</table>
<p>Next, drag a timer onto the form named <strong>tmrType</strong> and create an event handler for the
<strong>Tick</strong> event which we will fill in later.</p>
<p>Create a method named <strong>StartShow</strong> as follows:</p>
<p><strong>C#</strong></p>
<div>
<pre><span>using</span> System.Diagnostics;
...

<span>private</span> Process _process;

<span>public</span> <span>void</span> StartShow()
{
    _process = Process.Start(<span>&quot;notepad.exe&quot;</span>);
    tmrType.Start();
}</pre>
</div>
<p><strong>VB</strong></p>
<div>
<pre><span>Imports</span> System.Diagnostics

...

<span>' the Notepad process</span>
<span>Private</span> _process <span>As</span> Process

<span>Public</span> <span>Sub</span> StartShow()
    _process = Process.Start(<span>&quot;notepad.exe&quot;</span>)
    tmrType.Start()
<span>End</span> Sub</pre>
</div>
<p>This code starts an instance of Notepad and then starts the <strong>tmrType</strong> ticking.&nbsp; That tick event will send the appropriate letter to the Notepad window from the phrase:</p>
<p><strong>C#</strong></p>
<div>
<pre><span>using</span> System.Runtime.InteropServices;

...

[DllImport(<span>&quot;user32&quot;</span>)]
<span>public</span> <span>static</span> <span>extern</span> <span>int</span> SetForegroundWindow(IntPtr hwnd);

<span>// counter variables</span>
<span>private</span> <span>int</span> i, j;

<span>// the message to type out</span>
<span>private</span> <span>const</span> <span>string</span> msg = <span>&quot;All work and no play makes Jack a dull boy.&quot;</span>;

...

<span>private</span> <span>void</span> tmrType_Tick(<span>object</span> sender, EventArgs e)
{
    <span>// make sure the Notepad window is at the front</span>
    SetForegroundWindow(_process.MainWindowHandle);

    <span>// send the next letter to the window</span>
    <span>if</span>(i &lt; msg.Length)
        SendKeys.Send(msg[i&#43;&#43;].ToString());
    <span>else</span>
    {
        <span>// send a carriage return if we're at the end of the line</span>
        SendKeys.Send(<span>&quot;{ENTER}&quot;</span>);

        <span>// write the line 5 times</span>
        <span>if</span>(&#43;&#43;j &lt; 5)
            i = 0;
        <span>else</span>
        {
            <span>// when done, stop the timer, display the msgbox and close it up</span>
            tmrType.Stop();
            MessageBox.Show(<span>&quot;Happy Halloween!&quot;</span>);
            <span>this</span>.Close();
        }
    }
}</pre>
</div>
<p><strong>VB</strong></p>
<div>
<pre><span>Imports</span> System.Runtime.InteropServices

...

&lt;DllImport(<span>&quot;user32&quot;</span>)&gt; _
<span>Public</span> <span>Shared</span> <span>Function</span> SetForegroundWindow(<span>ByVal</span> hwnd <span>As</span> IntPtr) <span>As</span> <span>Integer</span>
<span>End</span> <span>Function</span>

<span>' counter variables</span>
<span>Private</span> i, j <span>As</span> <span>Integer</span>

<span>' the message to type out</span>
<span>Private</span> <span>Const</span> msg <span>As</span> <span>String</span> = <span>&quot;All work and no play makes Jack a dull boy.&quot;</span>

<span>Private</span> <span>Sub</span> tmrType_Tick(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> tmrType.Tick
    <span>' make sure the Notepad window is at the front</span>
    SetForegroundWindow(_process.MainWindowHandle)

    <span>' send the next letter to the window</span>
    <span>If</span> i &lt; msg.Length <span>Then</span>
        SendKeys.Send(msg.Chars(i).ToString())
        i &#43;= 1
    <span>Else</span>
        <span>' send a carriage return if we're at the end of the line</span>
        SendKeys.Send(<span>&quot;{ENTER}&quot;</span>)

        <span>' write the line 5 times</span>
        j = j &#43; 1
        <span>If</span> j &lt; 5 <span>Then</span>
            i = 0
        <span>Else</span>
            <span>' when done, stop the timer, display the msgbox and close it up</span>
            tmrType.<span>Stop</span>()
            MessageBox.Show(<span>&quot;Happy Halloween!&quot;</span>)
            <span>Me</span>.Close()
        <span>End</span> <span>If</span>
    <span>End</span> <span>If</span>
<span>End</span> Sub</pre>
</div>
<p>At the start of the tick, a call is made to the Win32 API function <strong>SetForegroundWindow</strong>, passing in the window handle (<strong>_process.MainWindowHandle</strong>) of the Notepad process.&nbsp; This ensures that the Notepad window is focused before
 we send the next letter to the window using the <strong>SendKeys</strong> method.&nbsp; When the end of the phrase is reached, a carriage return is sent using
<strong>SendKeys</strong> and the string <strong>{ENTER}</strong>.&nbsp; This repeats 5 times at which point the timer is stopped, the message box is displayed, and the application closes.</p>
<p>&nbsp;</p>
<h3></h3>
<h3><a name="scheduler">The Scheduler</a></h3>
<p>The final piece is to setup a time at which the effect will display on the victim's PC.&nbsp; Create a simple dialog box with a
<strong>DateTimePicker</strong> control that allows the choosing of the appropriate date/time to run:</p>
<p><img height="136" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/image_3.png" width="234" border="0">
</p>
<p>Next, create a new application setting named <strong>Time</strong> as shown:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/image_4.png"><img height="114" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773776/image_thumb_3.png" width="494" border="0"></a>
</p>
<p>Next, setup the events on the <strong>Configuration</strong> form as follows:</p>
<p><strong>C#</strong></p>
<div>
<pre><span>private</span> <span>void</span> ConfigForm_Load(<span>object</span> sender, EventArgs e)
{
    <span>// if no time has been specified, show today's date, otherwise, show the date previously selected</span>
    <span>if</span>(Properties.Settings.Default.Time == DateTime.MinValue)
        dateTimePicker1.Value = DateTime.Now.Date;
    <span>else</span>
        dateTimePicker1.Value = Properties.Settings.Default.Time;
}

<span>private</span> <span>void</span> btnSave_Click(<span>object</span> sender, EventArgs e)
{
    <span>// save the currently selected date/time to the Settings collection</span>
    Properties.Settings.Default.Time = dateTimePicker1.Value;

    Properties.Settings.Default.Save();

    <span>// tell the user what's up</span>
    MessageBox.Show(<span>&quot;Date and time saved.  When you click OK, the application will continue running and the show will start upon the specified date and time.  If you wish to reset the date/time, restart the application with the '-config' switch.&quot;</span>, <span>&quot;Configuration updated&quot;</span>, MessageBoxButtons.OK, MessageBoxIcon.Information);

    <span>// close it up</span>
    <span>this</span>.DialogResult = DialogResult.OK;
    <span>this</span>.Close();
}

<span>private</span> <span>void</span> btnCancel_Click(<span>object</span> sender, EventArgs e)
{
    <span>// close it up</span>
    <span>this</span>.DialogResult = DialogResult.Cancel;
    <span>this</span>.Close();
}
</pre>
</div>
<p><strong>VB</strong></p>
<div>
<pre><span>Private</span> <span>Sub</span> ConfigForm_Load(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> <span>MyBase</span>.Load
    <span>' if no time has been specified, show today's date, otherwise, show the date previously selected</span>
    <span>If</span> My.Settings.<span>Default</span>.Time = DateTime.MinValue <span>Then</span>
        dateTimePicker1.Value = DateTime.Now.<span>Date</span>
    <span>Else</span>
        dateTimePicker1.Value = My.Settings.<span>Default</span>.Time
    <span>End</span> <span>If</span>
<span>End</span> <span>Sub</span>

<span>Private</span> <span>Sub</span> btnSave_Click(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> btnSave.Click
    <span>' save the currently selected date/time to the Settings collection</span>
    My.Settings.<span>Default</span>.Time = dateTimePicker1.Value

    My.Settings.<span>Default</span>.Save()

    <span>' tell the user what's up</span>
    MessageBox.Show(<span>&quot;Date and time saved.  When you click OK, the application will continue running and the show will start upon the specified date and time.  If you wish to reset the date/time, restart the application with the '-config' switch.&quot;</span>, <span>&quot;Configuration updated&quot;</span>, MessageBoxButtons.OK, MessageBoxIcon.Information)

    <span>' close it up</span>
    <span>Me</span>.DialogResult = System.Windows.Forms.DialogResult.OK
    <span>Me</span>.Close()
<span>End</span> <span>Sub</span>

<span>Private</span> <span>Sub</span> btnCancel_Click(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> btnCancel.Click
    <span>' close it up</span>
    <span>Me</span>.DialogResult = System.Windows.Forms.DialogResult.Cancel
    <span>Me</span>.Close()
<span>End</span> Sub</pre>
</div>
<p>The code loads the current value at start (if it exists), saves it when the <strong>
Save</strong> button is clicked, and does nothing when <strong>Cancel</strong> is clicked.</p>
<p>Back on the main form of either application, drag and drop a timer control named
<strong>tmrScheduler</strong> to the main design surface.&nbsp; Set the properties as follows:</p>
<table cellspacing="0" cellpadding="2" width="400" border="1">
<tbody>
<tr>
<td valign="top" width="200"><strong>Property</strong></td>
<td valign="top" width="200"><strong>Value</strong></td>
</tr>
<tr>
<td valign="top" width="200">Enabled</td>
<td valign="top" width="200">True</td>
</tr>
<tr>
<td valign="top" width="200">Interval</td>
<td valign="top" width="200">60000</td>
</tr>
</tbody>
</table>
<p>This will start the timer immediately and call the <strong>Tick</strong> event once every minute.&nbsp; That event will check to see whether the requested time has passed and, if so, starts the show:</p>
<p><strong>C# - Cursed Video</strong></p>
<div>
<pre><span>private</span> <span>void</span> tmrScheduler_Tick(<span>object</span> sender, EventArgs e)
{
    <span>// if the current time is greater than the time set by the user</span>
    <span>if</span>(DateTime.Now &gt;= Properties.Settings.Default.Time)
    {
        <span>// bring up the window</span>
        <span>this</span>.WindowState = FormWindowState.Maximized;

        <span>// disable this timer</span>
        tmrScheduler.Enabled = <span>false</span>;

        <span>// bring it to the top</span>
        <span>this</span>.BringToFront();

        <span>// play the movie</span>
        StartShow();
    }
}</pre>
</div>
<p><strong>VB - Cursed Video</strong></p>
<div>
<pre><span>Private</span> <span>Sub</span> tmrScheduler_Tick(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> tmrScheduler.Tick
    <span>' if the current time is greater than the time set by the user</span>
    <span>If</span> DateTime.Now &gt;= My.Settings.<span>Default</span>.Time <span>Then</span>
        <span>' bring up the window</span>
        <span>Me</span>.WindowState = FormWindowState.Maximized

        <span>' disable this timer</span>
        tmrScheduler.Enabled = <span>False</span>

        <span>' bring it to the top</span>
        <span>Me</span>.BringToFront()

        <span>' play the movie</span>
        StartShow()
    <span>End</span> <span>If</span>
<span>End</span> Sub</pre>
</div>
<p><strong>C# - The Shining</strong></p>
<div>
<pre><span>private</span> <span>void</span> tmrScheduler_Tick(<span>object</span> sender, EventArgs e)
{
    <span>// if the current time is greater than the time set by the user</span>
    <span>if</span>(DateTime.Now &gt;= Properties.Settings.Default.Time)
    {
        <span>// disable this timer</span>
        tmrScheduler.Enabled = <span>false</span>;

        <span>// start typing</span>
        StartShow();
    }
}</pre>
</div>
<p><strong>VB - The Shining</strong></p>
<div>
<pre><span>Private</span> <span>Sub</span> tmrScheduler_Tick(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs) <span>Handles</span> tmrScheduler.Tick
    <span>' if the current time is greater than the time set by the user</span>
    <span>If</span> DateTime.Now &gt;= My.Settings.<span>Default</span>.Time <span>Then</span>
        <span>' disable this timer</span>
        tmrScheduler.Enabled = <span>False</span>

        <span>' start typing</span>
        StartShow()
    <span>End</span> <span>If</span>
<span>End</span> Sub</pre>
</div>
<h3>Configuration/Testing</h3>
<p>To make it easy to reset the launch time, and to test the effect without scheduling it, two command line parameters can be added to
<strong>Program.cs/vb</strong> to re-run the configuration or test.&nbsp; Add the following code prior to the call to
<strong>Application.Run:</strong></p>
<p><strong>C#</strong></p>
<div>
<pre><span>// test the effect</span>
<span>if</span>(Environment.CommandLine.IndexOf(<span>&quot;test&quot;</span>) &gt; -1)
{
    Form1 f = <span>new</span> Form1();
    f.StartShow();
    f.ShowDialog();
    <span>return</span>;
}

<span>// if we haven't set the time, or the user requested the config dialog, display it</span>
<span>if</span>(Properties.Settings.Default.Time == DateTime.MinValue || Environment.CommandLine.IndexOf(<span>&quot;config&quot;</span>) &gt; -1)
{
    <span>if</span>(<span>new</span> ConfigForm().ShowDialog() == DialogResult.Cancel)
        <span>return</span>;
}</pre>
</div>
<p><strong>VB</strong></p>
<strong></strong>
<div>
<pre><span>' test the effect</span>
<span>If</span> Environment.CommandLine.IndexOf(<span>&quot;test&quot;</span>) &gt; -1 <span>Then</span>
    <span>Dim</span> f <span>As</span> Form1 = <span>New</span> Form1()
    f.StartShow()
    f.ShowDialog()
    <span>Return</span>
<span>End</span> <span>If</span>

<span>' if we haven't set the time, or the user requested the config dialog, display it</span>
<span>If</span> My.Settings.<span>Default</span>.Time = DateTime.MinValue <span>OrElse</span> Environment.CommandLine.IndexOf(<span>&quot;config&quot;</span>) &gt; -1 <span>Then</span>
    <span>If</span> <span>New</span> ConfigForm().ShowDialog() = DialogResult.Cancel <span>Then</span>
        <span>Return</span>
    <span>End</span> <span>If</span>
<span>End</span> If</pre>
</div>
<p>If <strong>-test</strong> is passed on the command line, the form is created and the show is started.&nbsp; If
<strong>-config</strong> is passed on the command line, the Configuration dialog is displayed and the application continues as it would the first time it ran.</p>
<h3><strong></strong></h3>
<h3>Deployment</h3>
<p><strong>Cursed Video</strong></p>
<p>Copy the exe, <strong>Microsoft.DirectX</strong> and <strong>Microsoft.DirectX.AudioVideoPlayback</strong> to a folder on the user's PC along with a video clip named
<strong>ring.wmv</strong>.&nbsp; Of course, you can replace that video clip with any clip of your choosing, though if you wish to use a different filename, you will have to change the code and recompile.</p>
<p><strong>The Shining</strong></p>
<p>Copy the exe to a folder on the user's PC.</p>
<p>&nbsp;</p>
<p>For either, create a shortcut to it in the Startup program group, or set it up to run via the registry using the following key for the logged in user:
</p>
<ul>
<li>HKCU\Software\Microsoft\Windows\CurrentVersion\Run</li></ul>
<p>Simply create a new string key with any Name, and a Data value of the path to the executable.
</p>
<p>Next, start the application once on their PC to setup the date and time for the show to begin. Once that is done, the application will remain running in the background. If the PC is restarted, and the application is setup to run at startup as described above,
 it will start silently and remain running, waiting for the date and time specified.
</p>
<h3>Summary</h3>
<p>Two Halloween applications for the price of one.&nbsp; Not that you paid for either.&nbsp; Be sure to have fun with them this Halloween and disturb anyone you can.&nbsp; Enjoy!</p>
<h3>Thanks</h3>
<p>Thanks to Giovanni Montrone for testing out these applications during development.</p>
<h3>Bio</h3>
<p>Brian is a Microsoft C# MVP and a recognized .NET expert with over 6 years experience developing .NET solutions, and over 9 years of professional experience architecting and developing solutions using Microsoft technologies and platforms, although he has
 been &quot;coding for fun&quot; for as long as he can remember.&nbsp; Outside the world of .NET and business applications, Brian enjoys developing both hardware and software projects in the areas of gaming, robotics, and whatever else strikes his fancy for the next ten minutes.
 He rarely passes up an opportunity to dive into a C/C&#43;&#43; or assembly language project.&nbsp; You can reach Brian via his blog at
<a href="http://www.brianpeek.com/">http://www.brianpeek.com/</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:d6ad859429a74dd7b4a39e7600d1b812">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Possessed-PC-Pranks-for-Halloween</comments>
      <itunes:summary>





In this application, Brian Peek demonstrates how to create two spooky Halloween applications to trick your friends and colleagues.



Brian Peek
ASPSOFT, Inc.

Difficulty: Easy
Time Required: 
Less than 1 hour
Cost: Free
Software: Visual Basic or Visual C# Express Editions,

DirectX SDK (for application #1)
Hardware: None
Download: Download





&amp;nbsp; 
Introduction
Last year I wrote two articles on how to annoy your friends and family by 
dripping blood down their computer screen, or by 
squirting them with (hopefully) fake blood from (even more hopefully) a fake skull.&amp;nbsp; Halloween is just around the corner, so here are two more applications which you can use to further bother the people around you. 
&amp;nbsp; 
Application #1 - Cursed Video
If you have ever seen the horror film 
The Ring, then you can likely guess the basic premise of this application.&amp;nbsp; For those that haven&#39;t, the film is about a video tape which, when watched, will cause the viewer to die within a week of viewing it.&amp;nbsp; So, what better way to annoy and terrify your
 friends than by playing the &amp;quot;cursed video&amp;quot; at a time you schedule without their knowing? 
This application will use a library from Managed DirectX to play the video.&amp;nbsp; If you haven&#39;t already, grab the full

DirectX SDK and install.&amp;nbsp; Note that we will be creating a dependency on DirectX, so the victim&#39;s PC will need to have DirectX 9.0c installed.&amp;nbsp; Almost every XP desktop has it installed at this point, but be sure to test the app on the target PC.&amp;nbsp; Additionally,
 I have had mixed success drawing a semi-transparent video with every method I&#39;ve tried (DX, WPF, etc.).&amp;nbsp; It is very dependent on video drivers, so the intended effect may not be perfect on all PCs.&amp;nbsp; Again, be sure to test. 
Next, create a new C#/VB Windows Application project and set references to the Microsoft.DirectX and Microsoft.DirectX.AudioVideoPlayback assemblies as shown: 

 
Next, we need to make some modifications</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Possessed-PC-Pranks-for-Halloween</link>
      <pubDate>Mon, 29 Oct 2007 22:03:21 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Possessed-PC-Pranks-for-Halloween</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5773776_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5773776_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>5</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Possessed-PC-Pranks-for-Halloween/RSS</wfw:commentRss>
      <category>Halloween</category>
      <category>Windows</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>April Fool&#39;s Day with Bouncy Balls</title>
      <description><![CDATA[
<p>&nbsp;</p>
<span>
<table class="" cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td class="" width="50"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_24658.jpg"><img height="37" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2465_thumb6.jpg" width="50" border="0"></a>
</td>
<td class=""><span class="entry_description">In this article, Clint Rutkas builds a relay application that will drop 1,000 super bouncy balls from the ceiling as an April Fools gag!
</span></td>
</tr>
<tr>
<td class="" colspan="2">
<div class="entry_author">Clint Rutkas</div>
<div class="entry_company"><a href="http://www.betterthaneveryone.com/">Better Than Everyone</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
3-6 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">$100-$200</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Basic or Visual C# Express Editions</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"><a href="http://www.controlanything.com/Merchant2/merchant.mvc?Screen=CTGY&amp;Store_Code=NCD&amp;Category_Code=USB_Devices">Control Anything USB Relay Board</a>, a drill, a ton of super
 bouncy balls and some zippie ties</span></div>
<div class="entry_details"><b>Download: </b><a class="" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/AprilFools.zip">Download</a></div>
</td>
</tr>
</tbody>
</table>
</span>
<div class="entry_details">&nbsp;</div>
<h3>Introduction</h3>
<p>I'm tend to go a bit crazy when it comes to pranks.&nbsp; April Fool's day is almost like Christmas to me.&nbsp; So&nbsp;bombarding someone with&nbsp;1,000 super bouncy balls seemed like the proper thing to do come the first possible moment.</p>
<p>But that someone was a bit harder than I thought.&nbsp; I needed a victim however&nbsp;but with how
<a href="http://www.springcm.com/">SpringCM's</a> executive offices are designed, I quickly found him.&nbsp; My victim for this task is my CTO, Dave Dahl.&nbsp; I wasn't alone in this prank, I had my friend / co-worker,
<a href="http://andy.cindercube.org/">Andy Konkol</a>, help out with the final assembly and testing of the application.</p>
<p>Here is the <a href="http://www.youtube.com/watch?v=1IflN4daL8w">video of the final outcome over at YouTube</a>.</p>
<h3><b>The Prank Setup</b></h3>
<p>You need a laptop, a rigging system, a WiFi network, a ton of bouncy balls, a drill, a spare ceiling tile, some string&nbsp;and a relay board.&nbsp; Here is the picture of the system finally done.&nbsp; The ceiling tile was modified with the sides shaved and gluing a piece
 of wood to the back to apply anchors into.&nbsp; To figure out how to wire up relay boards, I suggest reading
<a href="http://msdn.microsoft.com/coding4fun/events/holidays/article.aspx?articleid=1230660&amp;title=Animated&#43;Musical&#43;Holiday&#43;Light&#43;Show">
Brian Peek's holiday lighting article</a>.&nbsp; Brian provides diagrams and wiring safety information.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_24852.jpg"></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_24962.jpg"><img height="300" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2496_thumb.jpg" width="400" border="0"></a></p>
<p>And we mustn't forget the balls.&nbsp; How does one buy super bouncy balls?&nbsp; It was surprisingly simple with Google and searching for &quot;Super Bouncy balls&quot;.&nbsp; I got mine from
<a href="http://www.gumball-machine.com/bouncy-balls.html">Gumball Machine Warehouse</a>&nbsp;for about $70 if memory serves.&nbsp; Each bag weights about 5 pounds I'd guess and is about a foot by a foot.&nbsp; Apply them gingerly onto the shaven tile since it isn't supported
 by the orginal 1/4&quot; lip anymore.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2465_thumb53.jpg"><img height="300" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2465_thumb5_thumb.jpg" width="400" border="0"></a></p>
<p>Andy Konkol admiring the release rig.&nbsp; You can see we've mounted the drill to the fire system.&nbsp; You'll also notice the drill's trigger is tied down so all we need to do is hit the relay and the drill will be on.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_24872.jpg"><img height="300" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2487_thumb.jpg" width="400" border="0"></a></p>
<p>So as every good programmer knows is to test often, and as this picture shows, it is well earned.&nbsp; Cleaning up the mess took about five minutes.&nbsp; A video of this
<a href="http://www.youtube.com/watch?v=BXt0KX210tU">test can be found over on YouTube</a>.&nbsp; Since we didn't know how much it would hurt or cause damage, a human test subject was needed.&nbsp; I stepped up to plate and had the crap freaked out of myself even knowing
 the balls were going to be deployed.</p>
<p><img height="300" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/IMG_2485_thumb.jpg" width="400" border="0"></p>
<h3><strong>The Application</strong></h3>
<p>The application is fairly simple and uses a Control Anything USB relay board and has a laptop placed on a ceiling tile.&nbsp; The laptop was left on and with Remote Desktop Connection, the application will be triggered.</p>
<p><img height="294" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2004038/application4.png" width="300">
</p>
<h3>Relay Code</h3>
<p>I'm using the relay board for another project so&nbsp;currently it is a&nbsp;fairly simple codebase.&nbsp; This application was the test bed for the next project.&nbsp; How the relay board works is by sending a sequence of commands.&nbsp; 254 will prepare for a command, 29 then
 will turn all the relays off, 30 on.&nbsp; The Control Anything relay board has a host of other features I haven't had time yet to implement but will soon so you can check back for a richer API for the relay board.&nbsp; The company does provide Visual Basic 6 code
 examples and uses the chr$ command instead of a byte array.</p>
<p><strong>C#</strong></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">bool</span> AllRelaysOff()
{
    ComPort.WriteBuffer(<span class="kwrd">new</span> <span class="kwrd">byte</span>[] { 254, 29 });
    <span class="kwrd">return</span> relaySuccess();
}

<span class="kwrd">public</span> <span class="kwrd">bool</span> AllRelaysOn()
{
    ComPort.WriteBuffer(<span class="kwrd">new</span> <span class="kwrd">byte</span>[] { 254, 30 });
    <span class="kwrd">return</span> relaySuccess();
}

<span class="kwrd">private</span> <span class="kwrd">bool</span> relaySuccess()
{
    <span class="kwrd">return</span> (ComPort.ReadBufferChar() == 85);
}</pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>VB</strong></p>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Function</span> AllRelaysOff() <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
    ComPort.WriteBuffer(<span class="kwrd">New</span> <span class="kwrd">Byte</span>() {254, 29})
    <span class="kwrd">Return</span> relaySuccess()
<span class="kwrd">End</span> <span class="kwrd">Function</span>

<span class="kwrd">Public</span> <span class="kwrd">Function</span> AllRelaysOn() <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
    ComPort.WriteBuffer(<span class="kwrd">New</span> <span class="kwrd">Byte</span>() {254, 30})
    <span class="kwrd">Return</span> relaySuccess()
<span class="kwrd">End</span> <span class="kwrd">Function</span>

<span class="kwrd">Private</span> <span class="kwrd">Function</span> relaySuccess() <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
    <span class="kwrd">Return</span> (ComPort.ReadBufferChar = 85)
<span class="kwrd">End</span> Function</pre>
<p>&nbsp;</p>
<h3>Comport</h3>
<p>The comport code is actually a slightly&nbsp;refractored version from my <a href="http://msdn.microsoft.com/coding4fun/hardware/article.aspx?articleid=918683&amp;title=That's&#43;Totally&#43;Disco">
dance floor application</a>.&nbsp;&nbsp;The class itself is a wrapper for the .Net <strong>
SerialPort </strong>object which can be found in <strong>System.IO.Ports</strong>.&nbsp; Furthermore, it&nbsp;now inherits off
<strong>IDisposable</strong> to help auto close the serial port and is designed aimed to help ease use for multiple applications.</p>
<p><strong>C#</strong></p>
<pre class="csharpcode">    <span class="kwrd">public</span> <span class="kwrd">class</span> ComPortIO : IDisposable
    {
        <span class="preproc">#region</span> varibles
        <span class="kwrd">public</span> SerialPort ComPort 
        {
            get { <span class="kwrd">return</span> _comPort; }
            set { _comPort = <span class="kwrd">value</span>; }
        }
        <span class="kwrd">private</span> SerialPort _comPort;

        <span class="kwrd">public</span> <span class="kwrd">bool</span> DoneWriting
        {
            get { <span class="kwrd">return</span> _doneWriting; }
            set { _doneWriting = <span class="kwrd">value</span>; }
        }
        <span class="kwrd">private</span> <span class="kwrd">bool</span> _doneWriting;

        <span class="kwrd">public</span> <span class="kwrd">bool</span> DisableWriting
        {
            get { <span class="kwrd">return</span> _disableWriting; }
            set { _disableWriting = <span class="kwrd">value</span>; }
        }
        <span class="kwrd">private</span> <span class="kwrd">bool</span> _disableWriting;
        <span class="preproc">#endregion</span>

        <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()
        {
            <span class="kwrd">if</span> (ComPort.IsOpen)
                ComPort.Close();
        }

        <span class="preproc">#region</span> constructors
        <span class="kwrd">public</span> ComPortIO(<span class="kwrd">string</span> ComPortName, <span class="kwrd">int</span> BaudRate, <span class="kwrd">bool</span> DisableComWriting)
        {
            DisableWriting = DisableComWriting;

            <span class="kwrd">if</span> (!DisableWriting)
            {
                <span class="kwrd">if</span> (!doesPortExist(ComPortName))
                    <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">&quot;The serial port used is not valid&quot;</span>, ComPortName);

                ComPort = <span class="kwrd">new</span> SerialPort(ComPortName, BaudRate, Parity.None, 8, StopBits.One);

                <span class="kwrd">if</span> (!ComPort.IsOpen)
                    ComPort.Open();

                ComPort.ReadTimeout = 100;
            }
        }
        <span class="preproc">#endregion</span>

        <span class="preproc">#region</span> <span class="kwrd">public</span> functions
        <span class="kwrd">public</span> <span class="kwrd">void</span> WriteBuffer(<span class="kwrd">char</span>[] Buffer)
        {
            <span class="kwrd">if</span> (!DisableWriting)
                ComPort.Write(Buffer, 0, Buffer.Length);
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> WriteBuffer(<span class="kwrd">byte</span>[] Buffer)
        {
            <span class="kwrd">if</span> (!DisableWriting)
                ComPort.Write(Buffer, 0, Buffer.Length);
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> WriteBuffer(<span class="kwrd">string</span> Buffer)
        {
            <span class="kwrd">if</span> (!DisableWriting)
                ComPort.Write(Buffer);
        }

        <span class="kwrd">public</span> <span class="kwrd">string</span> ReadBuffer()
        {
            <span class="kwrd">try</span>
            {
                <span class="kwrd">if</span> (!DisableWriting &amp;&amp; ComPort.IsOpen)
                {
                    <span class="kwrd">return</span> ComPort.ReadLine();
                }
            }
            <span class="kwrd">catch</span> (Exception) { }
            <span class="kwrd">return</span> <span class="kwrd">null</span>;
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> ReadBufferChar()
        {
            <span class="kwrd">try</span>
            {
                <span class="kwrd">if</span> (!DisableWriting &amp;&amp; ComPort.IsOpen)
                {
                    <span class="kwrd">return</span> ComPort.ReadChar();
                }
            }
            <span class="kwrd">catch</span> (Exception) { }
            <span class="kwrd">return</span> -1;
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> ReadBufferByte()
        {
            <span class="kwrd">try</span>
            {
                <span class="kwrd">if</span> (!DisableWriting &amp;&amp; ComPort.IsOpen)
                {
                    <span class="kwrd">return</span> ComPort.ReadByte();
                }
            }
            <span class="kwrd">catch</span> (Exception) { }

            <span class="kwrd">return</span> -1;
        }
        <span class="preproc">#endregion</span>

        <span class="preproc">#region</span> <span class="kwrd">private</span> functions
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> doesPortExist(<span class="kwrd">string</span> ComPortName)
        {
            <span class="kwrd">string</span>[] serialPortNames = SerialPort.GetPortNames();

            <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; serialPortNames.Length; i&#43;&#43;)
            {
                <span class="kwrd">if</span> (<span class="kwrd">string</span>.Compare(serialPortNames[i], ComPortName, <span class="kwrd">true</span>) == 0)
                    <span class="kwrd">return</span> <span class="kwrd">true</span>;
            }
            <span class="kwrd">return</span> <span class="kwrd">false</span>;
        }
        <span class="preproc">#endregion</span>
    }</pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>VB</strong></p>
<div>&nbsp;</div>
<pre class="csharpcode">    <span class="kwrd">Public</span> <span class="kwrd">Class</span> ComPortIO
        <span class="kwrd">Implements</span> IDisposable

        <span class="kwrd">Private</span> _comPort <span class="kwrd">As</span> SerialPort
        <span class="kwrd">Private</span> _doneWriting <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
        <span class="kwrd">Private</span> _disableWriting <span class="kwrd">As</span> <span class="kwrd">Boolean</span>

        <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>(<span class="kwrd">ByVal</span> ComPortName <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> BaudRate <span class="kwrd">As</span> <span class="kwrd">Integer</span>, <span class="kwrd">ByVal</span> DisableComWriting <span class="kwrd">As</span> <span class="kwrd">Boolean</span>)
            <span class="kwrd">MyBase</span>.<span class="kwrd">New</span>()
            DisableWriting = DisableComWriting
            <span class="kwrd">If</span> <span class="kwrd">Not</span> DisableWriting <span class="kwrd">Then</span>
                <span class="kwrd">If</span> <span class="kwrd">Not</span> doesPortExist(ComPortName) <span class="kwrd">Then</span>
                    <span class="kwrd">Throw</span> <span class="kwrd">New</span> ArgumentException(<span class="str">&quot;The serial port used is not valid&quot;</span>, ComPortName)
                <span class="kwrd">End</span> <span class="kwrd">If</span>
                ComPort = <span class="kwrd">New</span> SerialPort(ComPortName, BaudRate, Parity.None, 8, StopBits.One)
                <span class="kwrd">If</span> <span class="kwrd">Not</span> ComPort.IsOpen <span class="kwrd">Then</span>
                    ComPort.Open()
                <span class="kwrd">End</span> <span class="kwrd">If</span>
                ComPort.ReadTimeout = 100
            <span class="kwrd">End</span> <span class="kwrd">If</span>
        <span class="kwrd">End</span> <span class="kwrd">Sub</span>

        <span class="kwrd">Public</span> <span class="kwrd">Property</span> ComPort() <span class="kwrd">As</span> SerialPort
            <span class="kwrd">Get</span>
                <span class="kwrd">Return</span> _comPort
            <span class="kwrd">End</span> <span class="kwrd">Get</span>
            <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> SerialPort)
                _comPort = value
            <span class="kwrd">End</span> <span class="kwrd">Set</span>
        <span class="kwrd">End</span> <span class="kwrd">Property</span>

        <span class="kwrd">Public</span> <span class="kwrd">Property</span> DoneWriting() <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
            <span class="kwrd">Get</span>
                <span class="kwrd">Return</span> _doneWriting
            <span class="kwrd">End</span> <span class="kwrd">Get</span>
            <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> <span class="kwrd">Boolean</span>)
                _doneWriting = value
            <span class="kwrd">End</span> <span class="kwrd">Set</span>
        <span class="kwrd">End</span> <span class="kwrd">Property</span>

        <span class="kwrd">Public</span> <span class="kwrd">Property</span> DisableWriting() <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
            <span class="kwrd">Get</span>
                <span class="kwrd">Return</span> _disableWriting
            <span class="kwrd">End</span> <span class="kwrd">Get</span>
            <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> <span class="kwrd">Boolean</span>)
                _disableWriting = value
            <span class="kwrd">End</span> <span class="kwrd">Set</span>
        <span class="kwrd">End</span> <span class="kwrd">Property</span>

        <span class="kwrd">Public</span> <span class="kwrd">Overloads</span> <span class="kwrd">Sub</span> Dispose() <span class="kwrd">Implements</span> IDisposable.Dispose
            <span class="kwrd">If</span> ComPort.IsOpen <span class="kwrd">Then</span>
                ComPort.Close()
            <span class="kwrd">End</span> <span class="kwrd">If</span>
        <span class="kwrd">End</span> <span class="kwrd">Sub</span>

        <span class="kwrd">Public</span> <span class="kwrd">Overloads</span> <span class="kwrd">Sub</span> WriteBuffer(<span class="kwrd">ByVal</span> Buffer() <span class="kwrd">As</span> <span class="kwrd">Char</span>)
            <span class="kwrd">If</span> <span class="kwrd">Not</span> DisableWriting <span class="kwrd">Then</span>
                ComPort.Write(Buffer, 0, Buffer.Length)
            <span class="kwrd">End</span> <span class="kwrd">If</span>
        <span class="kwrd">End</span> <span class="kwrd">Sub</span>

        <span class="kwrd">Public</span> <span class="kwrd">Overloads</span> <span class="kwrd">Sub</span> WriteBuffer(<span class="kwrd">ByVal</span> Buffer() <span class="kwrd">As</span> <span class="kwrd">Byte</span>)
            <span class="kwrd">If</span> <span class="kwrd">Not</span> DisableWriting <span class="kwrd">Then</span>
                ComPort.Write(Buffer, 0, Buffer.Length)
            <span class="kwrd">End</span> <span class="kwrd">If</span>
        <span class="kwrd">End</span> <span class="kwrd">Sub</span>

        <span class="kwrd">Public</span> <span class="kwrd">Overloads</span> <span class="kwrd">Sub</span> WriteBuffer(<span class="kwrd">ByVal</span> Buffer <span class="kwrd">As</span> <span class="kwrd">String</span>)
            <span class="kwrd">If</span> <span class="kwrd">Not</span> DisableWriting <span class="kwrd">Then</span>
                ComPort.Write(Buffer)
            <span class="kwrd">End</span> <span class="kwrd">If</span>
        <span class="kwrd">End</span> <span class="kwrd">Sub</span>

        <span class="kwrd">Public</span> <span class="kwrd">Function</span> ReadBuffer() <span class="kwrd">As</span> <span class="kwrd">String</span>
            <span class="kwrd">Try</span>
                <span class="kwrd">If</span> (<span class="kwrd">Not</span> DisableWriting _
                   <span class="kwrd">AndAlso</span> ComPort.IsOpen) <span class="kwrd">Then</span>
                    <span class="kwrd">Return</span> ComPort.ReadLine
                <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Catch</span>
            <span class="kwrd">End</span> <span class="kwrd">Try</span>
            <span class="kwrd">Return</span> <span class="kwrd">Nothing</span>
        <span class="kwrd">End</span> <span class="kwrd">Function</span>

        <span class="kwrd">Public</span> <span class="kwrd">Function</span> ReadBufferChar() <span class="kwrd">As</span> <span class="kwrd">Integer</span>
            <span class="kwrd">Try</span>
                <span class="kwrd">If</span> (<span class="kwrd">Not</span> DisableWriting _
                   <span class="kwrd">AndAlso</span> ComPort.IsOpen) <span class="kwrd">Then</span>
                    <span class="kwrd">Return</span> ComPort.ReadChar
                <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Catch</span>

            <span class="kwrd">End</span> <span class="kwrd">Try</span>
            <span class="kwrd">Return</span> -1
        <span class="kwrd">End</span> <span class="kwrd">Function</span>

        <span class="kwrd">Public</span> <span class="kwrd">Function</span> ReadBufferByte() <span class="kwrd">As</span> <span class="kwrd">Integer</span>
            <span class="kwrd">Try</span>
                <span class="kwrd">If</span> (<span class="kwrd">Not</span> DisableWriting _
                   <span class="kwrd">AndAlso</span> ComPort.IsOpen) <span class="kwrd">Then</span>
                    <span class="kwrd">Return</span> ComPort.ReadByte
                <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Catch</span>

            <span class="kwrd">End</span> <span class="kwrd">Try</span>
            <span class="kwrd">Return</span> -1
        <span class="kwrd">End</span> <span class="kwrd">Function</span>

        <span class="kwrd">Private</span> <span class="kwrd">Shared</span> <span class="kwrd">Function</span> doesPortExist(<span class="kwrd">ByVal</span> ComPortName <span class="kwrd">As</span> <span class="kwrd">String</span>) <span class="kwrd">As</span> <span class="kwrd">Boolean</span>
            <span class="kwrd">Dim</span> serialPortNames() <span class="kwrd">As</span> <span class="kwrd">String</span> = SerialPort.GetPortNames
            <span class="kwrd">Dim</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0
            <span class="kwrd">Do</span> <span class="kwrd">While</span> (i &lt; serialPortNames.Length)
                <span class="kwrd">If</span> (<span class="kwrd">String</span>.Compare(serialPortNames(i), ComPortName, <span class="kwrd">True</span>) = 0) <span class="kwrd">Then</span>
                    <span class="kwrd">Return</span> <span class="kwrd">True</span>
                <span class="kwrd">End</span> <span class="kwrd">If</span>
                i = (i &#43; 1)
            <span class="kwrd">Loop</span>
            <span class="kwrd">Return</span> <span class="kwrd">False</span>
        <span class="kwrd">End</span> <span class="kwrd">Function</span>
    <span class="kwrd">End</span> Class</pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h3><b>Deployment</b> </h3>
<p>As soon as Dave Dahl sat down, I clicked the drop button and the everything worked like clock work.&nbsp; If you want to see the video, once again it is over at
<a href="http://www.youtube.com/watch?v=1IflN4daL8w">YouTube for your April Fools Day pleasure</a>.
</p>
<h3><b>Summary</b> </h3>
<p>Before you do such a prank, please be sure you your victim will be cool with it so you&nbsp;won't get fired.&nbsp; Thankfully, I wasn't and Dave is cool ... I hope.&nbsp; I wasn't happy totally with our deployment solution since it was partially visible due to the string.&nbsp;
 I'd also like to have had the entire system automated with maybe an IR sensor or a force sensor hidden in the seat.&nbsp; Given a few more weekends and actually planning this prank out a bit more, I think Andy and myself could have come up with a more robust system.&nbsp;</p>
<h3><b>Thanks</b> </h3>
<p>A special thanks to Dave Dahl for being such a good sport&nbsp;and <a href="http://andy.cindercube.org/">
Andy Konkol</a> for helping out.</p>
<h3>Bio</h3>
<p>Clint is an application developer for <a href="http://springcm.com/">SpringCM</a>, an on-demand, web-based document and content management system.&nbsp; His two primary development languages are C# and JavaScript. Prior to the ball drop project, he worked on
 his <a href="http://msdn.microsoft.com/coding4fun/coolapplications/disco/default.aspx">
Disco Dance Floor</a>. In his off time, he whips up other random weird projects and does twenty something activities with his friends. Clint's blog is
<a href="http://betterthaneveryone.com/">betterthaneveryone.com</a> and can be emailed at
<a href="mailto:clint@rutkas.com">clint@rutkas.com</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:bbb7552ede354b2ebe139e7600d4b0d7">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/April-Fools-Day-with-Bouncy-Balls</comments>
      <itunes:summary>
&amp;nbsp; 






In this article, Clint Rutkas builds a relay application that will drop 1,000 super bouncy balls from the ceiling as an April Fools gag!




Clint Rutkas
Better Than Everyone

Difficulty: Intermediate
Time Required: 
3-6 hours
Cost: $100-$200
Software: Visual Basic or Visual C# Express Editions
Hardware: Control Anything USB Relay Board, a drill, a ton of super
 bouncy balls and some zippie ties
Download: Download





&amp;nbsp;
Introduction
I&#39;m tend to go a bit crazy when it comes to pranks.&amp;nbsp; April Fool&#39;s day is almost like Christmas to me.&amp;nbsp; So&amp;nbsp;bombarding someone with&amp;nbsp;1,000 super bouncy balls seemed like the proper thing to do come the first possible moment. 
But that someone was a bit harder than I thought.&amp;nbsp; I needed a victim however&amp;nbsp;but with how
SpringCM&#39;s executive offices are designed, I quickly found him.&amp;nbsp; My victim for this task is my CTO, Dave Dahl.&amp;nbsp; I wasn&#39;t alone in this prank, I had my friend / co-worker,
Andy Konkol, help out with the final assembly and testing of the application. 
Here is the video of the final outcome over at YouTube. 
The Prank Setup
You need a laptop, a rigging system, a WiFi network, a ton of bouncy balls, a drill, a spare ceiling tile, some string&amp;nbsp;and a relay board.&amp;nbsp; Here is the picture of the system finally done.&amp;nbsp; The ceiling tile was modified with the sides shaved and gluing a piece
 of wood to the back to apply anchors into.&amp;nbsp; To figure out how to wire up relay boards, I suggest reading

Brian Peek&#39;s holiday lighting article.&amp;nbsp; Brian provides diagrams and wiring safety information.
 
 
And we mustn&#39;t forget the balls.&amp;nbsp; How does one buy super bouncy balls?&amp;nbsp; It was surprisingly simple with Google and searching for &amp;quot;Super Bouncy balls&amp;quot;.&amp;nbsp; I got mine from
Gumball Machine Warehouse&amp;nbsp;for about $70 if memory serves.&amp;nbsp; Each bag weights about 5 pounds I&#39;d guess and is about a foot by a foot.&amp;nbsp; Apply them gingerly onto the shaven</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/April-Fools-Day-with-Bouncy-Balls</link>
      <pubDate>Mon, 02 Apr 2007 09:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/April-Fools-Day-with-Bouncy-Balls</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2004038_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2004038_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Clint Rutkas</dc:creator>
      <itunes:author>Clint Rutkas</itunes:author>
      <slash:comments>4</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/April-Fools-Day-with-Bouncy-Balls/RSS</wfw:commentRss>
      <category>Robotics</category>
      <category>Holiday</category>
      <category>april fools day</category>
    </item>
  <item>
      <title>I&#39;m a mean one, I&#39;m the Grinch ... by using Amazon Web Services</title>
      <description><![CDATA[
<p>With the aid of Amazon.com web services, <a href="http://www.betterthaneveryone.com/">
Clint Rutkas</a> created a program that will guess what your gift is. With the size of your wrapped present, the program will poll Amazon and based on what is on your wishlist, it will guess what it may be!</p>
<div class="entry_details">&nbsp;</div>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
1-3 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Studio Express Editions</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input">None</span></div>
<div class="entry_details"><b>Download:&nbsp;</b><a class="" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/AmazonWishListCS.zip">C#</a> or
<a class="" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/AmazonWishListVB.zip">Visual Basic</a>&nbsp;
<ul>
</ul>
</div>
<h2>Signing up for the Amazon Web Services</h2>
<p>The first step in using this application is <a href="https://aws-portal.amazon.com/gp/aws/developer/registration/index.html/103-7399647-0537426?">
signing up for the Amazon Web Services</a>.&nbsp; From there you'll get a AWS key that you will use to access the web service for authorization purposes.&nbsp; This key should be 20 characters.</p>
<p><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/amazonFindKey20.gif">
</p>
<h2>Adding the Amazon Web Services to .Net</h2>
<p>The wonderful thing about .Net is how easy it is to add in a Web Service.&nbsp; First you right click on References in your solution.</p>
<p>&nbsp; <img height="228" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/addWebReference14.gif" width="278">
</p>
<p>The next step is adding in the WSDL.&nbsp; Here is the URL for it.</p>
<p><a href="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl">http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl</a>
</p>
<p><img height="492" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/addWebReference25.gif" width="701">
</p>
<h2>Oven is preheating, lets do some work.</h2>
<p>Ok, so now I have the web service added and Visual Studio is all ready to rock the casbah, we need know how to request&nbsp;information. &nbsp;For that, we need documentation.&nbsp; RTFM?&nbsp; Yes, read the manual which is
<a href="http://developer.amazonwebservices.com/connect/servlet/KbServlet/download/495-102-886/ecs-dg-20061114.pdf">
found here (PDF)</a>.&nbsp; After a few quick searches, I found some samples through direct requests.</p>
<p>Here is an example that will return my wishlists.&nbsp; You need to add in insert your key.</p>
<p><a href="http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&amp;AWSAccessKeyId=YOUR_KEY&amp;Operation=ListSearch&amp;ListType=WishList&amp;Email=Clint@pronerd.com">http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&amp;AWSAccessKeyId=YOUR_KEY&amp;Operation=ListSearch&amp;ListType=WishList&amp;Email=Clint@pronerd.com</a>
</p>
<p>Ok, so this is wonderful if I was doing JavaScript but I'm not.&nbsp; So how does one make this request in c#?&nbsp; You need the
<strong>ListSearchRequest</strong> , <strong>ListSearch</strong>, <strong>ListSearchResponse</strong>, and
<strong>AWSECommerceService</strong> objects. </p>
<p><strong>C# Code</strong> </p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="rem">// building search object for wishlist</span></pre>
<pre><span class="lnum">   2:  </span>ListSearchRequest request = <span class="kwrd">new</span> ListSearchRequest();</pre>
<pre class="alt"><span class="lnum">   3:  </span>request.ListType = ListSearchRequestListType.WishList;</pre>
<pre><span class="lnum">   4:  </span>request.Email = txtEmail.Text;</pre>
<pre class="alt"><span class="lnum">   5:  </span>&nbsp;</pre>
<pre><span class="lnum">   6:  </span>ListSearch listSearcher = <span class="kwrd">new</span> ListSearch();</pre>
<pre class="alt"><span class="lnum">   7:  </span>listSearcher.AWSAccessKeyId = AmazonKey;</pre>
<pre><span class="lnum">   8:  </span>listSearcher.Request = <span class="kwrd">new</span> ListSearchRequest[] { request };</pre>
<pre class="alt"><span class="lnum">   9:  </span>&nbsp;</pre>
<pre><span class="lnum">  10:  </span>ListSearchResponse response = amazonPrime.ListSearch(listSearcher);</pre>
<pre class="alt"><span class="lnum">  11:  </span><span class="rem">// populate wishlists</span></pre>
<pre><span class="lnum">  12:  </span><span class="kwrd">if</span> (response.Lists.Length &gt; 0)</pre>
<pre class="alt"><span class="lnum">  13:  </span>{</pre>
<pre><span class="lnum">  14:  </span>    List[] returnLists = response.Lists[0].List;</pre>
<pre class="alt"><span class="lnum">  15:  </span>    lstWishlists.DataSource = returnLists;</pre>
<pre><span class="lnum">  16:  </span>    lstWishlists.DisplayMember = <span class="str">&quot;ListName&quot;</span>; <span class="rem">// want to show the list name</span></pre>
<pre class="alt"><span class="lnum">  17:  </span>}</pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>Visual Basic</strong> </p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">Dim</span> request <span class="kwrd">As</span> ListSearchRequest = <span class="kwrd">New</span> ListSearchRequest</pre>
<pre><span class="lnum">   2:  </span>request.ListType = ListSearchRequestListType.WishList</pre>
<pre class="alt"><span class="lnum">   3:  </span>request.Email = txtEmail.Text</pre>
<pre><span class="lnum">   4:  </span><span class="kwrd">Dim</span> listSearcher <span class="kwrd">As</span> ListSearch = <span class="kwrd">New</span> ListSearch</pre>
<pre class="alt"><span class="lnum">   5:  </span>listSearcher.AWSAccessKeyId = AmazonKey</pre>
<pre><span class="lnum">   6:  </span>listSearcher.Request = <span class="kwrd">New</span> ListSearchRequest() {request}</pre>
<pre class="alt"><span class="lnum">   7:  </span><span class="kwrd">Dim</span> response <span class="kwrd">As</span> ListSearchResponse = amazonPrime.ListSearch(listSearcher)</pre>
<pre><span class="lnum">   8:  </span><span class="rem">' populate wishlists</span></pre>
<pre class="alt"><span class="lnum">   9:  </span><span class="kwrd">If</span> (response.Lists.Length &gt; 0) <span class="kwrd">Then</span></pre>
<pre><span class="lnum">  10:  </span>    <span class="kwrd">Dim</span> returnLists() <span class="kwrd">As</span> List = response.Lists(0).List</pre>
<pre class="alt"><span class="lnum">  11:  </span>    lstWishlists.DataSource = returnLists</pre>
<pre><span class="lnum">  12:  </span>    lstWishlists.DisplayMember = <span class="str">&quot;ListName&quot;</span></pre>
<pre class="alt"><span class="lnum">  13:  </span>    <span class="rem">' want to show the list name</span></pre>
<pre><span class="lnum">  14:  </span><span class="kwrd">End</span> If</pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<div>
<h2>Will all my wishlist items Come On Down!</h2>
<p>From here, I have access to the List ID now that I need.&nbsp; I still need the items on the list, which are returned 10 per request for max of 30 pages per the Amazon API.&nbsp; For this request, it took a bit of snooping to figure out what
<strong>RequestGroups</strong> I needed to return the items.&nbsp; I settled on the <strong>
ListItems </strong>and <strong>ItemAttributes</strong> to return the information off the wishlist.</p>
<p><strong>C# Code</strong></p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">private</span> ListItem[] GetWishlistItems(<span class="kwrd">string</span> ListId, <span class="kwrd">int</span> Page, <span class="kwrd">out</span> <span class="kwrd">int</span> TotalPages, <span class="kwrd">out</span> <span class="kwrd">int</span> TotalItems)</pre>
<pre><span class="lnum">   2:  </span>{</pre>
<pre class="alt"><span class="lnum">   3:  </span>    TotalPages = 0;</pre>
<pre><span class="lnum">   4:  </span>    TotalItems = 0;</pre>
<pre class="alt"><span class="lnum">   5:  </span>&nbsp;</pre>
<pre><span class="lnum">   6:  </span>    ListLookupRequest request = <span class="kwrd">new</span> ListLookupRequest();</pre>
<pre class="alt"><span class="lnum">   7:  </span>    request.ListId = ListId;</pre>
<pre><span class="lnum">   8:  </span>    request.ListType = ListLookupRequestListType.WishList;</pre>
<pre class="alt"><span class="lnum">   9:  </span>    request.ListTypeSpecified = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum">  10:  </span>    request.ProductPage = Page.ToString();</pre>
<pre class="alt"><span class="lnum">  11:  </span>    request.ResponseGroup = <span class="kwrd">new</span> <span class="kwrd">string</span>[] { <span class="str">&quot;ListItems&quot;</span>, <span class="str">&quot;ItemAttributes&quot;</span> }; <span class="rem">// ItemAttributes gets me package size</span></pre>
<pre><span class="lnum">  12:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  13:  </span>    ListLookup listLookup = <span class="kwrd">new</span> ListLookup();</pre>
<pre><span class="lnum">  14:  </span>    listLookup.AWSAccessKeyId = AmazonKey;</pre>
<pre class="alt"><span class="lnum">  15:  </span>    listLookup.Request = <span class="kwrd">new</span> ListLookupRequest[] { request };</pre>
<pre><span class="lnum">  16:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  17:  </span>    ListLookupResponse response = amazonPrime.ListLookup(listLookup);</pre>
<pre><span class="lnum">  18:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  19:  </span>    <span class="rem">// populate wishlists</span></pre>
<pre><span class="lnum">  20:  </span>    <span class="kwrd">if</span> (response.Lists != <span class="kwrd">null</span> &amp;&amp; response.Lists.Length &gt; 0 &amp;&amp; response.Lists[0].List.Length &gt; 0)</pre>
<pre class="alt"><span class="lnum">  21:  </span>    {</pre>
<pre><span class="lnum">  22:  </span>        List returnedList = response.Lists[0].List[0];</pre>
<pre class="alt"><span class="lnum">  23:  </span>&nbsp;</pre>
<pre><span class="lnum">  24:  </span>        TotalPages = Convert.ToInt32(returnedList.TotalPages);</pre>
<pre class="alt"><span class="lnum">  25:  </span>        TotalItems = Convert.ToInt32(returnedList.TotalItems);</pre>
<pre><span class="lnum">  26:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  27:  </span>        <span class="kwrd">return</span> response.Lists[0].List[0].ListItem;</pre>
<pre><span class="lnum">  28:  </span>    }</pre>
<pre class="alt"><span class="lnum">  29:  </span>    <span class="kwrd">return</span> <span class="kwrd">null</span>;</pre>
<pre><span class="lnum">  30:  </span>}</pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>Visual Basic</strong></p>
<p><strong></strong>&nbsp;</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Function</span> GetWishlistItems(<span class="kwrd">ByVal</span> ListId <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> Page <span class="kwrd">As</span> <span class="kwrd">Integer</span>, <span class="kwrd">ByRef</span> TotalPages <span class="kwrd">As</span> <span class="kwrd">Integer</span>, <span class="kwrd">ByRef</span> TotalItems <span class="kwrd">As</span> <span class="kwrd">Integer</span>) <span class="kwrd">As</span> ListItem()</pre>
<pre><span class="lnum">   2:  </span>        TotalPages = 0</pre>
<pre class="alt"><span class="lnum">   3:  </span>        TotalItems = 0</pre>
<pre><span class="lnum">   4:  </span>        <span class="kwrd">Dim</span> request <span class="kwrd">As</span> ListLookupRequest = <span class="kwrd">New</span> ListLookupRequest</pre>
<pre class="alt"><span class="lnum">   5:  </span>        request.ListId = ListId</pre>
<pre><span class="lnum">   6:  </span>        request.ListType = ListLookupRequestListType.WishList</pre>
<pre class="alt"><span class="lnum">   7:  </span>        request.ListTypeSpecified = <span class="kwrd">true</span></pre>
<pre><span class="lnum">   8:  </span>        request.ProductPage = Page.ToString</pre>
<pre class="alt"><span class="lnum">   9:  </span>        request.ResponseGroup = <span class="kwrd">New</span> <span class="kwrd">String</span>() {<span class="str">&quot;ListItems&quot;</span>, <span class="str">&quot;ItemAttributes&quot;</span>}</pre>
<pre><span class="lnum">  10:  </span>        <span class="rem">' ItemAttributes gets me package size</span></pre>
<pre class="alt"><span class="lnum">  11:  </span>        <span class="kwrd">Dim</span> listLookup <span class="kwrd">As</span> ListLookup = <span class="kwrd">New</span> ListLookup</pre>
<pre><span class="lnum">  12:  </span>        listLookup.AWSAccessKeyId = AmazonKey</pre>
<pre class="alt"><span class="lnum">  13:  </span>        listLookup.Request = <span class="kwrd">New</span> ListLookupRequest() {request}</pre>
<pre><span class="lnum">  14:  </span>        <span class="kwrd">Dim</span> response <span class="kwrd">As</span> ListLookupResponse = amazonPrime.ListLookup(listLookup)</pre>
<pre class="alt"><span class="lnum">  15:  </span>        <span class="rem">' populate wishlists</span></pre>
<pre><span class="lnum">  16:  </span>        <span class="kwrd">If</span> ((<span class="kwrd">Not</span> (response.Lists) <span class="kwrd">Is</span> <span class="kwrd">Nothing</span>)  _</pre>
<pre class="alt"><span class="lnum">  17:  </span>                    <span class="kwrd">AndAlso</span> ((response.Lists.Length &gt; 0)  _</pre>
<pre><span class="lnum">  18:  </span>                    <span class="kwrd">AndAlso</span> (response.Lists(0).List.Length &gt; 0))) <span class="kwrd">Then</span></pre>
<pre class="alt"><span class="lnum">  19:  </span>            <span class="kwrd">Dim</span> returnedList <span class="kwrd">As</span> List = response.Lists(0).List(0)</pre>
<pre><span class="lnum">  20:  </span>            TotalPages = Convert.ToInt32(returnedList.TotalPages)</pre>
<pre class="alt"><span class="lnum">  21:  </span>            TotalItems = Convert.ToInt32(returnedList.TotalItems)</pre>
<pre><span class="lnum">  22:  </span>            <span class="kwrd">Return</span> response.Lists(0).List(0).ListItem</pre>
<pre class="alt"><span class="lnum">  23:  </span>        <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum">  24:  </span>        <span class="kwrd">Return</span> <span class="kwrd">Nothing</span></pre>
<pre class="alt"><span class="lnum">  25:  </span>    <span class="kwrd">End</span> Function</pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h2>It rattles, it is Legos or a toaster.</h2>
<p>So it is neither, but as of now, we know the item's package size and that is about all.&nbsp; We need to datamine this information down.&nbsp; Since I stored the items in an array list, I can easily add and remove items without reallocating memory.&nbsp; This is good since
 there is no way to predetermine what the gift's size you're looking to find is.&nbsp; So with some inputs, we can request the height, width, and length of the item along with a tolerance for wrapping paper / extra padding.&nbsp; After testing this, I never realized
 how many DVDs I have on my list.</p>
<p><strong>C# Code</strong></p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span>ArrayList templist = <span class="kwrd">new</span> ArrayList();</pre>
<pre><span class="lnum">   2:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">   3:  </span><span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; giftList.Count; i&#43;&#43;)</pre>
<pre><span class="lnum">   4:  </span>{</pre>
<pre class="alt"><span class="lnum">   5:  </span>    <span class="kwrd">decimal</span> tolerance = numTol.Value;</pre>
<pre><span class="lnum">   6:  </span>    ListItemsSimple temp = (ListItemsSimple)giftList[i];</pre>
<pre class="alt"><span class="lnum">   7:  </span>&nbsp;</pre>
<pre><span class="lnum">   8:  </span>    <span class="kwrd">if</span>(</pre>
<pre class="alt"><span class="lnum">   9:  </span>        Math.Abs(temp.Height - numHeight.Value) &lt; tolerance &amp;&amp; </pre>
<pre><span class="lnum">  10:  </span>        (</pre>
<pre class="alt"><span class="lnum">  11:  </span>            <span class="rem">// incase Amazon and you disagree with </span></pre>
<pre><span class="lnum">  12:  </span>            <span class="rem">// which is length and width</span></pre>
<pre class="alt"><span class="lnum">  13:  </span>            (Math.Abs(temp.Length - numLength.Value) &lt; tolerance &amp;&amp;</pre>
<pre><span class="lnum">  14:  </span>            Math.Abs(temp.Width - numWidth.Value) &lt; tolerance)</pre>
<pre class="alt"><span class="lnum">  15:  </span>            ||</pre>
<pre><span class="lnum">  16:  </span>            (Math.Abs(temp.Width - numLength.Value) &lt; tolerance &amp;&amp;</pre>
<pre class="alt"><span class="lnum">  17:  </span>            Math.Abs(temp.Length - numWidth.Value) &lt; tolerance))</pre>
<pre><span class="lnum">  18:  </span>        )</pre>
<pre class="alt"><span class="lnum">  19:  </span>    {</pre>
<pre><span class="lnum">  20:  </span>        templist.Add(giftList[i]);</pre>
<pre class="alt"><span class="lnum">  21:  </span>    }</pre>
<pre><span class="lnum">  22:  </span>}</pre>
<pre class="alt"><span class="lnum">  23:  </span>&nbsp;</pre>
<pre><span class="lnum">  24:  </span>lstGifts.DataSource = templist;</pre>
<pre class="alt"><span class="lnum">  25:  </span>lstGifts.DisplayMember = <span class="str">&quot;Title&quot;</span>; // want to show the list name</pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>Visual Basic</strong></p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">Dim</span> templist <span class="kwrd">As</span> ArrayList = <span class="kwrd">New</span> ArrayList</pre>
<pre><span class="lnum">   2:  </span><span class="kwrd">Dim</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0</pre>
<pre class="alt"><span class="lnum">   3:  </span><span class="kwrd">Do</span> <span class="kwrd">While</span> (i &lt; giftList.Count)</pre>
<pre><span class="lnum">   4:  </span>    <span class="kwrd">Dim</span> tolerance <span class="kwrd">As</span> <span class="kwrd">Decimal</span> = numTol.Value</pre>
<pre class="alt"><span class="lnum">   5:  </span>    <span class="kwrd">Dim</span> temp <span class="kwrd">As</span> ListItemsSimple = <span class="kwrd">CType</span>(giftList(i),ListItemsSimple)</pre>
<pre><span class="lnum">   6:  </span>    <span class="kwrd">If</span> ((Math.Abs((temp.Height - numHeight.Value)) &lt; tolerance)  _</pre>
<pre class="alt"><span class="lnum">   7:  </span>                <span class="kwrd">AndAlso</span> (((Math.Abs((temp.Length - numLength.Value)) &lt; tolerance)  _</pre>
<pre><span class="lnum">   8:  </span>                <span class="kwrd">AndAlso</span> (Math.Abs((temp.Width - numWidth.Value)) &lt; tolerance))  _</pre>
<pre class="alt"><span class="lnum">   9:  </span>                <span class="kwrd">OrElse</span> ((Math.Abs((temp.Width - numLength.Value)) &lt; tolerance)  _</pre>
<pre><span class="lnum">  10:  </span>                <span class="kwrd">AndAlso</span> (Math.Abs((temp.Length - numWidth.Value)) &lt; tolerance)))) <span class="kwrd">Then</span></pre>
<pre class="alt"><span class="lnum">  11:  </span>        templist.Add(giftList(i))</pre>
<pre><span class="lnum">  12:  </span>    <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre class="alt"><span class="lnum">  13:  </span>    i = (i &#43; 1)</pre>
<pre><span class="lnum">  14:  </span><span class="kwrd">Loop</span></pre>
<pre class="alt"><span class="lnum">  15:  </span>lstGifts.DataSource = templist</pre>
<pre><span class="lnum">  16:  </span>lstGifts.DisplayMember = <span class="str">&quot;Title&quot;</span></pre>
</div>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h2>Wrapping it all together with only 3 peices of tape.</h2>
<p>So the rest of the application is just fluff.&nbsp; Add some paint using&nbsp;counter-clockwise swirling motions and you get this.</p>
<p><img height="446" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1308209/grinch9.gif" width="418">
</p>
<h2>Problems?&nbsp; </h2>
<p>For a while I did have a snip of code that removed items that were bought and got greater than and less than signs and found out I'm getting 2 copies of Rome season one (good show) on accident.&nbsp; That caused me to realize I don't know when items were bought
 and I'm slightly more stupid than I thought.&nbsp; I know how many of an item were asked for and how many were purchased, I don't know when they were bought.&nbsp; Due to this fact, I cannot restrict items.&nbsp; Amazon has the wishlist anti-spoiler feature so I figured
 I'll just return everything.</p>
<p><strong>Author Bio</strong>: Clint is an application developer for <a href="http://springcm.com/">
SpringCM</a>, an on-demand, web-based document and content management system. As a developer, Clint is part of an innovative team committed to supporting affordable, scalable and reliable enterprise content management. His two primary development languages
 are C# and JavaScript. He worked on his <a href="http://msdn.microsoft.com/coding4fun/coolapplications/disco/default.aspx">
Disco Dance Floor</a>&nbsp;and helps out Coding4Fun with thier daily blog entries. In his off time, he whips up other random weird projects and does twenty something activities with his friends. Clint's blog is
<a href="http://betterthaneveryone.com/">betterthaneveryone.com</a> and can be emailed at
<a href="mailto:clint@rutkas.com">clint@rutkas.com</a>. <span>Clint Rutkas created a program will guess what your gift is. With the size of your wrapped present, the program will poll Amazon and based on what is on your wishlist, it will guess what it may be!]]&gt;
 Clint Rutkas http://betterthaneveryone.com Clint Rutkas's Blog http://channel9.msdn.com/ShowPost.aspx?PostID=266742 http://channel9.msdn.com/ShowPost.aspx?PostID=266743 Intermediate Less than $50 1-3 hours Visual Studio Express Editions]]&gt; ]]&gt;</span></p>
</div>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:bd547dc825974f0bbc609e7600d71aaa">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Im-a-mean-one-Im-the-Grinch--by-using-Amazon-Web-Services</comments>
      <itunes:summary>
With the aid of Amazon.com web services, 
Clint Rutkas created a program that will guess what your gift is. With the size of your wrapped present, the program will poll Amazon and based on what is on your wishlist, it will guess what it may be! 
&amp;nbsp;
Difficulty: Intermediate
Time Required: 
1-3 hours
Cost: Free
Software: Visual Studio Express Editions
Hardware: None
Download:&amp;nbsp;C# or
Visual Basic&amp;nbsp;



Signing up for the Amazon Web Services
The first step in using this application is 
signing up for the Amazon Web Services.&amp;nbsp; From there you&#39;ll get a AWS key that you will use to access the web service for authorization purposes.&amp;nbsp; This key should be 20 characters. 

 
Adding the Amazon Web Services to .Net
The wonderful thing about .Net is how easy it is to add in a Web Service.&amp;nbsp; First you right click on References in your solution. 
&amp;nbsp; 
 
The next step is adding in the WSDL.&amp;nbsp; Here is the URL for it. 
http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl
 

 
Oven is preheating, lets do some work.
Ok, so now I have the web service added and Visual Studio is all ready to rock the casbah, we need know how to request&amp;nbsp;information. &amp;nbsp;For that, we need documentation.&amp;nbsp; RTFM?&amp;nbsp; Yes, read the manual which is

found here (PDF).&amp;nbsp; After a few quick searches, I found some samples through direct requests. 
Here is an example that will return my wishlists.&amp;nbsp; You need to add in insert your key. 
http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&amp;amp;AWSAccessKeyId=YOUR_KEY&amp;amp;Operation=ListSearch&amp;amp;ListType=WishList&amp;amp;Email=Clint@pronerd.com
 
Ok, so this is wonderful if I was doing JavaScript but I&#39;m not.&amp;nbsp; So how does one make this request in c#?&amp;nbsp; You need the
ListSearchRequest , ListSearch, ListSearchResponse, and
AWSECommerceService objects.  
C# Code  

   1:  // building search object for wishlist
   2:  ListSearchRequest request = new ListSearchRequest();
   3:  reques</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Im-a-mean-one-Im-the-Grinch--by-using-Amazon-Web-Services</link>
      <pubDate>Sat, 16 Dec 2006 21:11:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Im-a-mean-one-Im-the-Grinch--by-using-Amazon-Web-Services</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1308209_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1308209_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Clint Rutkas</dc:creator>
      <itunes:author>Clint Rutkas</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Im-a-mean-one-Im-the-Grinch--by-using-Amazon-Web-Services/RSS</wfw:commentRss>
      <category>Web Services</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Have You Been Naughty or Nice?</title>
      <description><![CDATA[<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<div><span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1287528/thumb5.jpg"><img height="50" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1287528/thumb_thumb1.jpg" width="50" border="0"></a>
</td>
<td><span class="entry_description">Is Santa paying you a visit this year? Find out how naughty or nice you are based on what you say on your blog or personal web site!</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Arian Kulp</div>
<div class="entry_company"><a href="http://www.ariankulp.com">Arian Kulp's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
1-3 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn.com/express/">Visual Basic or Visual C# Express Editions</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><strong>Download: </strong><a href="http://channel9.msdn.com/ShowPost.aspx?PostID=266250">Sample Code</a></div>
</td>
</tr>
</tbody>
</table>
</span>
<blockquote>
<p>He's making a list and checking it twice,<br>
Gonna find out who's naughty and nice,<br>
Santa Claus is coming to town.</p>
</blockquote>
<p>Did this song creep you out as a kid?&nbsp; It did me!&nbsp; Now that you're all grown up (well, some of us anyway!) you may think that it doesn't apply to you anymore.&nbsp; Do you really want to take that chance though?&nbsp; I didn't think so!&nbsp; This article helps to evaluate
 your level of naughtiness/niceness based on your blog (or other personal web site).
</p>
<p>Read the article for some background information, then explore the code yourself.&nbsp; This application uses the
<strong>BackgroundWorker</strong>, <strong>WebClient</strong>, and works with regular expressions with the
<strong>Regex</strong> object.&nbsp; In order to open the project, you will need Visual Studio Express Editions (either C# or Visual Basic) or higher.&nbsp; You can download the Express editions for free from
<a href="http://msdn.microsoft.com/vstudio/express">here</a>. </p>
<h2>Background</h2>
<p>An ancient Chinese proverb states that &quot;The entries in your blog reveal your inner self.&quot;&nbsp; Even though I just made that up, it's no less true.&nbsp; Are you grumpy, happy, hopeful, crazy?&nbsp; Chances are it's obvious from your blog posts.&nbsp; This application will
 take a URL, scan it for a list of &quot;naughty&quot; and &quot;nice&quot; words, and come up with a score of niceness.&nbsp; But beware: pages linked from the given URL will also be scanned and taken into account.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1287528/image19.jpg"><img height="176" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1287528/image18.jpg" width="240" border="0"></a>
</p>
<p><b>(click image to zoom)</b></p>
<h2>Downloading the URL</h2>
<p>So the first step is to download the given URL.&nbsp; This can be accomplished by opening a socket, issuing an HTTP GET request, and reading back the resulting stream of bytes one at a time.&nbsp; On the other hand, it can also be performed in two lines of code using
 the <strong>System.Net.WebClient</strong><em> </em>object.&nbsp; For me, the choice was simple.&nbsp; The
<strong>WebClient</strong> has a number of methods to download a file synchronously or asynchronously, either as a string, a byte array, or directly to a file.&nbsp; Once the object is instantiated, a single line of code does the actual work.&nbsp; It's so easy, you'll
 be adding URL download functionality into every application before you know it!&nbsp;</p>
<p><strong>NOTE: </strong>You must specify a complete URL, that is, beginning with HTTP.&nbsp; You won't get an error otherwise, it just won't appear to work right.</p>
<p></p>
<pre><code></code></pre>
<b>Visual Basic</b>
<p></p>
<pre class="csharpcode"><span class="kwrd">Dim</span> wc <span class="kwrd">As</span> WebClient = <span class="kwrd">New</span> WebClient
body = wc.DownloadString(url)</pre>
<p><b>Visual C#</b></p>
<pre class="csharpcode">WebClient wc = <span class="kwrd">new</span> WebClient();
body = wc.DownloadString(url);</pre>
<h2>Searching for Patterns</h2>
<p>Once you have the contents of the URL in a string, you can anything with it as with any other string.&nbsp; Perform
<strong>IndexOf</strong> searches, save it to a database, or apply regular expressions.&nbsp; This is the use of interest for this application.&nbsp; Regular expression support is found in the
<strong>System.Text.RegularExpressions</strong><em> </em>namespace with the <strong>
Regex</strong> object.&nbsp; Using the <strong>Regex </strong>object is pretty easy, but coming up with the expression itself can be a challenge.</p>
<p>If you haven't used regular expressions before, you may want to take a few minutes to read about them.&nbsp; I good place to start is the MSDN reference page,
<a href="http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcomregularexpressions.asp">
.NET Framework Regular Expressions</a>.&nbsp; Unfortunately, regular expressions aren't very intuitive at first (or ever for some people!).&nbsp; Creating your own expression can be difficult, but you can often find pre-built ones online.&nbsp; Note that regular expressions
 are used in conjunction with string verification, formatting, searching, and replacing.&nbsp; This application will use three different expressions.&nbsp; One will be used to search for &quot;nice&quot; keywords, another for &quot;naughty&quot; keywords.&nbsp; The third expression will locate
 hyperlinks based on the <strong>href</strong> attribute of the <strong>a</strong> element found in HTML.</p>
<p>Creating a <strong>Regex</strong> object incurs some overhead, not only from object creation, but also from parsing the expression.&nbsp; To minimize this, all three
<strong>Regex</strong> objects are created when the application starts up.</p>
<pre><code></code></pre>
<p><strong>Visual Basic</strong></p>
<p></p>
<pre class="csharpcode"><span class="kwrd">Dim</span> REGEX_NICE_WORDS <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;love|great|good|rocks|awesome|nice&quot;</span>
<span class="kwrd">Dim</span> REGEX_NAUGHTY_WORDS <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;damn|sucks|hate|stupid|dumb|bad&quot;</span>
<span class="kwrd">Dim</span> REGEX_HYPERLINKS <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="str">&quot;href\s*=\s*(?:\&quot;</span><span class="str">&quot;&quot;</span><span class="str">&quot;(?&lt;1&gt;[^&quot;</span><span class="str">&quot;&quot;</span><span class="str">&quot;]*)&quot;</span><span class="str">&quot;&quot;</span><span class="str">&quot;|(?&lt;1&gt;\S&#43;))&quot;</span></pre>
<pre class="csharpcode"><span class="kwrd">Private</span> urlRegex, niceregex, naughtyregex <span class="kwrd">As</span> Regex</pre>
<p><b>Visual C#</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> REGEX_NICE_WORDS = <span class="str">&quot;love|great|good|rocks|awesome|nice&quot;</span>;
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> REGEX_NAUGHTY_WORDS = <span class="str">&quot;damn|sucks|hate|stupid|dumb|bad&quot;</span>;
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> REGEX_HYPERLINKS = <span class="str">&quot;href\\s*=\\s*(?:\&quot;\&quot;(?&lt;1&gt;[^\&quot;\&quot;]*)\&quot;\&quot;|(?&lt;1&gt;\\S&#43;))&quot;</span>;

<span class="kwrd">private</span> Regex niceRegex, naughtyRegex, urlRegex;</pre>
<p>The basic flow will be: search for nice words, search for naughty keywords, search for hyperlinks, repeat the nice/naughty search for each linked page.&nbsp; Linked pages are not scanned for additional links to avoid overload.&nbsp; As it is, some sites already take
 a full minute to process!&nbsp; The process of downloading a page then performing the searches is contained in the
<strong>DetermineScore </strong>method.</p>
<p>In order to actually perform the search, invoke the <strong>Matches</strong> method.&nbsp; This returns a
<strong>MatchCollection</strong> object for iteration.&nbsp; There's no need to iterate the actual words found, so the
<strong>Count</strong> property is sufficient:</p>
<p></p>
<pre><code></code></pre>
<p><strong>Visual Basic</strong></p>
<p></p>
<pre class="csharpcode">niceCount = niceregex.Matches(body).Count
naughtyCount = naughtyregex.Matches(body).Count</pre>
<b>Visual C#</b>
<pre class="csharpcode">niceCount = niceRegex.Matches(body).Count;
naughtyCount = naughtyRegex.Matches(body).Count;
</pre>
<p>Another one line of code performing lots of work!&nbsp; If you needed the information, you could then use the returned
<strong>MatchCollection</strong> to determine specifically which words were returned, along with much other information about each match.&nbsp; The expression for nice and naughty words is simple: the vertical pipe (bar) acts like an OR Boolean operator.&nbsp; In other
 words, the regular expression parser will scan the entire input string (the downloaded HTML) and add a
<strong>Match</strong> object each time one of the words is found.</p>
<h2>Looking a Level Deeper</h2>
<p>After analyzing the given URL, it's time to take a look at linked pages.&nbsp; After all, the types of sites you link to also say something about how naughty or nice you probably are!&nbsp; That third regular expression is much more complex than the first two.&nbsp; Showing
 it again, we have:</p>
<blockquote>
<p>href\s*=\s*(?:&quot;&quot;(?&lt;1&gt;[^&quot;&quot;]*)&quot;&quot;|(?&lt;1&gt;\S&#43;))</p>
</blockquote>
<p>This is complicated a bit by the way that strings must be escaped in Visual C# and Visual Basic.&nbsp; In both languages, you can't just have quotes within a quoted string (you'll notice that this expression is slight different in the VB and C# code samples above).&nbsp;
 In C#, you precede the double&nbsp;quote with a backslash (\&quot;).&nbsp; If you actually need a backslash, you need to double that as well (\\).&nbsp; In Visual Basic, you double the doublequote (&quot;&quot;).&nbsp; What does this mess mean?&nbsp; Well, suffice to say that is looking for the
<strong>href</strong> attribute, and the quotes and brackets after it.&nbsp; Unfortunately, the resulting match is always more than we actually want.&nbsp; For example, a link to my site would be returned as:</p>
<div>
<blockquote>
<p>href=&quot;http://ariankulp.com/rss.aspx&quot;</p>
</blockquote>
<p>It also returns returns relative links, CSS/RSS links, and others that aren't all that interesting.&nbsp; It's easy to filter out the relative links by checking to see if each match begins with
<strong>href=&quot;http</strong>.&nbsp; The CSS/RSS links, if using an absolute host, are more complicated, so I don't filter them out.&nbsp; For each valid match found, I call the
<strong>DetermineScore </strong>method to count up naughty and nice words.&nbsp; Note that the scores on linked pages are cut in half.&nbsp; More weight is given to your own site!</p>
<h2>Putting it All Together</h2>
<p>Performing all of the URL downloads and pattern matching takes some time.&nbsp; A site with many links can really slow things down.&nbsp; When you click the button to start things off, any work that you perform will occur on the user interface thread.&nbsp; All of a sudden,
 the application is unresponsive.&nbsp; The solution to this is to run the analyzing in a separate, background&nbsp;thread.&nbsp; The
<strong>BackgroundWorker</strong> object makes this easy.&nbsp; When you invoke the <strong>
RunWorkerAsync</strong> method, the <strong>DoWork</strong> event fires on a different thread.&nbsp; The event handler then makes the necessary calls to download and analyze the given URL and discovered URL's.</p>
<p>As each link is analyzed, progress is reported by raising the <strong>ProgressChanged</strong> event.&nbsp; This is responsible for adding the links, along with naughty/nice count, to the
<strong>ListView</strong> control.</p>
<pre><code></code></pre>
<p><strong>Visual Basic</strong></p>
<p></p>
<pre class="csharpcode"><span class="kwrd">Dim</span> ls <span class="kwrd">As</span> LinkScore = <span class="kwrd">CType</span>(e.UserState, LinkScore)
<span class="kwrd">Dim</span> lvi <span class="kwrd">As</span> ListViewItem = scoresListView.Items.Add(ls.Url)

lvi.SubItems.AddRange(<span class="kwrd">New</span> <span class="kwrd">String</span>() {ls.Good.ToString, ls.Bad.ToString})

overallProgressBar.Style = ProgressBarStyle.Blocks
overallProgressBar.Value = e.ProgressPercentage</pre>
<p><b>Visual C#</b></p>
<pre class="csharpcode">LinkScore ls = e.UserState <span class="kwrd">as</span> LinkScore;

ListViewItem lvi = scoresListView.Items.Add(ls.Url);
lvi.SubItems.AddRange(
    <span class="kwrd">new</span> <span class="kwrd">string</span>[] { ls.Good.ToString(), ls.Bad.ToString() });

overallProgressBar.Style = ProgressBarStyle.Blocks;
overallProgressBar.Value = e.ProgressPercentage;
</pre>
<p>Clicking <strong>Cancel</strong> calls the <strong>CancelAsync</strong> method.&nbsp; The worker thread periodically checks the
<strong>CancellationRequested</strong> flag to exit early if necessary.&nbsp; While the initial link is being downloaded, a
<strong>ProgressBar</strong> control goes into marquee mode (think <em>Knight Rider</em>!).&nbsp; It changes to a standard progress bar as discovered links are analyzed.&nbsp; Finally, the
<strong>RunWorkerCompleted</strong> event fires when everything is done (based on the
<strong>DoWork</strong> event handler completing).&nbsp; This updates the progress percentage, enables the
<strong>Cancel</strong> button, and hides the progress bar.</p>
<h2>Next Steps</h2>
<p>The application isn't all that useful, but it's fun!&nbsp; It could easily be extended to perform different actions on discovered pages, or simply to search for different keywords.&nbsp; Several enhancements that would be fairly easy would be:</p>
<ol>
<li>Add a checkbox to prevent linked pages from being counted.&nbsp; This would speed things up.
</li><li>Add an options page to edit naughty/nice keywords and tweak other settings. </li><li>Restrict the number of links to follow.&nbsp; If the given URL has links to 200 other pages, it may never finish!
</li><li>Better filtering of links.&nbsp; As I mentioned, resources like RSS or CSS don't need to be downloaded.&nbsp; Links on the same site may not be needed either.&nbsp; Checking for the same base URL would be a pretty easy addition.
</li><li>Create multiple worker threads to share the load of analyzing linked pages.&nbsp; This is a good scenario for parallelizing.</li></ol>
<h2>Conclusion</h2>
<p>I hope that you had fun with this application.&nbsp; It was fun coming up with a naughty-or-nice formula!&nbsp; I struggled a bit with the best balance.&nbsp; It's not perfect, but it works pretty well.&nbsp; If you have a better approach, by all means tweak it.&nbsp; Best of all,
 have fun!</p>
<p>Get started by downloading <a href="http://msdn.microsoft.com/vstudio/express">
Visual Studio Express</a> and download the sample code today.</p>
<hr>
<p>Arian Kulp is an independent software developer and writer working in the Midwest.&nbsp; He has been coding since the fifth grade on various platforms, and also enjoys photography, nature, and spending time with his family.&nbsp; Arian can be reached through his web
 site at <a href="http://www.ariankulp.com">http://www.ariankulp.com</a>.</p>
</div>
</div>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:36724041a27043b58a159e7600d72d0a">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Have-You-Been-Naughty-or-Nice</comments>
      <itunes:summary>








Is Santa paying you a visit this year? Find out how naughty or nice you are based on what you say on your blog or personal web site!



Arian Kulp
Arian Kulp&#39;s Blog

Difficulty: Intermediate
Time Required: 
1-3 hours
Cost: Free
Software: Visual Basic or Visual C# Express Editions
Hardware: 
Download: Sample Code






He&#39;s making a list and checking it twice,
Gonna find out who&#39;s naughty and nice,
Santa Claus is coming to town. 

Did this song creep you out as a kid?&amp;nbsp; It did me!&amp;nbsp; Now that you&#39;re all grown up (well, some of us anyway!) you may think that it doesn&#39;t apply to you anymore.&amp;nbsp; Do you really want to take that chance though?&amp;nbsp; I didn&#39;t think so!&amp;nbsp; This article helps to evaluate
 your level of naughtiness/niceness based on your blog (or other personal web site).
 
Read the article for some background information, then explore the code yourself.&amp;nbsp; This application uses the
BackgroundWorker, WebClient, and works with regular expressions with the
Regex object.&amp;nbsp; In order to open the project, you will need Visual Studio Express Editions (either C# or Visual Basic) or higher.&amp;nbsp; You can download the Express editions for free from
here.  
Background
An ancient Chinese proverb states that &amp;quot;The entries in your blog reveal your inner self.&amp;quot;&amp;nbsp; Even though I just made that up, it&#39;s no less true.&amp;nbsp; Are you grumpy, happy, hopeful, crazy?&amp;nbsp; Chances are it&#39;s obvious from your blog posts.&amp;nbsp; This application will
 take a URL, scan it for a list of &amp;quot;naughty&amp;quot; and &amp;quot;nice&amp;quot; words, and come up with a score of niceness.&amp;nbsp; But beware: pages linked from the given URL will also be scanned and taken into account. 

 
(click image to zoom) 
Downloading the URL
So the first step is to download the given URL.&amp;nbsp; This can be accomplished by opening a socket, issuing an HTTP GET request, and reading back the resulting stream of bytes one at a time.&amp;nbsp; On the other hand, it can also be performed </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Have-You-Been-Naughty-or-Nice</link>
      <pubDate>Thu, 14 Dec 2006 15:47:56 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Have-You-Been-Naughty-or-Nice</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1287528_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1287528_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>ArianKulp</dc:creator>
      <itunes:author>ArianKulp</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Have-You-Been-Naughty-or-Nice/RSS</wfw:commentRss>
      <category>events</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Holiday Gift Guide 2006</title>
      <description><![CDATA[
<p>Tired of giving socks every year to your favorite engineer or technology elitist? Coding4Fun has come up with a holiday gift guide of items that are sure to make them glee with joy. We've cranked up the geek-factor and have tried to come up with the biggest
 list of programmable presents on the Web! &nbsp;If you like the guide, <a href="http://www.digg.com/submit?url=http://msdn.microsoft.com/coding4fun/archive/article.aspx?articleid=1228621&amp;title=Holiday%20Gift%20Guide%202006">
Digg Us</a>. </p>
<p>Do you know of a programmable present that wasn't listed here? <a href="mailto:code4fun@microsoft.com">
Email us</a> and we'll get it added to our list. </p>
<p>The holiday guide is broken down into 5 sections. Programmable Hardware and Gadgets, Programmable Robots, Programmable Games, Cool Software Tools, and Top 10 Presents for Developers
</p>
<p></p>
<h3><a class="" title="hardware" name="hardware"></a><b>Programmable Hardware and Gadgets</b>
</h3>
<p>Enjoy tinkering?&nbsp; Think that the orginary can be modified to do something different with a little effort?&nbsp; This entire section of gifts are items one can program. The range from webcams to disco floor parts to cell phones.
<table class="" cellspacing="5" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/xbox360controller5.jpg" width="240" align="left"> Wireless Xbox 360 Controller for Windows</b>
</p>
<p>The newly released wireless controller can be used to play both Xbox 360 and Windows PC games, and best of all, you can program with it too. In fact, certain applications, like Virtual Earth 3D already include support for the Xbox 360 controller so you'll
 be able to use your controller to literally fly around the world! </p>
<p><b>Cost</b>: $37.99 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/Microsoft-VAMSFT-882224022408-Wireless-Controller/dp/B000B6MLUA/sr=8-2/qid=1165259673/ref=pd_bbs_sr_2/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Wireless Xbox 360 Controller</a> on Amazon.com </p>
<p><b>Code it</b>: The XNA Framework includes full support for Xbox 360 controllers for Windows and the Web using the XInput class. To learn the basics of programming your XNA controller, check out Paul Stubbs excellent
<a href="http://blogs.msdn.com/pstubbs/articles/531008.aspx">Xbox 360 controller article</a> as well as the newly updated version ported to work with the
<a href="http://blogs.msdn.com/pstubbs/archive/2006/08/31/733031.aspx">XNA Framework</a>.
</p>
</td>
</tr>
<tr>
<td class=""><b><img height="160" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/irman_front14.jpg" width="240" align="right"> IrMan</b><br>
Infrared man (Irman) is a small device that allows you to control your PC with the remote from your TV, VCR, CD or Stereo. You can use it to programmatically control any applications on your PC!<br>
<b>Cost</b>: $40<br>
<b>Get it</b>: <a href="http://www.evation.com/irman/">IrMan Home Page</a><br>
<b>Code it</b>: Duncan MacKenzie, the first Coding4Fun author, posted a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncodefun/html/code4fun06272003.asp">
classic article</a> on using an IrMan through a Pocket PC using Visual Studio .NET 2003.
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/wiiremote5.jpg" width="240" align="left"> Nintendo Wii Remote</b>
</p>
<p>Why the Wii Remote without the Nintendo Wii? Because some <a href="http://www.hackaday.com/2006/12/01/hacking-wiimote-bluetooth/">
clever hackers figure </a>out how to get information out of it. The Wii Remote is actually a Bluetooth device that has an XYZ accelerometer in it. With some computing, one is able to figure out the tilt of the controller.
</p>
<p><b>Cost</b>: $53.67 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/Nintendo-Wii-Remote-Controller/dp/B000IMWK2G/sr=8-1/qid=1165274081/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Nintendo Wii Remote</a> on Amazon.com<br>
<b>Code it</b>: [Link coming soon]</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/PE830_rg16.jpg" width="200" align="right"> Pedometer with PC Download</b>
</p>
<p>Geek out, even when your exercising using this built-in pedometer </p>
<p><b>Cost: </b>$59.99 </p>
<p><b>Get it:</b> <a href="http://www2.oregonscientific.com/shop/product.asp?cid=3&amp;scid=10&amp;pid=686">
Pedometer with PC Download</a> </p>
<p><b>Code it:</b> With the included PC download software, users can easily export the data into a database and easily track their progress.
</p>
</td>
</tr>
<tr>
<td class=""><b><img height="66" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/CFA635_YYE_Front_Backlight_On_43015.jpg" width="240" align="left"> CrystalFontz LCD Displays<br>
</b>Using the new Serial Port classes in the .NET Framework 2.0, you can create some pretty cool applications to display dynamic information on a CrystalFontz LCD display.<br>
<b>Cost</b>: $60-$80<br>
<b>Get it</b>: <a href="http://www.crystalfontz.com/">CrystalFontz Home Page</a><br>
<b>Code it</b>: Scott Hanselman has a <a href="http://msdn.microsoft.com/coding4fun/hardware/misc/article.aspx?articleid=914453">
great article that shows how to display</a> what's playing in Windows Media Player on an LCD display and Kit George has a cool
<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/SpaceInvadersCS.zip">
Space Invaders Console game demo</a> that he hooked up to an LCD display to control how you fly the spacecraft.
</td>
</tr>
<tr>
<td class="">
<p><b><img height="185" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/phidget6.jpg" width="240" align="right"> Phidgets</b>
</p>
<p><a href="http://www.phidgets.com/">Phidgets</a> are a low cost, easy to use building block that connects to your PC through USB. Through a very robust API, developing applications is quick and easy. They have RFID, electrical relays, Servos, LED, multiple
 different types of sensors, and even a Pan &amp; Tilt Web Cam kit. </p>
<p><b>Cost</b>: $75 and up </p>
<p><b>Get it</b>: </p>
<p><b>Code it</b>: Scott Hanselman created a <a href="http://msdn.microsoft.com/coding4fun/article.aspx?articleid=914024">
weather collection program</a> and Brian Peek created a <a href="http://msdn.microsoft.com/coding4fun/article.aspx?articleid=905480">
motion-detecting Halloween prank from one</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="150" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/aic25016.jpg" width="139" align="left"> Airlink Network Camera AIC 250
</b></p>
<p>Enjoy full motion video over a wireless connection with this easy-to-setup Web cam with built-in support for DSL or Cable model DHCP.
</p>
<p><b>Cost: </b>$99<b></b> </p>
<p><b>Get it:</b> <a href="http://shop1.outpost.com/product/4600208?site=sr:SEARCH:MAIN_RSLT_PG">
Airlink Network Camera at Frys.com</a> </p>
<p><b>Code it: </b>Scott Hanselman's got a great article that shows how to <a href="http://msdn.microsoft.com/coding4fun/hardware/video/article.aspx?articleid=912407">
programmatically detect motion</a> using the AIC 250 Network Camera.</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/streets7.jpg" width="240" align="right"> GPS Receiver with Microsoft Streets &amp; Trips 2007
</b></p>
<p>Where am I? With Microsoft Streets and Trips, it provides a turn-by-turn speech support and .NET integration. This software and GPS combo can be used with your laptop, Tablet PC, Windows Mobile device to find your way when asking for directions won't do.
</p>
<p><b>Cost</b><b>:</b> $129.99 </p>
<p><b>Get it</b><b>:</b> <a href="http://www.amazon.com/exec/obidos/ASIN/B000HDOJUC/ref=nosim/3147335-20">
Streets and Trips 2006</a> on Amazon.com </p>
<p><b>Code it</b><b>:</b> Scott Hanselman again comes to the rescue with a great article on
<a href="http://msdn.microsoft.com/coding4fun/hardware/misc/article.aspx?articleid=914453">
how read data off of the GPS receiver</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="175" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/controller115.jpg" width="240" align="left"> MAKE Controller Kit</b>
</p>
<p>Need a relay controller? How about a device that is Ethernet ready? USB too? Need digital Inputs also? Don't worry, MAKE has you covered with their MAKE controller. It has all of the above functionality and more. More so, it has API for .Net, Java, Max &amp;
 Pd, Flash, C / C&#43;&#43;. You can even network multiple controllers together to create a more complex device.
</p>
<p><b>Cost</b>: $149 </p>
<p><b>Get it</b>: <a href="http://www.makingthings.com/cgi-local/SoftCart.100.exe/online-store/scstore/c-MAKE_Controller_Kit.html?L&#43;scstore&#43;kmdj3248ff31f231&#43;1172938304">
Make Controller Kit</a> </p>
<p><b>Code it</b>: The Make Controller Kit features a <a href="http://www.makingthings.com/makecontrollerkit/guides/dotnet.html">
.NET library for easy programmability</a> that can be used with any managed code language including VB, C#, and C&#43;&#43;.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="150" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/CD_collection15.jpg" width="150" align="right"> Z-Wave PC SDK Starter Kit</b>
</p>
<p>Intermatic's HomeSettings Lighting Control Starter Kit is an easy way to help automate your home. Want your lights to turn on at 7 pm or
<a href="http://msdn.microsoft.com/coding4fun/hardware/home/article.aspx?articleid=1088252">
control your home entertainment system's lighting</a>, the Z-Wave makes it rather easy.
</p>
<p><b>Cost</b>: $149 not including discount for registered Express users </p>
<p><b>Get it</b>: <a href="http://www.controlthink.com/zwavesdk.htm">Z-Wave PC SDK Starter Kit</a>
</p>
<p><b>Code it</b>: The Z-Wave PC Starter Kit ships with the SDK, .NET Framework API and full documentation to get started. You can get help using the SDK on the
<a href="http://forums.controlthink.com/5/ShowForum.aspx">ControlThink Forums</a>.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="192" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/mc_200617.jpg" width="240" align="left"> Learning Edition Microcontroller Kit
</b></p>
<p>Whether you're young or old, learning the ins and outs of microcontrollers can be tricky. You can now learn the basics of microcontrollers including programming sensors, motors, resistors, microphones, diodes, capacitors and more.
</p>
<p><b>Cost:</b> $149.95 </p>
<p><b>Get it:</b> <a href="http://www.thamesandkosmos.com/products/mc/mc.html">Microcontroller Kit Home Page</a> (source: Wired Gift Guide)
</p>
<p><b>Code it:</b> The kit includes built-in programmability for controlling your hardware.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="162" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/ellipse4.jpg" width="240" align="right">Disco Dance Floor Parts
</b></p>
<p>If you want your home to be disco'ed out, you can get the PCB hardware boards from the people over at MIT who originally designed it. They also have boards pre-constructed if surface soldering isn't your forte for an additional cost.&nbsp; Not sure on what types
 of LEDs to buy or how to do the cabling?&nbsp; They have that too now! </p>
<p><b>Cost: </b>$35 to $450 dollars per board </p>
<p><b>Get it</b>: <a href="http://www.dropoutdesign.com/ddf-parts.html">Dropout Design</a>
</p>
<p><b>Code it</b>: You can't go wrong with Clint Rutkas's Coding4Fun article for how to
<a href="http://msdn.microsoft.com/coding4fun/article.aspx?articleid=918683">build out your own disco dance floor</a>!</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="202" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/EC.DEI.SCH1W17.jpg" width="160" align="left"> Sirius Conductor Satellite Radio Tuner</b>
</p>
<p>For <a href="http://www.sirius.com/">Sirius</a> Satellite radio fans, you can program macro-like behavior using the Z-Wave Sirius Radio Tuner. Because it's Z-Wave, you'll be able to easily program it or any other
<a href="http://www.z-wavealliance.org/content/modules/iaCM-ProReg-II/">Z-Wave Products</a> using the Intermatic .NET Framework 2.0 gear.
</p>
<p><b>Cost: </b>$149.99 </p>
<p><b>Get it:</b> <a href="http://www.circuitcity.com/ssm/SIRIUS-Conductor-Satellite-Radio-Tuner-SCH1W/sem/rpsm/oid/164934/catOid/-14641/rpem/ccd/productDetail.do">
Z-Wave Sirius Radio Tuner at Circuit City</a> </p>
<p><b>Code it:</b> If you have the Z-Wave PC SDK with <a href="http://www.controlthink.com/zwavesdk.htm">
Intermatic Home Settings Lighting Control Starter Kit</a>, it includes the ControlThink SDK which enables you to easily program Z-Wave gear.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="193" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/phones4.jpg" width="240" align="right"> Windows Mobile Smartphones</b>
</p>
<p>The Samsung Blackjack, T-Mobile Dash, or the Motorola Q are great at making complex life easy. They run Windows Mobile 5.0 Smart Phone edition and are slim and small. With this Windows Mobile Version, you won't be able to alter Office Documents, but you'll
 be able to view them through Picsel Viewer. All these phones have a full QWERTY keyboard on them.
</p>
<p>If you need more power, upgrade to a Cingular 8515, a Treo 700w, T-Mobile MDA, or the Samsung SCH-i730. These phones have larger screens that are touch sensitive and while physically bigger, they can do more. Unlike the phones above that run the Smart Phone
 edition these run the Pocket PC Edition. With these phones, you get Microsoft Office Mobile Suite so one can create and editing of Office documents.
</p>
<p><b>Price</b>: $199 - $600 </p>
<p><b>Get it</b>: <a href="http://www.microsoft.com/windowsmobile/devices/default.mspx">
Windows Mobile Smartphones</a> </p>
<p><b>Code it</b>: You can use Visual Studio 2005 Standard Edition, one is able to develop for these devices and create software with ease, like Bryan Dougherty's
<a href="http://msdn.microsoft.com/coding4fun/gaming/arcade/article.aspx?articleid=1044050&amp;title=Pac-Man&#43;for&#43;the&#43;Smartphone">
Mobile Pac-man</a> </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="188" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/SDK0052T16.jpg" width="250" align="left"> StreetDeck Software</b>
</p>
<p>StreetDeck software is the ultimate must-have software for pimping out your car. StreetDeck includes, GPS Navigation, internet-enhanced navigation using Google Maps or Microsoft Live Local, Media Sync for your MP3 collection, games, and best of all, there's
 an SDK so it's fully customizable. </p>
<p><b>Cost</b>: $199.99 </p>
<p><b>Get it</b>: <a href="http://store.mp3car.com/ProductDetails.asp?ProductCode=SDK%2D005">
StreetDeck software on MP3Car.com</a> </p>
<p><b>Code it</b>: Streetdeck includes a <a href="http://www.streetdeck.com/developers-SDK.php">
SDK for programming using VB Script</a>, similar to Office VBA, and you can also build a .NET add-in in Visual Basic, C#, or C&#43;&#43; by
<a href="http://www.mp3car.com/wiki/index.php/Building_a_.Net_Addin_for_StreetDeck">
making it available through COM</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="198" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/estarling_new14.jpg" width="240" align="right"> eStarling Wi-Fi Email/RSS-Enabled LCD Frame</b><br>
This frame enables users to either run an email configuration or RSS feed configuration so you can choose to write an application that dynamically sends an email (say from a Webcam periodically), dynamically upload your pictures to Flickr, or create your own
 RSS feed with pictures.</p>
<p><b>Cost:</b> $249.99</p>
<p><b>Get it:</b> <a href="http://www.thinkgeek.com/electronics/cameras/7edc/">eStarling page on ThinkGeek.com</a><b></b></p>
<p><b>Code it:</b> You can use <a href="http://www.codeplex.com/FlickrNet">Sam Judson's Flickr .NET API</a> to easily programmatically send pictures to Flickr, or use the
<a href="http://photograham.me.uk/FlickrWebCam/">FlickrWebCam application</a> to have mom get real-time pictures of you from your Webcam or use the
<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebmailsmtpmailclasstopic.asp">
SmtpMail Class</a> to email a picture attachment in one line of code. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="162" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/300_115.jpg" width="240" align="left"> Home Theater and Lighting Controller 300 featuring OmniLinkTM<br>
</b>If you have your house setup for Z-Wave Home Automation, then you'll want this programmable remote that enables you to easily control your lights, home theater and more.
</p>
<p><b>Cost: </b>$599 </p>
<p><b>Get it:</b> <a href="http://www.monstercentral.com/Public/productPage_control.asp?pin=3368">
Home Theater and Lighting Controller 300</a><b></b> </p>
<p><b>Code it: </b>If you have the Z-Wave PC SDK with <a href="http://www.controlthink.com/zwavesdk.htm">
Intermatic Home Settings Lighting Control Starter Kit</a>, it includes the ControlThink SDK which enables you to easily program Z-Wave gear.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="173" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/01425i1475220014.jpg" width="240" align="right"> Windows</b><b> Media Center</b><b>
</b></p>
<p>Now is a great time to upgrade your old PC, like the <a href="http://configure.us.dell.com/dellstore/config.aspx?oc=dxps410f1&amp;cs=19&amp;dgvcode=ss&amp;c=US&amp;l=EN">
Dell XPS 410</a> a <a href="http://www.pcmag.com/article2/0,1895,2017294,00.asp">
PC Magazine Editor's Choice</a> that ships with Windows Media Center 2005, but includes a
<b>free</b> upgrade to <a href="http://www.microsoft.com/windowsvista/getready/editions/home_premium.mspx">
Windows Vista Home Premium</a> which includes a <a href="http://www.microsoft.com/windowsvista/experiences/magic.mspx">
revamped Media Center</a> with built-in streaming to your Xbox 360. </p>
<p><b>Cost</b>: $999 - $2,500 </p>
<p><b>Get it</b>: <a href="http://configure.us.dell.com/dellstore/config.aspx?oc=dxps410f1&amp;cs=19&amp;dgvcode=ss&amp;c=US&amp;l=EN">
Dell Online Store</a> </p>
<p><b>Code it</b>: Windows Vista Media Center has a much-improved API and <a href="http://blog.mediacentersandbox.com/PermaLink,guid,817c2b05-2a9e-47ac-80c9-1c4db5b26c18.aspx">
three different ways to mod Media Center</a> including HTML, XAML, and Media Center's own markup language using the
<a href="http://www.microsoft.com/downloads/details.aspx?familyid=7614FE22-8A64-4DFB-AA0C-DB53035F40A0&amp;displaylang=en">
Windows SDK</a>. </p>
</td>
</tr>
</tbody>
</table>
</p>
<h3>
<p><a class="" title="robots" name="robots"></a><b>Robotics</b> </p>
</h3>
<p>Mr. Roboto, please come to the front, your Roomba is waiting for you. This entire section lists robots and electronics that do everything from a vacuum cleaner to&nbsp;creating your own cellphones to GPS.
<table class="" cellspacing="5" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="">
<p><b><img height="210" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/remoterobotweb15.jpg" width="240" align="left"> Microbric Viper Robot
</b></p>
<p>The Microbric Viper robot enables you to build complex electronic devices with little or no prior electronics knowledge and no soldering required.
</p>
<p><b>Cost</b>: $89.99 </p>
<p><b>Get it</b>: <a href="http://www.microbric.com/page.php?sId=17">Microbric Viper Robot</a> and
<a href="http://iguanaworks.net/ir/serial/">Serial IR Transmitter/Receiver</a> </p>
<p><b>Code it</b>: Scott Hanselman walks through programming a <a href="http://msdn.microsoft.com/coding4fun/hardware/robotics/article.aspx?articleid=1192168">
Microbric Viper Robot</a> </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/GPSlogact_img15.jpg" width="200" align="right"> Lassen iQ FAT16 Datalogger - Complete Kit</b>
</p>
<p>Ever think you constantly walk in circles? Think you could optimize your routes if you only could map where your went? Use this GPS&nbsp;device to passively map your routes, all you need is an SD card added in. Then return to your computer, upload your data and
 see where you wandered. Great for mapping routes biking or hiking. </p>
<p><b>Cost:</b> $150.70 </p>
<p><b>Get It</b>: <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=671">
Spark Fun</a> </p>
<p><b>Code It</b>: From their <a href="http://www.sparkfun.com/datasheets/GPS/GPSLogger%20V1_0.pdf">
GPS Logger Datasheet</a>, you can get it to work with <a href="http://www.sparkfun.com/datasheets/GPS/Casey-Lunch.kml">
Google Maps </a>or create your own from the specification provided. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/2811816.gif" width="200" align="left"> Parallax Bluetooth Boe-Bot Kit for Microsoft Robotics Studio</b>
</p>
<p>Using <a href="http://msdn.com/robotics/">Microsoft Robotics Studio</a>, you can easily program the Boe-Bot Parallax kit over Bluetooth and best of all, the Robotics Studio team has negotiated a 15% discount on the BoeBot.
</p>
<p><b>Cost</b>: $198.77 after 15% discount </p>
<p><b>Get it</b>: <a href="http://www.parallax.com/detail.asp?product_id=28118">Parallax Boe-Bot Kit</a>
</p>
<p><b>Code it</b>: You can use Microsoft Robotics Studio which exposes services to control your
<a href="http://msdn.microsoft.com/robotics/learn/tutorials/setuphdwr/default.aspx#Parallax">
Parallax Boe-Bot Kit using Bluetooth</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/img_toothbundle_small15.jpg" width="227" align="right"> iRobot Roomba
</b></p>
<p>It's not just a vacuum cleaner it's also your programmable minion! You can use the clean-the-house excuse as your justification for getting this friendly house cleaner.
</p>
<p><b>Cost</b>: $229 or $339 depending on model </p>
<p><b>Get it</b>: <a href="http://www.roombadevtools.com/productcart/pc/viewPrd.asp?idcategory=9&amp;idproduct=23">
Roomba Red &#43; RooTooth bundle</a>, <a href="http://www.roombadevtools.com/productcart/pc/viewPrd.asp?idcategory=9&amp;idproduct=18">
Roomba Discovery &#43; RooTooth Bundle</a> </p>
<p><b>Code it</b>: You can use Microsoft Robotics Studio which includes built-in <a href="http://msdn.microsoft.com/robotics/learn/tutorials/setuphdwr/default.aspx#iRobot">
services for Roomba programming</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000E4FDAE.01.PT01._SS400_SCLZZZZZZZ_V37205325_15.jpg" width="240" align="left"> LEGO Mindstorms NXT</b>
</p>
<p>Lego Mindstorms NXT is Lego's newest release of their popular Mindstorms robotics and includes built-in three motor support and multiple sensor support including motion, touch, sound, and light.
</p>
<p><b>Cost</b>: $249.99 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/LEGO-4494799-Mindstorms-NXT/dp/B000E4FDAE/sr=8-1/qid=1165258587/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=toys-and-games">
Lego Mindstorms</a> on Amazon.com </p>
<p><b>Code it</b>: You can use Microsoft Robotics Studio which includes built-in services for
<a href="http://msdn.microsoft.com/robotics/learn/tutorials/setuphdwr/default.aspx#LegoNXT">
Lego Mindstorms NXT programming</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/GM862USBKit115.jpg" width="200" align="right"> GM862-GPS Evaluation Cell phone Kit – USB</b>
</p>
<p>Looking to write your own cell phone software? Just pop in your SIM card and get to it. Spark Fun has an evaluation cell phone board with GPS that can interface with your computer through USB.</p>
<p><b>Cost:</b> $274.65</p>
<p><b>Get It</b>: <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=280">
Spark Fun</a></p>
<p><b>Code It:</b> You can find the documentation for how to start interfacing with the board and Spark Fun provides a
<a href="http://www.sparkfun.com/commerce/product_info.php?products_id=281">Visual Basic example</a>.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/914_new_0115.jpg" width="138" align="left"> White Box Robotics PC-BOTs</b>
</p>
<p><a href="http://www.whiteboxrobotics.com/">Whitebox Robotics</a> has created the closest thing to having R2D2 at home with their newly released PC-BOTs. While it's the priciest of all robotics kits, it's hardware is no joke as it includes 1GB of RAM, an
 80GB hard drive, Windows XP Home, DVD Drive, and a wireless network card. </p>
<p><b>Cost</b>: $3,995 for the Developer kit, $4,995 to include the ever-so cool panels.
</p>
<p><b>Get it</b>: <a href="http://store.pcpowerzone.com/914pcspedro.html">914 PC-BOT</a>,
<a href="http://store.pcpowerzone.com/whhoro9pcro.html">9-Series PC-BOT</a> both from PCPowerzone
</p>
<p><b>Code it</b>: You can use Microsoft Robotics Studio to program Whitebox Robotics devices (<a href="http://msdn.microsoft.com/robotics/media/MSRS_WhiteBox_300K.wvx">video</a>).
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/GM862USBKit115.jpg" align="right"> Tira – Infrared Remote Control Receiver/Transmitter</b>
</p>
<p><a href="http://blogs.msdn.com/ericgu/">Eric Gunnerson</a> pointed us to Tira, or Transmitting InfraRed Adapter, which is a device that enables you to send and receive infrared signals to any IR device, say to control home automation, or to change your TV
 channel. Best of all, it's fully programmable so you can control when to send IR signals or what happens when it receives IR signals.</p>
<p><strong>Cost:</strong> $49.00</p>
<p><strong>Get it:</strong> Tira 2.1 on <a href="http://www.home-electro.com/buy_it.php">
Home Electronics</a></p>
<p><strong>Code it:</strong> Tira's Developer Page includes a <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/tira_api_win_latest.zip">
downloadable SDK</a> which includes a DLL that you can call from any .NET language or directly from C&#43;&#43;, once you install the
<a href="http://www.home-electro.com/tira_support.php#Downloads">Tira drivers</a>.<br>
</p>
</td>
</tr>
</tbody>
</table>
</p>
<h3><a class="" title="games" name="games"></a><b>Programmable Games</b> </h3>
<p>Think the final boss is too hard?&nbsp; &quot;Modify&quot; the game to give yourself that extra edge.&nbsp; As any Coding4Fun reader can tell you, games are more fun when you can mod them, and we've chosen our favorite moddable games that you can take and extend to your heart's
 content.&nbsp;
<table class="" cellspacing="5" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="">
<p><b><img height="225" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/rocketcmd_0.jpg" width="300" align="right">Rocket Commander</b>
</p>
<p><a href="http://abi.exdream.com/">Benjamin Nitschke</a>'s Rocket Commander is both fun and educational as Ben put together 10 step-by-step videos that show how to build a fully moddable an immersive 3D game using Managed DirectX and C#.
</p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/RocketCommanderv1.1.msi">
Rocket Commander Game</a> </p>
<p><b>Code it</b>: <a href="http://msdn.microsoft.com/coding4fun/gaming/arcade/article.aspx?articleid=997852">
Watch all 10 videos and download the source code</a> to start building your own RocketCommander mod.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><b><img height="180" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/clip_image00238.jpg" width="240" align="left"></b>Mech Commander 2</b>
</p>
<p>If you're interested in how real commercial games are built, look no further than Mech Commander 2, a real-time strategy game with full source code available released by Microsoft Game Studios. If you're a C&#43;&#43; developer you can learn how to build your own
 mods to Mech Commander in these three free webcasts </p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6d790cde-c3e5-46be-b3a5-729581269a9c&amp;DisplayLang=en">
Download the full source code</a> (1GB) </p>
<p><b>Code it</b>: Mike Klucher from the XNA team gave a 3-part on-demand Webcast series on how to mod Mech Commander 2that you should use as your starting point:
<a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032296433">
Part 1</a>, <a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&amp;EventID=1032296436">
Part 2</a>, and <a href="http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&amp;EventID=1032296439">
Part 3</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000067FDW.01._AA280_SCLZZZZZZZ_.jpg" width="200" align="right">World of Warcraft</b>
</p>
<p>If you haven't started playing World of Warcraft, you simply don't know what you're missing! With the
<a href="http://www.amazon.com/World-Warcraft-Expansion-Burning-Crusade/dp/B000BWZY7Q/sr=8-1/qid=1165263496/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Burning Crusade Expansion Pack</a> coming out on January 16<sup>th</sup>, now is a great time to join this ever-evolving world!
</p>
<p><b>Cost: </b>$19.99<b></b> </p>
<p><b>Get it: </b><a href="http://www.amazon.com/Blizzard-Entertainment-World-of-Warcraft/dp/B000067FDW/sr=8-2/qid=1165261682/ref=pd_bbs_sr_2/104-7127103-7243165?ie=UTF8&amp;s=videogames">World of Warcraft</a> on Amazon.com or pre-order the
<a href="http://www.amazon.com/World-Warcraft-Expansion-Burning-Crusade/dp/B000BWZY7Q/sr=8-1/qid=1165263496/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Burning Crusade</a><b></b> </p>
<p><b>Code it: </b>World of Warcraft scripting and add-ins are coded in LUA, which you can add
<a href="http://luaforge.net/projects/lualangpack/">Visual Studio 2005 support</a> (Standard and above), or check out
<a href="http://www.davidnikdel.com/projects/wow-360/">David Nikdel's WoW-360</a> Project, or
<a href="http://wowprofilers.com/Downloads/details/id=13.html">UniUploader</a> (<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/2_uu_250_settings_simple_thumb.jpg">screenshot</a>) which enables you to dynamically upload much more detailed players
 stats to a WowRoster portal. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000FIQAME.01._AA280_SCLZZZZZZZ_V60792105_.jpg" width="200" align="left">Neverwinter Nights 2 Limited Edition DVD</b>
</p>
<p>Neverwinter Nights 2 is a popular Dungeon and Dragons game that enables users to create their own worlds and adventures and includes a large community of users building games and dungeons for you to explore
</p>
<p><b>Cost</b>: ~$34.99 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/Atari-26503-Neverwinter-Nights-DVD-ROM/dp/B000E0XX9Q/sr=1-1/qid=1165418883/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Neverwinter Nights 2</a> on Amazon.com </p>
<p><b>Code it</b>: The Neverwinter Nights game builder is written in C# using the .NET Framework and you can write Game Builder plug-ins
<a href="http://www.nwn2.pwp.blueyonder.co.uk/ToolsetTuts/plugins/createplugins.html">
using any Visual Studio 2005 language</a> including VB, C#, or C&#43;&#43;. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000BC38K6.01._AA280_SCLZZZZZZZ_.jpg" width="200" align="right">Civilization IV</b>
</p>
<p>Sid Meier's Civilization IV is an unlike the typical Age of Empires battle strategy game in that players can use everything from diplomacy to technology to advance their civilization.
</p>
<p><strong>Cost:</strong> $39.99 or $19.99 for the expansion </p>
<p><strong>Get it:</strong> <a href="http://www.amazon.com/2K-Games-710425217128-Meiers-Civilization/dp/B000BC38K6/sr=1-1/qid=1165263585/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Civilization IV</a> on Amazon.com or <a href="http://www.amazon.com/Sid-Meiers-Civilization-IV-Expansion/dp/B000FHGA4S/sr=1-2/qid=1165263705/ref=pd_bbs_sr_2/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Warlords Expansion Pack</a> </p>
<p><strong>Code it:</strong> Civilization IV includes a <a href="http://civilization4.net/files/modding/PythonAPI_original/&amp;&amp;DI=293&amp;IG=6c43348add274a70b71a72bf022ec5c6&amp;POS=1&amp;CM=WPU&amp;CE=1&amp;CS=AWP&amp;SR=1">
Python and C&#43;&#43; SDK</a> and, while we haven't tried it, you may also be able to call the DLL from VB and C#.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="78" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/header17.jpg" width="240" align="left"> Half Life 2 Holiday 2006 Collection</b>
</p>
<p>The Half Life 2 Holiday 2006 Collection includes Counter-Strike: Source, Half-Life 2, Half-Life 2: Deathmatch, Half-Life 2: Episode One, Half-Life Deathmatch: Source, Half-Life: Source. The good news is that you can now officially use
<a href="http://msdn.microsoft.com/vstudio/express/visualc/">Visual C&#43;&#43; 2005 Express Edition</a> for your Half Life 2 mods.
</p>
<p><strong>Cost:</strong> $49.95 </p>
<p><strong>Get it:</strong> <a href="http://steampowered.com/v/index.php?area=package&amp;SubId=201&amp;">
Holiday 2006 Collection</a> </p>
<p><strong>Code it:</strong> <a href="http://developer.valvesoftware.com/wiki/SDK_Docs">
Valve's online wiki SDK</a> docs include everything you need to get started including steps to get
<a href="http://developer.valvesoftware.com/wiki/Compiling_under_VS2005">Visual Studio 2005 working</a>.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000GCJ6MK.01._AA280_SCLZZZZZZZ_V41077232_.jpg" width="200" align="right">Flight Simulator X Deluxe DVD</b>
</p>
<p>While Flight Simulator X's hardware requirements are quite big, the graphics on Windows Vista using DirectX 10 are nothing short of breathtaking.
</p>
<p><b>Cost</b>: $49.99 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/Microsoft-Flight-Simulator-Deluxe-DVD/dp/B000GCJ6MK/sr=1-1/qid=1165264203/ref=pd_bbs_sr_1/104-7127103-7243165?ie=UTF8&amp;s=videogames">
Flight Simulator X</a> on Amazon.com </p>
<p><b>Code it</b>: The Deluxe edition of Flight Simulator X includes a new <a href="http://fsinsider.com/Community/Developers-Corner/About-the-SDK.htm">
SDK called SimConnect</a> that you can use to manipulate and control the Flight Simulator world using VB, C#, or C&#43;&#43;.
</p>
</td>
</tr>
</tbody>
</table>
</p>
<h3><a class="" title="tools" name="tools"></a><b>Software Tools</b> </h3>
<p>Tools to help make video games, robots and webpages oh my! Every good craftsmen needs their tools and we're no exception.&nbsp; Below is a list of tools and tool add-on's that will make anyone's life that much easier.
<table class="" cellspacing="5" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="">
<p><b>Microsoft Robotic Studio</b> </p>
<p>If you have LEGO Mindstorm RCX or NXT, you actually can control them through Microsoft Robotic Studio. It can control far more than just LEGO too, it is able to control
<a href="http://msdn.microsoft.com/robotics/learn/tutorials/setuphdwr/default.aspx">
far more</a> and comes full of examples. Instead of having to deal with low level coding to deal with everything on your robots, one can write a wrapper then have the Robotic Studio do all the heavy lifting!
</p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://msdn.microsoft.com/robotics/">Microsoft Robotics Studio</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b>Microsoft Visual Studio Express Editions</b>&nbsp;<b></b> </p>
<p>You can get everything someone needs to code in 6 different flavors. Web Development, SQL Server, Visual Basic, C#, C&#43;&#43;, and J# Editions are available for download from Microsoft. They are the perfect gift for the hobbyist, novice or student developer that
 is looking for lightweight, easy to learn and use tools. Each edition is able to run side by side on your computer with other installations so you can collect them all!
</p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://msdn.com/express">Visual Studio Express Editions</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="67" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/XNA_Hero_Banner15.jpg" width="240" align="left"> Microsoft XNA Game Studio Express</b>
</p>
<p>Think you are cut out to build video games? Using Microsoft Game Studio Express you can try out building video games that can be played. If you have an Xbox 360, you can actually transfer the game you created to it too! You can show off to your friends the
 games you created (Don't forget to add in a god mode for yourself). </p>
<p><b>Cost</b>: Free for Windows/$99 year for Xbox porting and content subscription
</p>
<p><b>Get it</b>: <a href="http://msdn.microsoft.com/directx/XNA/default.aspx">XNA Game Studio Express</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="177" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/pdn30_camaro_thumb14.jpg" width="240" align="right"> Paint.NET</b>
</p>
<p>Paint.NET is a free image and photo manipulation software that is open source too! Paint.NET is written in .NET 2.0 and mostly is c# and has a small amount of C&#43;&#43;. It supports layers, unlimited history, a simple and intuitive interface, and is loaded with
 special effects. While it isn't an Adobe Photoshop replacement, it is simple and powerful enough for someone on a budget.
</p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://www.getpaint.net/">GetPaint.NET</a> </p>
<p><b>Code it</b>: Paint.NET has a managed API that you can write plug-ins for using any managed language as shown in this
<a href="http://www.codeproject.com/csharp/PdnNoiseEffect.asp">Code Project tutorial</a> by Dennis Dietrich.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="160" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/Reflector16.png" width="160" align="left"> Reflector for .NET</b>
</p>
<p>Do you have a program that is written in .NET and you can't figure out how it they preformed a certain task? You thought you fixed that bug but it is still happening after you deployed it. Use Reflector it to see how they pulled it off and verify deployments!
 Reflector is capable of showing the source code of DLL's in .NET 1.1 and 2.0 in both Visual Basic and Visual C#. What is displayed isn't a 1 to 1 code representation, instead what the ILM runs, however one can figure out how certain tasks are accomplished
 and should be able to gauge what is happening. </p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://www.aisto.com/roeder/dotnet/">Reflector for .NET</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/thumb_ts2_0116.gif" width="187" align="right"> TeamSpeak</b>
</p>
<p>If you're a gamer, you've likely used TeamSpeak or Ventrilo to have live chat while playing online games. For us, the choice between TS and Vent came down to who has the API's, and it was clear that TeamSpeak is the way to go given its built for extensibility
</p>
<p><b>Cost</b>: Free </p>
<p><b>Get it</b>: <a href="http://www.goteamspeak.com/">TeamSpeak</a> </p>
<p><b>Code it</b>: You can find a couple of .NET TS samples including <a href="http://www.peterbarrette.com/">
Peter Barette's</a> <a href="http://forum.goteamspeak.com/showthread.php?t=23789">
C# Chat Text application</a> or Oliver Flint's <a href="http://forum.goteamspeak.com/showthread.php?t=33995">
TSDisplay.NET</a> (<a href="http://www.oliverflint.co.uk/tsdisplay.net/default.aspx?hostname=voice.teamspeak.org&amp;serverport=10050&amp;queryport=51234">live demo</a>) using ASP.NET
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/display_settings15.png" width="215" align="left"> UltraMon</b>
</p>
<p>If your coder has multiple monitors, you may think about getting them UltraMon. UltraMon extends out the Windows Taskbar across all the monitors along with the ability to create shortcut keystrokes to send windows to different monitors. In addition, it allows
 for each monitor to have a different display profile. Plus it has scripting support!
</p>
<p><b>Cost</b>: $39.95 </p>
<p><b>Get it</b>: <a href="http://www.realtimesoft.com/ultramon/">UltraMon</a> </p>
<p><b>Code It</b>: Ultramon has a <a href="http://www.realtimesoft.com/ultramon/developers.asp">
SDK </a>along with <a href="http://www.realtimesoft.com/ultramon/tour/scripting.asp">
scripting support</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="240" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/B000BT8TRQ.01._AA280_SCLZZZZZZZ_16.jpg" width="240" align="right"> Microsoft Visual Studio 2005</b>
</p>
<p>If developing for mobile applications or want to use 3<sup>rd</sup> party Visual Studio add-ins, you'll need to upgrade to Visual Studio Standard or Professional Edition. Visual Studio Express Editions projects will seamlessly work with the full versions
 of Visual Studio. </p>
<p><b>Cost</b>: $179 - $679 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/Microsoft-Visual-Studio-Standard-2005/dp/B000BT8TRQ/sr=8-1/qid=1165270874/ref=pd_bbs_1/104-7127103-7243165?ie=UTF8&amp;s=software">
Standard Edition</a> (<a href="http://www.amazon.com/Microsoft-Visual-Studio-Standard-Upgrade/dp/B000BT8TS0/sr=8-2/qid=1165270874/ref=pd_bbs_2/104-7127103-7243165?ie=UTF8&amp;s=software">upgrade price</a>),
<a href="http://www.amazon.com/Microsoft-Visual-Studio-Professional-2005/dp/B000BTA4LU/sr=1-1/qid=1165270933/ref=pd_bbs_1/104-7127103-7243165?ie=UTF8&amp;s=software">
Professional Edition</a> (<a href="http://www.amazon.com/Microsoft-Visual-Studio-Professional-Upgrade/dp/B000BT8TRG/sr=1-2/qid=1165270933/ref=pd_bbs_2/104-7127103-7243165?ie=UTF8&amp;s=software">upgrade price</a>)
</p>
<p><b>Code it</b>: <a href="http://www.microsoft.com/downloads/details.aspx?familyid=7e0fdd66-698a-4e6a-b373-bd0642847ab7&amp;displaylang=en">
Visual Studio 2005 includes a free SDK</a> that you can use to create your own add-ins or even your own programming language.
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="54" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/statusIndicator16.png" width="298" align="left"> JetBrains ReSharper
</b></p>
<p>ReSharper is an add-in to Visual Studio 2003 and 2005. ReSharper provides an intelligent coding assistance, on-the-fly error highlighting (no more recompiling), additional searching and navigation features, unit testing, and realy time analysis of code warnings
 / errors … the list goes on and on. JetBrains ReSharper is free to try out for 30 days, $200 for a full copy.
</p>
<p><b>Cost</b>: $200 </p>
<p><b>Get it</b>: <a href="http://www.jetbrains.com/resharper/">JetBrains ReSharper</a>
</p>
<p><b>Code it</b>: ReSharper has an <a href="http://www.jetbrains.com/resharper/features/openAPI.html">
open API</a> which you can use to modify how your code is refactored. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="87" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/logo16.gif" width="200" align="right"> WebSuperGoo ABCpdf</b>
</p>
<p>PDFs are everywhere and progressively more applications are needing them. AbcPDF allows a developer to easily manipulate or create dynamic PDFs. It is fully multithreaded and is loaded with stock full of examples to figure out everything. Past just normal
 PDF generation, it also can do HTML to PDF generation. </p>
<p><b>Cost</b>: $328, <a href="http://www.websupergoo.com/linktous.htm">Possibly free if you link to them</a>.
</p>
<p><b>Get it</b>: <a href="http://www.websupergoo.com/abcpdf-1.htm">WebSuperGoo</a>
</p>
<p><b>Code it</b>: Here is their <a href="http://www.websupergoo.com/helppdf5net/default.html">
API for ABCpdf</a>. </p>
</td>
</tr>
</tbody>
</table>
</p>
<h3><a class="" title="topten" name="topten"></a><b>Top 10 Cool Presents for Developers</b>
</h3>
<p>What are your top 5 favorite ... wait, this isn't a movie.&nbsp;&nbsp;&nbsp;Here are what Coding4Fun would deem Top 10 cool presents for Coders.&nbsp; Some range from a magazine subscription to DNA.&nbsp; Each one is
<table class="" cellspacing="5" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="">
<p><b><img height="168" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/optimus_mini14.jpg" width="240" align="right"> Optimus mini three keyboard</b>
</p>
<p>Wondering how much CPU or RAM your system is taking up? How about what the weather is? The Optimus mini three keyboard allows you to view what is going on in the world with animation.
</p>
<p><strong>Cost:</strong> $159.99 </p>
<p><strong>Get It:</strong> <a href="http://www.thinkgeek.com/computing/input/88ee/">
Optimus mini three keyboard </a>on ThinkGeek </p>
<p><strong>Code It:</strong> The Optimus Mini has a <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/OptimusMiniC_23Example.zip">
c# library </a>to use along with other languages which can be <a href="http://www.artlebedev.com/everything/optimus-mini/developers/">
found here</a>. </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="97" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/safari7.jpg" width="192" align="left"> O'Reilly Safari Books Online Subscription</b>
</p>
<p>Wonder why FireFox and Internet Explorer's JavaScript Dom acts different for the same property?&nbsp; Me too.&nbsp; That is why I have a ton of O'Reilly books at my desk.&nbsp; With their online solution, one has the entire library to their disposal.&nbsp; No need to go through
 pages upon pages of search results! </p>
<p><strong>Cost:</strong> $39.99 per month</p>
<p><strong>Get It:</strong> <a href="http://safari.oreilly.com/">Safari Books Online</a></p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="60" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/make25.gif" width="155" align="right"> MAKE Magazine</b>
</p>
<p>MAKE magazine is a magazine that actually encourages you to break your warranties. Wonder how to do modify your camera to do strobe photography, they'll explain how to create a rig to create. How about a toy gun alarm clock? A jet made out of a jar? A 5-in-1
 network cable? These are just a few of many things they show people how to make in their quarterly magazine. In addition to their magazine, they have a great blog over at
<a href="http://makezine.com/blog/">http://makezine.com/blog/</a>. </p>
<p><b>Cost</b>: Register your copy of Visual Studio Express and get 5 issues for the price of 4.
</p>
<p><b>Get it</b>: <a href="http://makezine.com/magazine/">Make Magazine</a> </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/515767B_p18.jpg" width="200" align="left"> Color Call</b>
</p>
<p>You're in the middle of a meeting and you're up on the whiteboard. The phone rings, should you answer? Find out easily with the Color-Call Caller ID System which enables you to setup which phone numbers should correspond to up to four different colors.&nbsp;
</p>
<p><b>Cost</b>: $29.99 </p>
<p><b>Get it</b>: <a href="http://www.brookstone.com/store/product.asp?pid=515767&amp;wid=100&amp;cid=59&amp;sid=630&amp;search_type=subcategory&amp;prodtemp=t1">
Color-Call Caller ID</a> from Brookstone </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/buckle1_5B4_5D.jpg" align="right"> Scrolling LED Belt Buckle</b>
</p>
<p>Nothing says geek chic like a scrolling LED Belt Buckle.&nbsp; It can hold up to six messages at a time with each message containing 256 characters. You can see pictures of our very own
<a class="" href="http://blogs.msdn.com/saraford">Sara Ford</a> wearing the <a class="" href="http://blogs.msdn.com/danielfe/archive/2006/12/13/sara-ford-shows-off-the-scrolling-led-belt-buckle.aspx">
Scrolling LED Belt Buckle</a>. </p>
<p><b>Cost</b>: $29.99 </p>
<p><b>Get it</b>: <a href="http://www.scrollingbuckle.com/">Scrolling Belt Buckle</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="132" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/usb_hub_DX_0317.jpg" width="150" align="left"> Self Destruction Button USB Hub</b><br>
You can't go wrong accessorizing your office with this custom USB Hub that would be perfect for Dr. Evil.&nbsp; Just remember, do not press the red button no matter how much you want to.
</p>
<p><b>Cost</b>: $64.66 </p>
<p><b>Get it</b>: <a href="http://www.geekstuff4u.com/product_info.php?manufacturers_id=&amp;products_id=404">
Self Destruction USB Hub</a> from GeekStuff4u.com </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="150" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/podcastkit_USBweb113.jpg" width="118" align="right">Alesis USB Podcasting Kit</b>
</p>
<p>For your inspiring Podcaster, the Alesis kit takes the guesswork out of podcasting. It comes with an 8-Channel USB Mixer, dynamic microphone, stand, and headphones. It also comes with 30 days of free hosting for your podcasts.
</p>
<p><b>Cost</b>: $250 </p>
<p><b>Get it</b>: <b><a href="http://www.alesis.com/product.php?id=99">Alesis USB Podcasting Kit</a></b>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="119" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/fs2004_40015.jpg" width="240" align="left"> Matrox DualHead2Go / TripleHead2Go</b>
</p>
<p>Afraid which new video card is right for you or are you on a laptop? The Matrox allows a coder to have up to three monitors with the TripleHead2Go (two with the DualHead2Go) with only one video input. Multiple monitor support is build into Windows. While
 having that many monitors may seem a tad excessive, they do help boost productivity and help the keep workspace less messy.
</p>
<p><b>Cost</b>: $169-$299 </p>
<p><b>Get it</b>: <a href="http://www.matrox.com/graphics/en/gxm/products/">Matrox Products</a>
</p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="156" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/pic_bedroom_orange14.jpg" width="240" align="right"> DNA Portrait</b>
</p>
<p>The ultimate in personalized artwork, this portrait is created by using your actual DNA and comes in fun color choices like Firesky, Ice, Citylights, and Citron
</p>
<p><b>Cost</b>: $390 for 18” x 24”, $490 for 24” x 36” and $790 for 36” x 54” </p>
<p><b>Get it</b>: <a href="http://www.dna11.com/">DNA11</a> </p>
</td>
</tr>
<tr>
<td class="">
<p><b><img height="200" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/320468816.jpg" width="200" align="left"> 22”&#43; wide screen monitors</b>
</p>
<p>What is better than having dual monitors? Dual 22” widescreen monitors. Bigger monitors aid in the ability to read more and have been shown to have
<a href="http://www.nytimes.com/2005/10/16/magazine/16guru.html?ei=5090&amp;en=c8985a80d74cefc1&amp;ex=1287115200&amp;adxnnl=1&amp;partner=rssuserland&amp;emc=rss&amp;pagewanted=all&amp;adxnnlx=1129521853-ar/Jp1qnf0XCl9MGUEiLGA">
boost productivity 10 to 44%</a>. Please verify the graphic card / device they have can support a monitor of this size.
</p>
<p><b>Cost</b>: $400-$500 </p>
<p><b>Get it</b>: <a href="http://accessories.us.dell.com/sna/productlisting.aspx?c=us&amp;category_id=6198&amp;cs=19&amp;l=en&amp;s=dhs">
Dell</a> or NewEgg lists of <a href="http://www.newegg.com/Product/ProductList.asp?Category=19&amp;N=2010190020&#43;1301919996&#43;1109917865&amp;Submit=ENE&amp;SubCategory=20">
22”-23”</a>&#43; or <a href="http://www.newegg.com/Product/ProductList.asp?Category=19&amp;N=2010190020&#43;1301919996&#43;1109909240&amp;Submit=ENE&amp;SubCategory=20">
23”&#43; </a></p>
</td>
</tr>
<tr>
<td class="">
<p><b><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1228621/1878739026.01._AA240_SCLZZZZZZZ_V57043853_.jpg" align="right"> C&#43;&#43; Programming Books</b>
</p>
<p>Every programmer needs C&#43;&#43; books. Some need a C&#43;&#43; GUI Programming Guide while others need a primer book.&nbsp; The gift of reference books is always a good bet.
</p>
<p><b>Cost</b>: $30 to $50 </p>
<p><b>Get it</b>: <a href="http://www.amazon.com/C%2B%2B-Primer-Plus-5th-Sams/dp/0672326973/sr=1-1/qid=1165987086/ref=pd_bbs_sr_1/102-0481056-4888969?ie=UTF8&amp;s=books">
Amazon</a></p>
</td>
</tr>
</tbody>
</table>
</p>
<h3><b>Happy Holidays From Coding4Fun!</b></h3>
<p>Now only if I can get someone to get me all these gadgets, software, and toys, I mean highly educational, non-fun&nbsp;devices.&nbsp; Thanks for reading and if you think we've missed any awesome holiday gift, please
<a href="mailto:code4fun@microsoft.com">Email us</a> and we'll get it added to our list.&nbsp; If you like the guide,
<a href="http://www.digg.com/submit?url=http://msdn.microsoft.com/coding4fun/archive/article.aspx?articleid=1228621&amp;title=Holiday%20Gift%20Guide%202006">
Digg Us</a>. </p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:520639481d1d4b0e972f9e7600d76541">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/Holiday-Gift-Guide-2006</comments>
      <itunes:summary>
Tired of giving socks every year to your favorite engineer or technology elitist? Coding4Fun has come up with a holiday gift guide of items that are sure to make them glee with joy. We&#39;ve cranked up the geek-factor and have tried to come up with the biggest
 list of programmable presents on the Web! &amp;nbsp;If you like the guide, 
Digg Us.  
Do you know of a programmable present that wasn&#39;t listed here? 
Email us and we&#39;ll get it added to our list.  
The holiday guide is broken down into 5 sections. Programmable Hardware and Gadgets, Programmable Robots, Programmable Games, Cool Software Tools, and Top 10 Presents for Developers
 
 
Programmable Hardware and Gadgets

Enjoy tinkering?&amp;nbsp; Think that the orginary can be modified to do something different with a little effort?&amp;nbsp; This entire section of gifts are items one can program. The range from webcams to disco floor parts to cell phones.




 Wireless Xbox 360 Controller for Windows
 
The newly released wireless controller can be used to play both Xbox 360 and Windows PC games, and best of all, you can program with it too. In fact, certain applications, like Virtual Earth 3D already include support for the Xbox 360 controller so you&#39;ll
 be able to use your controller to literally fly around the world!  
Cost: $37.99  
Get it: 
Wireless Xbox 360 Controller on Amazon.com  
Code it: The XNA Framework includes full support for Xbox 360 controllers for Windows and the Web using the XInput class. To learn the basics of programming your XNA controller, check out Paul Stubbs excellent
Xbox 360 controller article as well as the newly updated version ported to work with the
XNA Framework.
 



 IrMan
Infrared man (Irman) is a small device that allows you to control your PC with the remote from your TV, VCR, CD or Stereo. You can use it to programmatically control any applications on your PC!
Cost: $40
Get it: IrMan Home Page
Code it: Duncan MacKenzie, the first Coding4Fun author, posted a 
classic article on using an I</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/Holiday-Gift-Guide-2006</link>
      <pubDate>Thu, 07 Dec 2006 02:09:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/Holiday-Gift-Guide-2006</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1228621_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/1228621_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Clint Rutkas</dc:creator>
      <itunes:author>Clint Rutkas</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/blog/Holiday-Gift-Guide-2006/RSS</wfw:commentRss>
      <category>events</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Kid&#39;s Programming Language: Santa&#39;s Gifts</title>
      <description><![CDATA[<span id="c4fmetadata">
<table class="" cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td class="" width="50">&nbsp;</td>
<td class=""><span class="entry_description">This article is in a series in which we are recreating classic video games in KPL code—in this article, Santa's Gifts</span></td>
</tr>
<tr>
<td class="" colspan="2">
<div class="entry_author">Larry Serflaten</div>
<div class="entry_company"><a></a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Easy</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
1-3 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://www.kidsprogramminglanguage.com/">Kid's Programming Language</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1183279/SantasGifts_KPL.msi">Download</a>
<ul>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p>&nbsp;</p>
<p>One way to get started programming games is to pick a popular game that is fun to play, that has all of the rules already made up, and develop a program that just transfers that game to the computer. Doing that much will help beginning programmers raise
 their programming skills as they code and tweak their own rendition of the fun game. A Christmastime example of that method accompanies this article, programmed using a relatively new programming language designed to help beginners gain programming skills.
 Kids' Programming Language (KPL) is a simplified but modern programming language and development environment that introduces beginners to the basic programming concepts. Just as many famous sports players start out playing sports while they're young, KPL is
 a tool kids can use to program computers while they are still young. With KPL being a free download, it is well within their budget!
</p>
<p>The referenced KPL game is called Santa's Gifts, but it is very similar in nature to the popular Tetris genre of falling objects that need to be properly positioned for optimum points. The rules and game play is simple to learn, but strategically placing
 the falling objects will give the advanced players higher scores. Using the arrow keys to move the objects from side to side allows the player to position them where they want. Pressing the Down arrow key lets the object drop. When three or more objects of
 the same type are positioned together, they form a group that is removed from the drop zone, adding some number of points to the player's score. The strategic part of the game is to try to build groups of four or five items, or to try to cause chain reactions
 where the removal of one group causes another group to be formed and removed. Both of those methods yield more points than just creating groups of three. There is a time aspect to the play as well. The player can't take all day to decide where to position
 the next item. The time to decide is decreased as the levels progress, which will cause the player to have to recognize certain patterns that score better, decide on a strategy to complete those patterns, and go for it in a relatively short period of time.
</p>
<h4><b>Do some functional testing</b></h4>
<p>If at all possible, create the game on a piece of paper first, or use pieces of paper to represent objects in the game, and set it all out on a table top to run through the game a few times. Get input and feedback from other game players, and check it over
 to see if the rules are easy to learn, and if there is opportunity for advanced players to gain an advantage at beating the game. You'll want to iron out the problems and any other conflicts on paper as much as possible before they become problems while writing
 the game code. It is much easier to change a rule on paper than retrofit a new rule into the computer program. For the simpler games, some may do all of that planning and checking in their head, as I know I did on more than a few occasions, but it cannot be
 stressed enough to do the planning first, to avoid scrapping or re-writing whole sections of code.
</p>
<p>As I mentioned before about the sports heroes playing the sport while they were young, it takes many years to develop the skills needed to play professionally. They certainly didn't do everything right while they were learning. Expect a little of that in
 yourself. Those professional players didn't quit, and they kept going until they made it to the top. That sort of perseverance is what you'll need to get past the few failures that may happen. If you can't get the programming to work one way, try another route.
 Don't be discouraged about starting a project over, or trying to do it in a new way, especially as you begin to develop your skills. Mentors, or others familiar with the tools you are using, are a good source of information and can help you find the right
 path, instead of the trial and error mode of learning. </p>
<h4><b>In summary:</b> </h4>
<p>Begin a new game by writing the storyline. Describe where the player is coming from, and where he has to get to. Include the objects or obstacles he will meet along the way, and then move on to creating the rules of engagement. Pretend your table top is
 your computer screen and cut out pieces of paper to represent the objects the player will see on the screen. Play the game several times, taking notes of any conflicts or other ideas that will be included in the game. Refine the movements and game play such
 that a child can learn it fairly quickly and figure out how to add something the advanced players can use to gain an upper hand. Begin coding the program by adding just a shell that shows how the screen will look, and provide the means to start the game, and
 whatever needs to happen to end the game. Then start adding routines to get the game up and running. For example, if there is going to be five levels to the game where each level shows a different screen, then start with a loop in your main procedure that
 iterates 1 to 5, that will call the routines to draw the different screens as they are needed. Just get the basic shell in place as the starting point. Then add the objects that make up the game, such as adding the player to the screen, and allowing him to
 move in each of the levels. Then add the objects to the different screens, or whatever the player will be interacting with, and so on. Piece by piece, build the game by providing the skeleton and then adding the meat. You can do that on the whole game level,
 and on a finer level for different routines. Be mindful of saving your work at different milestones, and then working with a copy from there. You should save your work periodically, at various milestones, so that if the day happens where your file gets corrupted,
 or you code yourself into a corner, you can go back and make another copy of the last milestone and get back into it, instead of having to start all over from scratch.
</p>
<h4><b>About the game listing...</b></h4>
<p>For those who are going to be looking at Santa's Gifts source code, I want to point out a couple techniques that might be useful in your own games. The first is in translating a one-dimensional array into something that represents the two-dimensional screen;
 specifically, checking for objects that are in the immediate area of the player. The second is the method I used to create the fading points that are shown when groups are removed from the play area. For people who do not yet have a copy of KPL, you can learn
 more about it from <a href="http://www.kidsprogramminglanguage.com/">www.kidsprogramminglanguage.com</a>.
</p>
<p>KPL only supports arrays of a single dimension, so representing two-dimensional space takes a bit of doing. In particular, X and Y coordinates have to be translated into an Index value that points to an element in the array. In general terms, transposing
 between the two can be shown by the following code: </p>
<pre><code></code></pre>
<pre class="csharpcode"><span class="rem">// XMax is the maximum extent of the 2D space in the horizontal direction </span>
X = Index Mod XMax
Y =  Index / XMax
Index = X &#43; (Y * XMax)
</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>That works when the arrays begin with the first element at index 0. Currently KPL begins its arrays at an index of 1, (but that may change!), so the above code becomes:
</p>
<pre><code></code></pre>
<pre class="csharpcode">X = (Index - 1) Mod XMax<br>Y = (Index - 1) / XMax<br></pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Because the KPL single dimension array uses the Index value to reference its elements, it is more often easier to work with the 2D grid cells by manipulating the Index value, instead of the X and Y values. When the game code has to check for any objects
 in a grid cell adjacent to the player, it can test the next cell to the right by adding 1 to the player's Index value, and the cell to the left by subtracting 1 from the player's Index value. Similarly, to check the next cell above or below the player, XMax
 can be subtracted or added (respectively) to the player's Index value. Of course boundary checks are needed to avoid looking above the top edge or below the bottom edge, which are easily handled by testing the adjusted Index value to be between zero and the
 upper bound of the KPL array. But boundary checks on the right or left edge are more difficult to handle when using the Index value.
</p>
<p>To represent a checkerboard, for example, the KPL array would hold elements indexed from 1 to 64 which represent the 8 X 8 grid. A value at Index 1 is the same value for the grid coordinate (0, 0) or (1, 1) depending on which value you prefer to begin numbering
 with. Assuming the upper left cell is at (1, 1) then the next cell to the right of the upper left cell is at (2, 1) with an index of 2, (3, 1) is Index 3, (4, 1) is Index 4, and so on to the upper right cell which is at (8, 1) corresponding to the KPL array
 Index value of 8. The cell below the upper left corner cell is at (1, 2) which equates to an index value of 9. And so it goes with the Index value incrementing by one as the grid cells are traversed left to right and top to bottom.
</p>
<p>The trouble arises when the player is at the right or left edge, because adding one when the player is at the right edge, or subtracting one when the player is at the left edge will actually be referencing a cell from a different row. If the player is at
 cell (8, 1) or Index 8, then the code must not add 1 for the adjacent test because the player is at the edge; there is no cell at (9, 1).
</p>
<p>One way to avoid overstepping the boundary is to convert the Index value back into its X and Y coordinates so you can test X in comparison with XMax. But there may be many places where such a check is made, which would require many such conversions. Even
 if centrally located in a function somewhere, the code must be called, which takes some amount of time, repeatedly, over and over, every time such a test is needed.
</p>
<p>The method I used instead of repeated boundary conversions effectively adds a blank cell to the right edge of the 2D space. The KPL array was lengthened to account for there being a cell there, but it was never used for player movements. What it did was
 avoid the need for special case tests for the right or left edges. Upper and lower boundaries were still in place, but adding that extra cell meant I could simplify the code used to test the adjacent cells. I could safely increment the Index and check for
 objects for tests to the right, and I could safely decrement the Index value and check for objects to the left because there was that extra cell at the end of each row. Tests to the left when the player was at the left edge found a blank cell (obviously no
 object there), and tests to the right when the player was at the right edge also found a blank cell. With a little tradeoff in memory usage, I simplified my code considerably. Check out the
<b>CheckAdjacent</b> routine in the game source code. It turned out to be nice uniform code that tests for upper or lower boundaries ahead of comparing the objects for similarity. That is the code used to find all the members of the same type for inclusion
 into a grouping. If a similar gift is found in an adjacent cell, then adjacent cells to that one have to checked for further similar gifts. If checking there finds one in an adjacent cell, then that new one has to have its adjacent cells checked as so on,
 to find all the gifts of the same type that are next to each other. You'll note the repetitive nature of those tests made for a good place to use a recursive call (where some routine calls itself to complete its task), but recursion is entirely another topic,
 worthy of its own detailed discussion. </p>
<p>The second technique I wanted to mention allowed me to print text on the screen and have it fade away. It was just one of those what-if discoveries I made while looking for a simple way to show the points for the currently removed group, without it remaining
 on the screen too long. I had used the Status area, but I didn't like how the points shown there seemed to be more like debugging information and not really a part of the game. What I did was take part of the screen image and make it partially transparent
 using my favorite paint program. I placed that translucent image in a sprite and used KPL's
<b>StampSprite</b> method to transfer the image to the screen. I found that I could print text to that area, and periodically stamp that translucent sprite over the text which would gradually erase the text. I also used that method to provide the BRIGHTNESS
 constant you'll find near the top of the listing. It controls the brightness of the background image. I didn't want the background image to be so bright as to distract from the animated gift images. I wanted a kind of lower-contrast image to avoid that distraction.
 When I found the translucent sprite could be stamped in place several times to build up to being opaque, I decided that would be how I could lower the contrast of the background, by making the background sprite translucent. It has to be translucent over some
 color or shade, and that is what the BRIGHTNESS value controls: it decides the brightness of the gray color used behind the translucent background image.
</p>
<p>One final note on playability. On faster computers you may find that the program runs way too fast to play. That is the way I have grown accustomed to designing programs. Design them so they can play faster than the human can because the computer can easily
 be slowed down to let the human catch up, but it is usually more difficult (or nearly impossible) to try to speed up a program when it runs too slow. Also near the top of the listing is a TIMEDELAY constant you can adjust to slow down the game more to your
 liking and abilities. </p>
<p>I hope you enjoy playing Santa's Gifts, and that you'll take up writing and sharing programs of your own design! If you need beta testers for your KPL program, or have questions or comments, do visit the KPL forums available from links in the help menu of
 the KPL environment. </p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:afb3a5f955354034ba589e7600d79762">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Santas-Gifts</comments>
      <itunes:summary>



&amp;nbsp;
This article is in a series in which we are recreating classic video games in KPL code—in this article, Santa&#39;s Gifts



Larry Serflaten


Difficulty: Easy
Time Required: 
1-3 hours
Cost: Free
Software: Kid&#39;s Programming Language
Hardware: 
Download: Download








&amp;nbsp; 
One way to get started programming games is to pick a popular game that is fun to play, that has all of the rules already made up, and develop a program that just transfers that game to the computer. Doing that much will help beginning programmers raise
 their programming skills as they code and tweak their own rendition of the fun game. A Christmastime example of that method accompanies this article, programmed using a relatively new programming language designed to help beginners gain programming skills.
 Kids&#39; Programming Language (KPL) is a simplified but modern programming language and development environment that introduces beginners to the basic programming concepts. Just as many famous sports players start out playing sports while they&#39;re young, KPL is
 a tool kids can use to program computers while they are still young. With KPL being a free download, it is well within their budget!
 
The referenced KPL game is called Santa&#39;s Gifts, but it is very similar in nature to the popular Tetris genre of falling objects that need to be properly positioned for optimum points. The rules and game play is simple to learn, but strategically placing
 the falling objects will give the advanced players higher scores. Using the arrow keys to move the objects from side to side allows the player to position them where they want. Pressing the Down arrow key lets the object drop. When three or more objects of
 the same type are positioned together, they form a group that is removed from the drop zone, adding some number of points to the player&#39;s score. The strategic part of the game is to try to build groups of four or five items, or to try to cause chain reactions
 where the removal of one group </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Santas-Gifts</link>
      <pubDate>Fri, 01 Dec 2006 09:42:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Santas-Gifts</guid>      
      <dc:creator>Larry Serflaten</dc:creator>
      <itunes:author>Larry Serflaten</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Santas-Gifts/RSS</wfw:commentRss>
      <category>events</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Kid’s Programming Language: Christmas Tree Shooter</title>
      <description><![CDATA[<span id="c4fmetadata">
<table class="" cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td class="" width="50">&nbsp;</td>
<td class=""><span class="entry_description">This article lights on a language called Kids Programming Language (KPL). This is a very easy language and especially made for people which are not the memeber of programers team. It mainly deals with games.</span></td>
</tr>
<tr>
<td class="" colspan="2">
<div class="entry_author">Walt Morrison and Jon Schwartz</div>
<div class="entry_company"><a></a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
1-3 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input">Phrogram</span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1127053/ChristmasTreeShooter_KPL.msi">Download</a>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p>Ho Ho Ho! Merry Christmas! Happy Holidays! Ho Ho Ho! Naughty or nice? We don't really want to know! Ho Ho Ho!</p>
<p>Have you seen the previous articles here at Coding4Fun about KPL, the <a href="http://www.kidsprogramminglanguage.com/">
Kid's Programming Language</a>? The <a href="http://msdn.microsoft.com/coding4fun/coolapplications/KPL/default.aspx">
overview</a> and the article on <a href="http://msdn.microsoft.com/coding4fun/gamedevelopment/KPL1/default.aspx">
KPL Pong</a>. KPL is not just for kids; it's for anyone who wants to code fun stuff fast. Proving the point, we're working on a couple of Holiday-themed KPL games and articles—like this one, ChristmasTreeShooter.kpl! We have a fun and easy suggestion for how
 you and family or friends can modify the game yourself, too. </p>
<p><img alt="" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/1127053/KPL-Xmas1_1.gif" border="0"></p>
<p>For some unknown reason, your Christmas tree is bobbing and weaving unpredictably before your eyes. It just won't hold still! And you have the rest of these ornaments that you
<i>have</i> to hang on the tree, or you can <i>forget</i> about opening that green box. You suspect it's got an
<a href="http://www.xbox.com/">Xbox 360</a> in it, and going with that theory, you're
<i>not</i> shaking it like the others. Just in case. Anyway, you do your best with the ornaments, and Santa rates your performance at the end. Not a guy you want to disappoint, coming down to that Christmas Eve wire...</p>
<p>This KPL game was implemented in 161 KPL instructions, and will be simple code for an experienced or hobbyist programmer to follow. It uses sprites for graphics and uses custom sound clips, which we're going to show you how to replace with your own voice-overs.
 What are friends or family going to say when it's <b>you</b> who rates their performance? Are you going to be deadpan and droll? Acerbic and insulting? Will you do a Santa voice, a Mrs. Claus voice or an Elf voice? However you record it, you know it'll be
 fun!</p>
<p>Chances are, if you're here at Coding4Fun, you're more than just a beginning programmer—but I bet you can think of some friends or family who might like to be a beginning programmer? Well, we made KPL for them—and you helping them learn with KPL should make
 it fun and easy for both of you. This game ought to catch their interest, but if they're a novice perhaps you can help them through the
<a href="http://www.ms-inc.net/Download.aspx?File=BeginningProgrammingWithKPL">Beginning Programming with KPL Tutorial</a> before you work with them on this or other KPL game code.</p>
<h2>Just the interesting stuff, please</h2>
<p>This article will assume some basic programming skill, and rather than explaining every line of code in the KPL program, will focus on key techniques or algorithms which will be useful as you develop your own KPL games:
</p>
<ul>
<li>Finding free images online<br>
<br>
</li><li>Using Sprites in KPL<br>
<br>
</li><li>Recording and using custom sounds<br>
<br>
</li><li>Using Arrays<br>
<br>
</li><li>Handling keyboard input<br>
<br>
</li><li>Sprite interaction<br>
<br>
</li><li>Allowing user customization of game behavior</li></ul>
<p>Before we begin, the article will make the most sense if you have installed KPL, and downloaded and unzipped the Christmas Tree Shooter program underneath your KPL install folder. The ideal way to start, of course, is to load ChristmasTreeShooter.kpl in
 the KPL IDE, click &quot;Run the program,&quot; and play it a few times before examining the code. <img src='http://ecn.channel9.msdn.com/o9/content/images/emoticons/emotion-1.gif?v=c9' alt='Smiley' /></p>
<p>KPL and this program are both available as freeware downloads from: <a href="http://www.kidsprogramminglanguage.com/download.htm">
http://www.kidsprogramminglanguage.com/download.htm</a>. KPL does have a dependency on the .NET Framework 1.1, and the KPL install will &quot;auto-magically&quot; download and install the Framework if it is not already installed on your machine.
</p>
<h2>Finding Free Images Online</h2>
<p>There are many many places online that offer free images that you can reuse in your own KPL programs. An
<a href="http://search.msn.com/results.aspx?q=christmas&#43;tree&#43;clipart&amp;FORM=QBHP">MSN Search for &quot;Christmas Tree Clipart&quot;</a> returned 589,677 search results when I ran it. Here's the page where we found our Xmas tree:</p>
<p><a href="http://www.geocities.com/~bug_hut/Christmas/trees.html">http://www.geocities.com/~bug_hut/Christmas/trees.html</a><u>
</u></p>
<p>That particular page is of interest because it's been viewed over 200,000 times—who'd have thought?!? And because it is the only web page I can think of using a background WAV file that I actually
<i>liked</i> hearing!</p>
<p>KPL supports images in all standard file formats, including GIF, JPG, PNG, TIF and BMP. KPL does support animated GIFs, but those are not used in our Christmas Tree Shooter. If you're using Internet Explorer, saving an image you find on the Web for reuse
 is easy: right-click the image, and select &quot;Save Picture As...&quot;. KPL will automatically find an image by file name if the image is in the Media\Images folder under the KPL installation folder; if you expect to use an image from more than one KPL program, this
 is the right place to put it. If an image is specific to the program you are working on, you can leave the image in the same folder as the .kpl program itself. KPL will find it in the local folder, looking there first before checking the Images folder.</p>
<p>Of course, the caveat about finding images online is making sure the site allows you to reuse the image. Image reuse happens all the time on the Web, but of course, if you find an image with a copyright or other usage limitation stated on the page, you will
 want to comply. There are many many freely usable images out there, so it's safest and simplest to keep looking until you find one with no strings attached.</p>
<h2>Using Sprites in KPL</h2>
<p>Here's a single method we coded that wraps the basic KPL sprite commands into one:</p>
<pre><code>Method LoadSizePlaceSprite(name As String, file As String, <br>                           scale As Decimal, x As Int, y As Int)<br>    LoadSprite( name, file ) <br>    ScaleSprite( name, scale )<br>    MoveSpriteToPoint( name, x, y )<br>    ShowSprite( name )    <br><br>End Method</code></pre>
<p>This allows a single call to load, place and display a sprite:</p>
<pre><code>LoadSizePlaceSprite(&quot;TREE&quot;, &quot;Christmas Tree3.png&quot;, 1.50, <br>                     TreeX, TreeY )</code></pre>
<p>The <b>name</b> parameter gives the sprite a name which you will use to refer to it when you manipulate the sprite.</p>
<p>The <b>file</b> parameter is the filename to the image file which will be used to represent the sprite on-screen. No path is required to the filename, but the file must be in the local folder with the .kpl program, or in KPL's Media\Images folder.</p>
<p>The <b>scale</b> parameter is a size multiplier for displaying the sprite. 1.0 is no size change, 0.5 is half size, etcâ€¦</p>
<p>The <b>x</b> and <b>y</b> parameters specify the screen location where the sprite will be displayed, in pixels, with the default being that the upper left corner of the window is location (0, 0).</p>
<p>KPL defaults all sprites to the same ZIndex of 0—all sprites are drawn or rendered on the same layer, so the last one drawn always appears &quot;on top.&quot;
<code>SetSpriteZIndex(name, ZIndex)</code> can be used to specify the ZIndex to control this. Sprites with a higher ZIndex will always be drawn on top of sprites with a lower ZIndex.</p>
<pre><code>SetSpriteZIndex(&quot;Ball&quot; &#43; BallCount, 10)</code></pre>
<p>Other Sprite-manipulating methods used in ChristmasTreeShooter.kpl are:</p>
<p><b>HideSprite()</b> takes the name of the sprite which is to be hidden when it is no longer needed:</p>
<pre><code>HideSprite(&quot;CrossH&quot;)</code></pre>
<p><b>GetSpriteHeight() </b>and<b> GetSpriteWidth()</b> return a height or width in pixels of the sprite:</p>
<pre><code>GetSpriteHeight( &quot;CrossH&quot; )</code></pre>
<p><b>SpritesIntersect()</b> takes the name of two sprites, and returns true only if they intersect or overlap on the screen:</p>
<pre><code>If SpritesIntersect(&quot;TREE&quot;, &quot;Ball&quot; &#43; OrnamentCount) Then</code></pre>
<p>That's all the Sprite code used in ChristmasTreeShooter.kpl. We have designed KPL to be as simple and as highly leveraged as possible, and this is particularly visible in KPL support for Sprites.</p>
<h2>Recording and using custom sounds</h2>
<p>This KPL program uses custom sounds for Santa's rating of your performance at the end of the game. As with images, sound files can be placed in the same folder as the program if they are used only for the program. If you'd like to share the sounds across
 more than one program, they can be placed into the Media\Sounds folder underneath KPL's install folder.</p>
<p>The sounds used for the game were recorded using the Sound Recorder, which is available as part of all versions of Windows. You can launch it from Start Menu &gt; All Programs &gt; Accessories &gt; Entertainment &gt; Sound Recorder, or by running sndrec32.exe from the
 Start &gt; Run... dialog. If you've been a geek long enough, that file name will remind you of the good (?!?) old days. Not only of 32-bit Windows, but of 8-character MSDOS file names. Amazing thing is, that really wasn't very long ago. <img src='http://ecn.channel9.msdn.com/o9/content/images/emoticons/emotion-1.gif?v=c9' alt='Smiley' /></p>
<p>The File menu and the tape-deck style button bar are all of the Sound Recorder that you'll need to use. KPL currently supports .WAV file formats. We're adding support for more sound formats—as well as the ability to play multiple, layered sounds—to KPL v
 2, which is targeted for a January 2006 release. Any other program which allows recording or editing supported sound files can be used instead of the Sound Recorder, or course.</p>
<p>So, here's a fun, easy customization: use Sound Recorder to record and save your own version of the following sound files in place of ours! Here are our sounds and their scripts:</p>
<p><b>HoHoILikeIt.wav</b>: &quot;Ho Ho Ho! I like it!&quot;</p>
<p><b>HoHoTryAgain.wav</b>: &quot;Ho Ho Ho! Try again!&quot;</p>
<p>You can, of course, say anything you like, and/or give your recordings a different name. If you do use a different name, you'll need to change the following lines of KPL code to match:</p>
<pre><code>If HitCount = 5 Then<br>    PlaySound( &quot;HoHoILikeIt.wav&quot; )<br>Else<br>    PlaySound( &quot;HoHoTryAgain.wav&quot; )</code></pre>
<p><code>End If</code></p>
<h2>Using Arrays in KPL</h2>
<p>KPL does support the use of arrays, as well as user-defined structures. KPL v 2 will add support for user-defined classes—an ideal way to encapsulate logic such as the handling of our Christmas tree ornaments. Until then, we kept this simple by using arrays
 to handle the five of them:</p>
<pre><code>Define BallX As Int[5]<br>Define BallY As Int[5]</code></pre>
<p><code>Define BallOffset As Int[5]</code></p>
<p>And here is an example from the program showing the use of these arrays:</p>
<pre><code>    BallOffset[OrnamentCount] = BallX[OrnamentCount] - TreeX </code></pre>
<h2>Handling keyboard input</h2>
<p>A simple model for coding a game in KPL is a large loop which, at a controlled interval, processes user input and game events. Here is our Method
<b>Main(),</b> which shows how this loop is the basis of the processing for the program:</p>
<pre><code>Method Main()<br>    SetupGame()<br>        <br>    // Show Instructions    <br>    Alert(&quot;Use the Arrow keys to move the shooter and tap the <br>           Space Bar to place an ornament. Placing an ornament <br>           on another will break both!&quot;, &quot;How to play!&quot;) <br><br>    Define CurrentTime As Decimal <br>    Define TimeLastChecked As Decimal<br>    <br>    // Start the wait time for the Space Bar to prevent the Key <br>    // Bounce effect     <br>    LastOrnamentFireTime = TickCount()<br><br>    While GameOver = False<br>    <br>        CurrentTime = TickCount()    <br>        <br>        // If 60 milliseconds have not passes since the last <br>        // time we checked, we don't do anything yet.<br>        If CurrentTime - TimeLastChecked &gt; 60 Then <br>            // Every 60 milliseconds (that's 17 times a <br>            // second!) we fall into this block.<br>            // First we process Key events to move the<br>            // targeting circle        <br>            ProcessKeyEvents()<br>            // Then we MoveTheTree.<br>            MoveTheTree()<br>            // We reset the timer each time, so we wait <br>            // another 60 milliseconds before moving again.<br>            TimeLastChecked = CurrentTime<br>        End If<br>        <br>    End While<br>    <br>    GameOverShowTree()<br>  <br>End Method</code></pre>
<p>The actual processing of key events is done in the <b>ProcessKeyEvents()</b> method, using the
<b>IsKeyDown()</b> function:</p>
<pre><code>    If IsKeyDown( &quot;Up&quot; ) Then<br>        If CrossHY &gt; 10 Then<br>            CrossHY = CrossHY - CrossHairSpeed<br>        End If<br><br>End If</code></pre>
<p>The key processing code checks for all keys that are relevant to targeting movement, and will handle any and all keys that are down. It also uses logic as shown above so that keys which would cause the targeting circle to move off the viewable screen are
 ignored.</p>
<p>One issue caused by processing keys in a loop this way results from the fact that the computer loop can be so much faster than our own fingers on the keyboard, which can result in processing the KeyDown more than once on a single tap of the Space Bar. When
 the single Space Bar keystroke is as important to the game as it is here, we must add a little extra code which makes sure we don't process that Space Bar keystroke more than once. The following code, at the bottom of the
<b>ProcessKeyEvents()</b> method, does this using the global variable <code>LastOrnamentFireTime</code>:</p>
<pre><code>// Process the wait time for the Space Key to reduce the Key <br>// Bounce Effect.  If it's been less than 200 milliseconds...<br>currentTime = TickCount()<br>If (currentTime - LastOrnamentFireTime) &lt; PlayerOrnamentFireDelay Then<br>    Return // Exit the method without processing<br>End If<br>If IsKeyDown( &quot;Space&quot; ) Then<br>    LastOrnamentFireTime = currentTime<br>    ShootOrnament()<br><br>End If</code></pre>
<h2>Sprite interaction</h2>
<p>What you are attempting to do with this game, of course, if place each of the five ornaments onto the bobbing and weaving Christmas tree, without breaking them. Since the tree and the ornaments are all implemented as sprites in this KPL program, this is
 as easy as checking to see whether the sprites &quot;intersect&quot; when you hit the spacebar to place an ornament. The code for this is in method<b> ShootOrnament()</b>:</p>
<pre><code>If SpritesIntersect(&quot;TREE&quot;, &quot;Ball&quot; &#43; OrnamentCount) Then<br>    PlaySound( HitSound )    <br>    // if we hit the tree count it and show it<br>    HitCount = HitCount &#43; 1<br>    // calculate the ornament offset<br>    BallOffset[OrnamentCount] = BallX[OrnamentCount] - TreeX <br>Else<br>    // if we miss the tree all together don't count or show ornament<br>    PlaySound( BreakSound )    <br>    HideSprite(&quot;Ball&quot; &#43; OrnamentCount)    <br><br>End If</code></pre>
<p>Note that if we actually got the ornament on the tree, we figure out its Offset so we can later move it along with the tree. And if we miss the tree altogether, the bulb breaks and is not shown.</p>
<p>These ornaments are those fragile little glass balls—proof that guys have no business decorating Christmas trees, right?!? If we actually shoot one glass ball on top of another, well, they both break, Santa is less than pleased, and we might never get to
 open that green box! Here are the nested <b>For...Next</b> loops that check for this:</p>
<pre><code>For Ornaments = 1 To OrnamentCount<br>    If Ornaments &lt; OrnamentCount Then<br>        For OtherOrnaments = (Ornaments &#43; 1) To OrnamentCount<br>            // Process balls hitting balls, don't count them and <br>            // don't show them<br>            If SpritesIntersect(&quot;Ball&quot; &#43; Ornaments, &quot;Ball&quot; &#43; <br>                                 OtherOrnaments) Then<br>                PlaySound( OrnamentHit )<br>                HideSprite(&quot;Ball&quot; &#43; Ornaments)<br>                HideSprite(&quot;Ball&quot; &#43; OtherOrnaments)<br>                HitCount = HitCount - 2<br>            End If<br>        Next<br>    End If<br>Next</code></pre>
<p>Besides nested loops always being fun exercises of logic, this is interesting because it shows how easy it can be to use an automatic type conversion to build a string from a number. Our sprites are named Ball1 to Ball5, and when we need to process them
 in a loop this way, we can simply construct the name by concatenating &quot;Ball&quot; &#43; Ornaments, where the latter is the integer loop index.</p>
<h2>Allowing user customization of game behavior</h2>
<p>Besides being educational, open-source KPL games have the advantage of allowing a user to change or customize the game behavior. The entire game and all its code is there for the user's modification, but it's also worth putting a little thought and effort
 into allowing easy customization of the behavior of your game. Our Christmas Tree Shooter does this with three global variables, defined, commented and changeable up at the top of the program file:</p>
<pre><code>// Set these next 3 variables to affect game play<br>Define CrossHairSpeed As Int = 20<br>Define TreeSpeed As Int = 20<br>// how many times the tree will move before game is over<br><br>Define MoveCount As Int = 2 // = once to the right, once to the left</code></pre>
<p>Good naming and comments make this pretty easy for users to find and change. The two speed variables can be tweaked to make the game easier or harder, depending on the user's reflexes. And the move count can be increased to lengthen the game and allow the
 user more time.</p>
<p>Building in game settings based on global variables like this just takes a little thought, and can allow a fun extra level of control for people playing your game.</p>
<h2>What's next?</h2>
<p>Two or three other Holiday-themed KPL games should also be up on the Coding4Fun site. Have fun with them, and Happy Holidays—no matter which particular Holiday you're celebrating at this time of year!</p>
<p>KPL Asteroids is also next in the series of retro games implemented with KPL—watch for that in the next couple of weeks!</p>
<p>There are now dozens of open source KPL games, and dozens more educational programs—either included in the base KPL install, or new and separately downloadable. Check them all out at
<a href="http://www.kidsprogramminglanguage.com/download.htm">http://www.kidsprogramminglanguage.com/download.htm</a>.</p>
<p>Moral of the story? Coding4Fun isn't just a name—it's the point!</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/holiday/RSS&WT.dl=0&WT.entryid=Entry:RSSView:e1c85d2eb93540c5b3f49e7600d7cc72">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Christmas-Tree-Shooter</comments>
      <itunes:summary>



&amp;nbsp;
This article lights on a language called Kids Programming Language (KPL). This is a very easy language and especially made for people which are not the memeber of programers team. It mainly deals with games.



Walt Morrison and Jon Schwartz


Difficulty: Intermediate
Time Required: 
1-3 hours
Cost: Free
Software: Phrogram
Hardware: 
Download: Download






Ho Ho Ho! Merry Christmas! Happy Holidays! Ho Ho Ho! Naughty or nice? We don&#39;t really want to know! Ho Ho Ho! 
Have you seen the previous articles here at Coding4Fun about KPL, the 
Kid&#39;s Programming Language? The 
overview and the article on 
KPL Pong. KPL is not just for kids; it&#39;s for anyone who wants to code fun stuff fast. Proving the point, we&#39;re working on a couple of Holiday-themed KPL games and articles—like this one, ChristmasTreeShooter.kpl! We have a fun and easy suggestion for how
 you and family or friends can modify the game yourself, too.  
 
For some unknown reason, your Christmas tree is bobbing and weaving unpredictably before your eyes. It just won&#39;t hold still! And you have the rest of these ornaments that you
have to hang on the tree, or you can forget about opening that green box. You suspect it&#39;s got an
Xbox 360 in it, and going with that theory, you&#39;re
not shaking it like the others. Just in case. Anyway, you do your best with the ornaments, and Santa rates your performance at the end. Not a guy you want to disappoint, coming down to that Christmas Eve wire... 
This KPL game was implemented in 161 KPL instructions, and will be simple code for an experienced or hobbyist programmer to follow. It uses sprites for graphics and uses custom sound clips, which we&#39;re going to show you how to replace with your own voice-overs.
 What are friends or family going to say when it&#39;s you who rates their performance? Are you going to be deadpan and droll? Acerbic and insulting? Will you do a Santa voice, a Mrs. Claus voice or an Elf voice? However you record it, you know it&#39;ll be
 fun! 
Chance</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Christmas-Tree-Shooter</link>
      <pubDate>Thu, 23 Nov 2006 05:39:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Christmas-Tree-Shooter</guid>      
      <dc:creator>Walt Morrison </dc:creator>
      <itunes:author>Walt Morrison </itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Kids-Programming-Language-Christmas-Tree-Shooter/RSS</wfw:commentRss>
      <category>events</category>
      <category>Holiday</category>
    </item>    
</channel>
</rss>